ww driver: enumeratedir grows past 256 entries

The wwstage driver silently dropped directory entries past a 256
cap; the cstage twin already grows by realloc-doubling. Grow the
same way (seed 8, double) so both stages agree on any directory size.
This commit is contained in:
2026-06-13 04:37:47 +09:00
parent f7845057a7
commit 4dc8459a90
4 changed files with 221 additions and 22 deletions

View File

@@ -3199,9 +3199,13 @@ fn bytecmp(a: *u8, alen: u64, b: *u8, blen: u64) i32 = {
fn enumeratedir(dirpath: *u8) (**u8, i32) = {
let fd: i32 = os.open(pathstr(dirpath), os.flag.RDONLY, 0i32);
if (fd < 0) { return nil: **u8, 0; };
let maxnames: i32 = 256;
let names: []*u8 = alloc([], maxnames: u64)!;
let nlens: []u64 = alloc([], maxnames: u64)!;
// #65: grow-dynamic (mirror cstage enumerate_dir_ww realloc-doubling,
// cmd/ww/main.c:209). The old fixed 256-name cap silently dropped every
// eligible file past it, diverging the combined.ww from cstage on a
// module dir with >256 sources.
let cap: i32 = 8;
let names: []*u8 = alloc([], cap: u64)!;
let nlens: []u64 = alloc([], cap: u64)!;
let n: i32 = 0;
let buf: []u8 = alloc([], 8192u64)!;
buf.len = 8192;
@@ -3216,15 +3220,27 @@ fn enumeratedir(dirpath: *u8) (**u8, i32) = {
let nm: *u8 = buf.ptr + off + 19u64;
let nl: u64 = cstrlen(nm);
if (dirfilekeep(nm, nl)) {
if (n < maxnames) {
let cp: []u8 = alloc([], nl + 1u64)!;
let i: u64 = 0u64;
for (i < nl) { cp[i] = nm[i]; i += 1u64; };
cp[nl] = 0u8;
names[n] = cp.ptr;
nlens[n] = nl;
n += 1;
if (n >= cap) {
let ncap: i32 = cap * 2;
let nn: []*u8 = alloc([], ncap: u64)!;
let nl2: []u64 = alloc([], ncap: u64)!;
let k: i32 = 0;
for (k < n) {
nn[k] = names[k];
nl2[k] = nlens[k];
k += 1;
};
names = nn;
nlens = nl2;
cap = ncap;
};
let cp: []u8 = alloc([], nl + 1u64)!;
let i: u64 = 0u64;
for (i < nl) { cp[i] = nm[i]; i += 1u64; };
cp[nl] = 0u8;
names[n] = cp.ptr;
nlens[n] = nl;
n += 1;
};
off += reclen;
};

View File

@@ -361,9 +361,13 @@ fn bytecmp(a: *u8, alen: u64, b: *u8, blen: u64) i32 = {
fn enumeratedir(dirpath: *u8) (**u8, i32) = {
let fd: i32 = os.open(pathstr(dirpath), os.flag.RDONLY, 0i32);
if (fd < 0) { return nil: **u8, 0; };
let maxnames: i32 = 256;
let names: []*u8 = alloc([], maxnames: u64)!;
let nlens: []u64 = alloc([], maxnames: u64)!;
// #65: grow-dynamic (mirror cstage enumerate_dir_ww realloc-doubling,
// cmd/ww/main.c:209). The old fixed 256-name cap silently dropped every
// eligible file past it, diverging the combined.ww from cstage on a
// module dir with >256 sources.
let cap: i32 = 8;
let names: []*u8 = alloc([], cap: u64)!;
let nlens: []u64 = alloc([], cap: u64)!;
let n: i32 = 0;
let buf: []u8 = alloc([], 8192u64)!;
buf.len = 8192;
@@ -378,15 +382,27 @@ fn enumeratedir(dirpath: *u8) (**u8, i32) = {
let nm: *u8 = buf.ptr + off + 19u64;
let nl: u64 = cstrlen(nm);
if (dirfilekeep(nm, nl)) {
if (n < maxnames) {
let cp: []u8 = alloc([], nl + 1u64)!;
let i: u64 = 0u64;
for (i < nl) { cp[i] = nm[i]; i += 1u64; };
cp[nl] = 0u8;
names[n] = cp.ptr;
nlens[n] = nl;
n += 1;
if (n >= cap) {
let ncap: i32 = cap * 2;
let nn: []*u8 = alloc([], ncap: u64)!;
let nl2: []u64 = alloc([], ncap: u64)!;
let k: i32 = 0;
for (k < n) {
nn[k] = names[k];
nl2[k] = nlens[k];
k += 1;
};
names = nn;
nlens = nl2;
cap = ncap;
};
let cp: []u8 = alloc([], nl + 1u64)!;
let i: u64 = 0u64;
for (i < nl) { cp[i] = nm[i]; i += 1u64; };
cp[nl] = 0u8;
names[n] = cp.ptr;
nlens[n] = nl;
n += 1;
};
off += reclen;
};