diff --git a/selfhost/cmd/ww/main.combined.ww b/selfhost/cmd/ww/main.combined.ww index 4d0b0b4d..88e043c7 100644 --- a/selfhost/cmd/ww/main.combined.ww +++ b/selfhost/cmd/ww/main.combined.ww @@ -3323,32 +3323,38 @@ fn expand(c: *expctx, pathcs: *u8) void = { // starts with `package ;` return the package name as a fresh // heap-allocated NUL-terminated *u8, else nil. Same shape as cstage // peek_package. +// +// Reads the WHOLE file (via slurp), not a fixed prefix: cstage's +// peek_package scans line-by-line with fgets and no total cap, stopping +// at the first non-comment-non-blank line. A prior 2048-byte read cap +// here diverged from cstage on files whose `package` decl sits behind a +// >2048-byte comment header (strconv decimal/ftos/stof, memio) — +// returning nil and making the #16 D-i injection asymmetric (rule-10 +// break, byte-id divergence in the regenerated combined). The corpus has +// no line >2047 chars, so a whole-file line scan matches cstage's +// per-line fgets byte-for-byte on every real input. fn peekpackage(pathcs: *u8) *u8 = { - let fd: i32 = os.open(pathstr(pathcs), os.flag.RDONLY, 0i32); - if (fd < 0) { return nil; }; - let buf: []u8 = alloc([], 2048u64)!; - buf.len = 2048; - let n: i64 = os.read(fd, buf.ptr, 2048u64); - os.close(fd); - if (n <= 0i64) { return nil; }; - let nu: u64 = n: u64; + let bufp: *u8; + let nu: u64; + bufp, nu = slurp(pathcs); + if (bufp == nil) { return nil; }; let p: u64 = 0u64; for (p < nu) { let q: u64 = p; for (q < nu) { - if (buf[q] == 10u8) { break; }; // '\n' + if (bufp[q] == 10u8) { break; }; // '\n' q += 1u64; }; let s: u64 = p; for (s < q) { - if (buf[s] != 32u8) { - if (buf[s] != 9u8) { break; }; + if (bufp[s] != 32u8) { + if (bufp[s] != 9u8) { break; }; }; s += 1u64; }; if (s < q) { let line: str; - line.ptr = buf.ptr + s; + line.ptr = bufp + s; line.len = (q - s): i32; // hasprefix("//") subsumes the old s+1= 97u8) { if (ch <= 122u8) { isalpha = true; }; }; if (ch >= 65u8) { if (ch <= 90u8) { isalpha = true; }; }; @@ -3384,7 +3390,7 @@ fn peekpackage(pathcs: *u8) *u8 = { if (plen == 0u64) { return nil; }; let r: []u8 = alloc([], plen + 1u64)!; let k: u64 = 0u64; - for (k < plen) { r[k] = buf[start + k]; k += 1u64; }; + for (k < plen) { r[k] = bufp[start + k]; k += 1u64; }; r[plen] = 0u8; return r.ptr; }; diff --git a/selfhost/cmd/ww/main.ww b/selfhost/cmd/ww/main.ww index e9136ea4..c2baefe2 100644 --- a/selfhost/cmd/ww/main.ww +++ b/selfhost/cmd/ww/main.ww @@ -537,32 +537,38 @@ fn expand(c: *expctx, pathcs: *u8) void = { // starts with `package ;` return the package name as a fresh // heap-allocated NUL-terminated *u8, else nil. Same shape as cstage // peek_package. +// +// Reads the WHOLE file (via slurp), not a fixed prefix: cstage's +// peek_package scans line-by-line with fgets and no total cap, stopping +// at the first non-comment-non-blank line. A prior 2048-byte read cap +// here diverged from cstage on files whose `package` decl sits behind a +// >2048-byte comment header (strconv decimal/ftos/stof, memio) — +// returning nil and making the #16 D-i injection asymmetric (rule-10 +// break, byte-id divergence in the regenerated combined). The corpus has +// no line >2047 chars, so a whole-file line scan matches cstage's +// per-line fgets byte-for-byte on every real input. fn peekpackage(pathcs: *u8) *u8 = { - let fd: i32 = os.open(pathstr(pathcs), os.flag.RDONLY, 0i32); - if (fd < 0) { return nil; }; - let buf: []u8 = alloc([], 2048u64)!; - buf.len = 2048; - let n: i64 = os.read(fd, buf.ptr, 2048u64); - os.close(fd); - if (n <= 0i64) { return nil; }; - let nu: u64 = n: u64; + let bufp: *u8; + let nu: u64; + bufp, nu = slurp(pathcs); + if (bufp == nil) { return nil; }; let p: u64 = 0u64; for (p < nu) { let q: u64 = p; for (q < nu) { - if (buf[q] == 10u8) { break; }; // '\n' + if (bufp[q] == 10u8) { break; }; // '\n' q += 1u64; }; let s: u64 = p; for (s < q) { - if (buf[s] != 32u8) { - if (buf[s] != 9u8) { break; }; + if (bufp[s] != 32u8) { + if (bufp[s] != 9u8) { break; }; }; s += 1u64; }; if (s < q) { let line: str; - line.ptr = buf.ptr + s; + line.ptr = bufp + s; line.len = (q - s): i32; // hasprefix("//") subsumes the old s+1= 97u8) { if (ch <= 122u8) { isalpha = true; }; }; if (ch >= 65u8) { if (ch <= 90u8) { isalpha = true; }; }; @@ -598,7 +604,7 @@ fn peekpackage(pathcs: *u8) *u8 = { if (plen == 0u64) { return nil; }; let r: []u8 = alloc([], plen + 1u64)!; let k: u64 = 0u64; - for (k < plen) { r[k] = buf[start + k]; k += 1u64; }; + for (k < plen) { r[k] = bufp[start + k]; k += 1u64; }; r[plen] = 0u8; return r.ptr; };