diff --git a/src/util/rbs_allocator.c b/src/util/rbs_allocator.c index 2a3f17076..51fee5d8d 100644 --- a/src/util/rbs_allocator.c +++ b/src/util/rbs_allocator.c @@ -39,15 +39,24 @@ typedef struct rbs_allocator_page { size_t used; } rbs_allocator_page_t; +// Normalize a raw page size to a safe value for payload_size subtraction. +// Falls back to 4096 when the raw value is <= 0 or smaller than the page +// header struct, preventing underflow in rbs_allocator_init. +// Internal API, intentionally omitted from the public header. +size_t rbs_allocator_normalize_page_size(long raw) { + if (raw <= 0) return 4096; + size_t page_size = (size_t) raw; + if (page_size <= sizeof(rbs_allocator_page_t)) return 4096; + return page_size; +} + static size_t get_system_page_size(void) { #ifdef _WIN32 SYSTEM_INFO si; GetSystemInfo(&si); - return si.dwPageSize; + return rbs_allocator_normalize_page_size((long) si.dwPageSize); #else - long sz = sysconf(_SC_PAGESIZE); - if (sz == -1) return 4096; // Fallback to the common 4KB page size - return (size_t) sz; + return rbs_allocator_normalize_page_size(sysconf(_SC_PAGESIZE)); #endif } diff --git a/wasm/rbs_wasm.c b/wasm/rbs_wasm.c index 14697d43f..efe9a609c 100644 --- a/wasm/rbs_wasm.c +++ b/wasm/rbs_wasm.c @@ -399,7 +399,19 @@ __attribute__((export_name("rbs_wasm_lex"))) int rbs_wasm_lex(const char *source * * @return 1 if the sample parsed successfully, 0 otherwise. */ +// Internal: defined in rbs_allocator.c, not declared in the public header. +extern size_t rbs_allocator_normalize_page_size(long raw); + __attribute__((export_name("rbs_wasm_selftest"))) int rbs_wasm_selftest(void) { + // Regression test: normalize_page_size must return a safe value + // (>= sizeof(rbs_allocator_page_t)) for inputs that would underflow + // payload_size. On WASI in a Rust cdylib, sysconf(_SC_PAGESIZE) + // returns 0; the normalization must catch that. + if (rbs_allocator_normalize_page_size(-1) != 4096) return 0; + if (rbs_allocator_normalize_page_size(0) != 4096) return 0; + if (rbs_allocator_normalize_page_size(1) != 4096) return 0; + if (rbs_allocator_normalize_page_size(65536) != 65536) return 0; + static const char source[] = "class User\n" " attr_reader name: String\n"