fix(qwen36): refuse loudly on a failed encode-buffer realloc - #1588
Conversation
|
Reviewed, and this one should go in. The unchecked growth reallocs are a real defect on a path fed by the network, the test injects a genuine allocation failure rather than reading the code, it forks so the refusal is observed as an exit code and a message instead of taking the test process with it, and It needs a rebase first, and the conflict is small. What landed is #1557 ( There is a trap in resolving it that is worth naming, because the obvious resolution is wrong in a way make will not complain about. The conflict markers fall like this: The recipe line, the (tabs, not spaces, on both recipe lines.) I applied exactly that against current dev and built and ran both: So after the rebase there is nothing else to change. Once it is pushed the CI needs an approval from us because it is your first PR here, and I will start it. |
Integrazione dev + JustVugg#1582 auto-tier VRAM + JustVugg#1580 build Windows CUDA + JustVugg#1588 + tetto RAM_GB qwen36
push_id and bpe_piece grow their token-id/BPE-symbol buffers with a bare realloc() and no NULL check, so an allocation failure under memory pressure overwrote the buffer pointer with NULL and the very next store wrote through it. Both are reached from encode_text on every inference request's prompt text (serve_one -> encode_text -> push_id/bpe_piece). qwen38.c's push_id/bpe_piece already guard this exact growth pattern (q38_encode_realloc / q38_encode_oom); qwen36.c never got the equivalent fix. This mirrors the project's established OOM-guard idiom (checked realloc, fprintf to stderr, exit(1)) used in st.h for the JustVugg#798 defect class. Adds tests/test_qwen36_encode_oom.c, which injects a real allocation failure via the shadow-realloc technique from tests/test_798_guards.c and asserts both call sites exit(1) with a message instead of crashing on the NULL write; verified red (SIGSEGV in the forked child) against the unpatched function before this fix, green after.
4c43286 to
d548042
Compare
Summary
push_idandbpe_pieceinqwen36.cgrow their token-id/BPE-symbol buffers with a barerealloc()and no NULL check. On allocation failure the buffer pointer is overwritten with NULL and the very next store ((*ids)[(*n)++]=v;/syms[sc++]=d;) writes through it. Both are reached fromencode_texton every inference request's prompt text (serve_one->encode_text->push_id/bpe_piece).qwen38.calready guards this exact pattern in its ownpush_id/bpe_piece(q38_encode_realloc/q38_encode_oom);qwen36.cnever got the equivalent fix. This applies the same OOM-guard idiom already established forst.hin the #798 defect class: checked realloc,fprintfto stderr naming the buffer,exit(1).Validation
make -C c checkmake -C c cuda-test(if applicable) -- n/a, no CUDA touchedAdded
tests/test_qwen36_encode_oom.c, which injects a real allocation failure via the shadow-realloc technique already used bytests/test_798_guards.c, and asserts both call sites exit(1) with a message instead of crashing on the NULL write. Verified red (the forked child SIGSEGVs) against the unpatched function before this change, green after.Compatibility
Found via a static-analysis pass (cppcheck) against
origin/dev, cross-checked by hand against the source and againstqwen38.c's existing fix for the identical pattern.