mirror of
https://github.com/brazilofmux/tinymux
synced 2026-08-13 00:23:11 -04:00
jit: ljust/rjust/center truncate when width < content (#772)
Found by the JIT differential fuzzer (random nested softcode, JIT vs interpreter). fun_ljust/fun_rjust/fun_center call centerjustcombo(..., bTrunc=true), which passes 1 to co_ljust/co_rjust/co_center → a too-wide string is truncated to the width. The rv64 blob wrappers co_ljust_wrap/co_rjust_wrap/co_center_wrap passed 0 (no truncation), so the JIT/DBT path returned the full string where the interpreter truncates: ljust(abcdef,3) interp: abc JIT (blob): abcdef rjust(abcdef,3) interp: abc JIT (blob): abcdef center(abcdef,3) interp: abc JIT (blob): abcdef (The padding case width > content already agreed, which is why the earlier flat audit missed this.) Change the final bTrunc arg from 0 to 1 in all three wrappers and rebuild the rv64 softlib blob. This also matches the interpreter's empty-string returns for width 0 and non-integer width: satoi→0 then truncate-to-0 → "". There is no host-side fold for these (hir_lower has no LJUST/RJUST/CENTER constant-fold), so the wrapper is the whole runtime path. Tests: add TC006 to ljust_fn/rjust_fn/center_fn asserting truncation (abcdef,3 → abc) plus width-0 and non-integer → "". Because these functions are not constant-folded, the JIT-compiled @if condition routes them through the tier2 blob wrappers, so the tests are genuinely fail-closed against this bug — verified by building the unfixed blob and confirming all three TC006 cases fail, then pass after the fix. Smoke (configured --enable-jit, runtime JIT confirmed active, tier2=872): 1086 / 0 failed / 0 crashes. Closes #772. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
26d28db4ad
commit
4fc70fa540
6 changed files with 71 additions and 9 deletions
Binary file not shown.
Binary file not shown.
|
|
@ -865,9 +865,12 @@ char *co_ljust_wrap(char *out, const char **fargs, int nfargs) {
|
|||
fill = (const unsigned char *)fargs[2];
|
||||
fill_len = rv64_slen(fargs[2]);
|
||||
}
|
||||
/* bTrunc=1: fun_ljust truncates when width < content (centerjustcombo
|
||||
* passes bTrunc=true). satoi→0 for width 0 / non-integer then truncates
|
||||
* to "", matching the interpreter's empty returns. See #772. */
|
||||
size_t n = co_ljust((unsigned char *)out,
|
||||
(const unsigned char *)fargs[0], len,
|
||||
(size_t)width, fill, fill_len, 0);
|
||||
(size_t)width, fill, fill_len, 1);
|
||||
out[n] = '\0';
|
||||
return out;
|
||||
}
|
||||
|
|
@ -884,9 +887,10 @@ char *co_rjust_wrap(char *out, const char **fargs, int nfargs) {
|
|||
fill = (const unsigned char *)fargs[2];
|
||||
fill_len = rv64_slen(fargs[2]);
|
||||
}
|
||||
/* bTrunc=1: see co_ljust_wrap above (#772). */
|
||||
size_t n = co_rjust((unsigned char *)out,
|
||||
(const unsigned char *)fargs[0], len,
|
||||
(size_t)width, fill, fill_len, 0);
|
||||
(size_t)width, fill, fill_len, 1);
|
||||
out[n] = '\0';
|
||||
return out;
|
||||
}
|
||||
|
|
@ -903,9 +907,10 @@ char *co_center_wrap(char *out, const char **fargs, int nfargs) {
|
|||
fill = (const unsigned char *)fargs[2];
|
||||
fill_len = rv64_slen(fargs[2]);
|
||||
}
|
||||
/* bTrunc=1: see co_ljust_wrap above (#772). */
|
||||
size_t n = co_center((unsigned char *)out,
|
||||
(const unsigned char *)fargs[0], len,
|
||||
(size_t)width, fill, fill_len, 0);
|
||||
(size_t)width, fill, fill_len, 1);
|
||||
out[n] = '\0';
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,11 +94,30 @@
|
|||
strmatch(center(X,7,-+), -+-X-+-)
|
||||
)=
|
||||
{
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Succeeded.;
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Succeeded.
|
||||
},
|
||||
{
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Failed (c2=[center(X,5,-+)] c3=[center(X,7,-+)]).
|
||||
}
|
||||
-
|
||||
#
|
||||
# Test Case #6 - Truncation when width < content (#772). fun_center passes
|
||||
# bTrunc=true, so a too-wide string is truncated; width 0 and non-integer
|
||||
# width collapse to empty. Previously untested. On the JIT/DBT blob
|
||||
# backend this also guards co_center_wrap.
|
||||
#
|
||||
&tr.tc006 test_center_fn=
|
||||
@if cand(
|
||||
strmatch(center(abcdef,3), abc),
|
||||
eq(strlen(center(abcdef,0)), 0),
|
||||
eq(strlen(center(abcdef,xyz)), 0)
|
||||
)=
|
||||
{
|
||||
@log smoke=TC006: center truncation. Succeeded.;
|
||||
@trig me/tr.done
|
||||
},
|
||||
{
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Failed (c2=[center(X,5,-+)] c3=[center(X,7,-+)]).;
|
||||
@log smoke=TC006: center truncation. Failed (t=[center(abcdef,3)] w0=[center(abcdef,0)] wx=[center(abcdef,xyz)]).;
|
||||
@trig me/tr.done
|
||||
}
|
||||
-
|
||||
|
|
|
|||
|
|
@ -90,11 +90,30 @@
|
|||
eq(strlen(ljust(123,11,-+)), 11)
|
||||
)=
|
||||
{
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Succeeded.;
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Succeeded.
|
||||
},
|
||||
{
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Failed.
|
||||
}
|
||||
-
|
||||
#
|
||||
# Test Case #6 - Truncation when width < content (#772). fun_ljust passes
|
||||
# bTrunc=true, so a too-wide string is truncated; width 0 and non-integer
|
||||
# width collapse to empty. Previously untested. On the JIT/DBT blob
|
||||
# backend this also guards co_ljust_wrap, which was the divergent path.
|
||||
#
|
||||
&tr.tc006 test_ljust_fn=
|
||||
@if cand(
|
||||
strmatch(ljust(abcdef,3), abc),
|
||||
eq(strlen(ljust(abcdef,0)), 0),
|
||||
eq(strlen(ljust(abcdef,xyz)), 0)
|
||||
)=
|
||||
{
|
||||
@log smoke=TC006: ljust truncation. Succeeded.;
|
||||
@trig me/tr.done
|
||||
},
|
||||
{
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Failed.;
|
||||
@log smoke=TC006: ljust truncation. Failed (t=[ljust(abcdef,3)] w0=[ljust(abcdef,0)] wx=[ljust(abcdef,xyz)]).;
|
||||
@trig me/tr.done
|
||||
}
|
||||
-
|
||||
|
|
|
|||
|
|
@ -90,11 +90,30 @@
|
|||
eq(strlen(rjust(123,11,-+)), 11)
|
||||
)=
|
||||
{
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Succeeded.;
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Succeeded.
|
||||
},
|
||||
{
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Failed.
|
||||
}
|
||||
-
|
||||
#
|
||||
# Test Case #6 - Truncation when width < content (#772). fun_rjust passes
|
||||
# bTrunc=true, so a too-wide string is truncated (to the leading chars);
|
||||
# width 0 and non-integer width collapse to empty. Previously untested.
|
||||
# On the JIT/DBT blob backend this also guards co_rjust_wrap.
|
||||
#
|
||||
&tr.tc006 test_rjust_fn=
|
||||
@if cand(
|
||||
strmatch(rjust(abcdef,3), abc),
|
||||
eq(strlen(rjust(abcdef,0)), 0),
|
||||
eq(strlen(rjust(abcdef,xyz)), 0)
|
||||
)=
|
||||
{
|
||||
@log smoke=TC006: rjust truncation. Succeeded.;
|
||||
@trig me/tr.done
|
||||
},
|
||||
{
|
||||
@log smoke=TC005: Vary string and width with '-+' fill. Failed.;
|
||||
@log smoke=TC006: rjust truncation. Failed (t=[rjust(abcdef,3)] w0=[rjust(abcdef,0)] wx=[rjust(abcdef,xyz)]).;
|
||||
@trig me/tr.done
|
||||
}
|
||||
-
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue