From 4dd08a4cdef5b1c42d9a2c19fc24412e97ef51d5 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 23 Jan 2026 07:33:05 -0600 Subject: [PATCH] Address #1702 with extra bounds check. The buffer overflow happened because we were creating many upvalue slots in the compiler without using them, along with some faulty logic that used the wrong length to check for the bitmap's bounds. --- src/core/compile.c | 3 ++- src/core/io.c | 2 +- src/mainclient/shell.c | 2 +- test/suite-corelib.janet | 7 ++++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/core/compile.c b/src/core/compile.c index 40d2c3e4..9f819a83 100644 --- a/src/core/compile.c +++ b/src/core/compile.c @@ -961,8 +961,9 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) { JANET_OUT_OF_MEMORY; } memcpy(chunks, scope->ua.chunks, sizeof(uint32_t) * numchunks); + /* fprintf(stderr, "slot chunks: %d, scope->ua.count: %d, numchunks: %d\n", slotchunks, scope->ua.count, numchunks); */ /* Register allocator preallocates some registers [240-255, high 16 bits of chunk index 7], we can ignore those. */ - if (scope->ua.count > 7) chunks[7] &= 0xFFFFU; + if (scope->ua.count > 7 && slotchunks > 7) chunks[7] &= 0xFFFFU; def->closure_bitset = chunks; } diff --git a/src/core/io.c b/src/core/io.c index 97668887..43996526 100644 --- a/src/core/io.c +++ b/src/core/io.c @@ -723,7 +723,7 @@ void janet_dynprintf(const char *name, FILE *dflt_file, const char *format, ...) va_start(args, format); JanetType xtype; Janet x; - if (name[0] == '\0') { /* Allow empty string to just use dflt_file directly */ + if (!name || name[0] == '\0') { /* Allow NULL or empty string to just use dflt_file directly */ x = janet_wrap_nil(); xtype = JANET_NIL; } else { diff --git a/src/mainclient/shell.c b/src/mainclient/shell.c index 010ea2e5..a6fa79ec 100644 --- a/src/mainclient/shell.c +++ b/src/mainclient/shell.c @@ -482,7 +482,7 @@ static void savehistory(void) { FILE *history_file = fopen(gbl_history_file, "wb"); for (int i = 0; i < gbl_history_count; i++) { if (gbl_history[i][0]) { /* Drop empty strings */ - janet_dynprintf("", history_file, "%j\n", janet_cstringv(gbl_history[i])); + janet_dynprintf(NULL, history_file, "%j\n", janet_cstringv(gbl_history[i])); } } fclose(history_file); diff --git a/test/suite-corelib.janet b/test/suite-corelib.janet index 02cdaaba..a3651cd2 100644 --- a/test/suite-corelib.janet +++ b/test/suite-corelib.janet @@ -202,5 +202,10 @@ (assert-no-error "def destructure splice works 2" (do (def (n) [(splice [])]) n)) (assert-no-error "var destructure splice works" (do (var [a] [;[1]]) a)) -(end-suite) +# Issue #1702 - fuzz case with upvalues +(each item [1 2 3] + # Generate a lot of upvalues (more than 224) + (def ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;out-buf @"") + (with-dyns [:out out-buf] 1)) +(end-suite)