Route the 16 routable bare-primsize GUARD sites (is-primitive / struct-vs-prim dispatch) through the #101 aliasprimsize SSoT helper. Byte-NEUTRAL by construction: an alias-narrow name is already neutralized downstream by the same arm, so routing emits no new asm (the empty-flip-set ken oracled). Shape-A exclude-prim-early (3): cgenutil sretretsize / structparamsize / structfloatclass — `primsize>0 return` then structlookup→nil returns the same value; route returns it early, same. Shape-B prim-guard-then-structlookup (13): cgenutil 4604/4650 + cgenexpr 4136/10244 + the 9-site CALL/assign cluster — primsize==0 →structlookup→nil→fall to normal; route skips the block→same normal. Install the peellint bare-primsize FINALE (B7 lint-fuse contract): tools/peellint now rejects any bare primsize() in the ww stage outside the annotated whitelist. Evasion-hardened per the B7 lesson — a character scan (comments + string/char literals stripped first) and a LEFT+RIGHT word-bounded match of the bare `primsize` TOKEN (not just `primsize(`), so the aliasprimsize() wrapper is never a hit and every compiling spelling reds: the call primsize(nm), the paren-wrap (primsize)(nm), the function-value bind `let p = primsize`, and any line-split. ww-only (the C stage dealiases via type_chase_named, no primsize symbol). Two independent exemption windows (peel-ok vs primsize-ok) so neither rule blinds the other. Runs as a make-test dep. Whitelist the 6 designed exemptions with primsize-ok WHY-annotations: machinery — aliasprimsize body (SSoT chase) | typenodeprimresolved + exprprimresolved (#11/#33 prim-resolver chasers) | cgcast leaf-loop + cgenexpr #11 deref-store (own ps==0 fallback; route would regress #11) | the primsize oracle/definition itself (nothing below to chase). structural — elemsizeof x2 + paramfieldsize (chase lives in the -c twin elemsizeofc; threading c is the dormant #110). Empty-flip-set proof: zero C bytes; cstage binaries bit-identical; bootstrap byte-id 990-997 + 950 all green (w6c == w6c_ww on the full selfhost, self-rebuild identical); combined.ww (w6c + wwdump) regen idempotent; sizelint 0; peellint 0 (raw-peel AND bare-primsize over the whole tree = the close-by-construction proof, zero unwhitelisted survivors). Tests: 944_peellint_gate +14 rows (bare / space-before-paren / name-at-EOL split / string-blind opener / paren-wrap / fn-value-bind RED; aliasprimsize wrapper + primsize-ok annotated GREEN; corrupt annotation RED; independent peel/primsize windows; C-file out-of-scope). Closes the #101 primsize-alias family by construction. #109.
This commit is contained in:
@@ -22,6 +22,18 @@
|
||||
* `(*t).under`, ww `t. under`, and a string literal containing
|
||||
* a block-comment OPENER token that blinded the old regex
|
||||
* comment-strip for the rest of the file.
|
||||
* 6. RULE 2 (#101/#109) — bare primsize() in the ww stage is the
|
||||
* alias-blind width shape aliasprimsize() supersedes. A bare
|
||||
* `primsize(` REDS; the SSoT wrapper `aliasprimsize(` must NOT
|
||||
* (left word boundary); the evasion spellings (space-before-paren,
|
||||
* name-at-EOL line split, string-blind block-comment opener in a
|
||||
* literal, paren-wrap `(primsize)(nm)`, function-value bind
|
||||
* `let p = primsize` — the last two reviewer-109-found, both
|
||||
* compile + run) all RED; a
|
||||
* `primsize-ok` annotation exempts; a corrupted one does not; the
|
||||
* primsize-ok and peel-ok windows are independent (neither blinds
|
||||
* the other's shape); and a C-file `primsize(` is out of scope
|
||||
* (the C stage chases via type_chase_named, no primsize symbol).
|
||||
*
|
||||
* Scratch trees live under /tmp and exercise the lint via its ROOT
|
||||
* override (sizelint-style), so the real tree is never touched.
|
||||
@@ -159,6 +171,79 @@ static const struct lintrow lintrows[] = {
|
||||
{ "evade_c_string_blind", "cmd/w6c/x.c",
|
||||
"static const char *s = \"/*\";\n"
|
||||
"static Type *f(Type *t) { return t->under; }\n", 1 },
|
||||
/* RULE 2 (#101/#109): bare primsize() outside the chase is the
|
||||
* forbidden alias-blind width shape; aliasprimsize is the SSoT. */
|
||||
{ "prim_bare", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||
"\tlet z: i32 = primsize(nm);\n"
|
||||
"\treturn z;\n"
|
||||
"};\n", 1 },
|
||||
{ "prim_evade_spacing", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||
"\tlet z: i32 = primsize (nm);\n"
|
||||
"\treturn z;\n"
|
||||
"};\n", 1 },
|
||||
{ "prim_evade_linesplit", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||
"\tlet z: i32 = primsize\n"
|
||||
"\t (nm);\n"
|
||||
"\treturn z;\n"
|
||||
"};\n", 1 },
|
||||
{ "prim_evade_string_blind", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(c: *cgen) str = {\n"
|
||||
"\tlet s: str = \"/*\";\n"
|
||||
"\tlet z: i32 = primsize(s);\n"
|
||||
"\treturn s;\n"
|
||||
"};\n", 1 },
|
||||
/* review-109 evasions: both COMPILE + run (verified) yet slipped a
|
||||
* `primsize(`-only matcher — the token rule reds them. */
|
||||
{ "prim_evade_parenwrap", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||
"\tlet z: i32 = (primsize)(nm);\n"
|
||||
"\treturn z;\n"
|
||||
"};\n", 1 },
|
||||
{ "prim_evade_fnvalue", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||
"\tlet p = primsize;\n"
|
||||
"\treturn p(nm);\n"
|
||||
"};\n", 1 },
|
||||
/* aliasprimsize() is the SSoT wrapper — its `primsize` suffix must
|
||||
* NOT trip the left-word-bounded matcher (the central evasion). */
|
||||
{ "prim_alias_wrapper_ok", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||
"\tlet z: i32 = aliasprimsize(c, nm);\n"
|
||||
"\treturn z;\n"
|
||||
"};\n", 0 },
|
||||
{ "prim_annotated_ok", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||
"\t// primsize-ok: chase body\n"
|
||||
"\tlet z: i32 = primsize(nm);\n"
|
||||
"\treturn z;\n"
|
||||
"};\n", 0 },
|
||||
{ "prim_corrupt_annotation", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||
"\t// primsize-okk-corrupt: nope\n"
|
||||
"\tlet z: i32 = primsize(nm);\n"
|
||||
"\treturn z;\n"
|
||||
"};\n", 1 },
|
||||
/* the two exemption windows are independent: primsize-ok must not
|
||||
* blind an under-token peel, nor peel-ok a bare primsize. */
|
||||
{ "prim_window_no_cross_under", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(t: *tinfo) *tinfo = {\n"
|
||||
"\t// primsize-ok: must NOT exempt the under peel below\n"
|
||||
"\treturn t.under;\n"
|
||||
"};\n", 1 },
|
||||
{ "peel_window_no_cross_prim", "selfhost/cmd/wcc/x.ww",
|
||||
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||
"\t// peel-ok: must NOT exempt the primsize below\n"
|
||||
"\tlet z: i32 = primsize(nm);\n"
|
||||
"\treturn z;\n"
|
||||
"};\n", 1 },
|
||||
/* RULE 2 is ww-only: the C stage dealiases via type_chase_named and
|
||||
* has no primsize symbol — a C `primsize(` is not in scope. */
|
||||
{ "prim_c_file_out_of_scope", "cmd/w6c/x.c",
|
||||
"static int primsize(const char *n) { return 0; }\n"
|
||||
"int g(void) { return primsize(\"u8\"); }\n", 0 },
|
||||
};
|
||||
|
||||
int
|
||||
|
||||
Reference in New Issue
Block a user