Fix 5 crash bugs: stack overflow, NULL deref, unchecked mallocs in glm.c#183
Merged
Merged
Conversation
Five crash-class bugs found by static analysis, all in glm.c:
C1: forward_all (line ~2709) used a fixed stack buffer float row[8192] for
the final RMS norm. The config checker allows hidden_size up to 1<<20;
any model with hidden > 8192 would smash the stack. Every other hot path
in the file correctly uses falloc(D). Replaced with falloc(D) + free.
C2: read_arr (line ~3334) dereferenced json_get() return without a NULL
check. If ref_glm.json is missing 'prompt_ids' or 'full_ids', this is a
guaranteed NULL-pointer dereference / segfault. Added a NULL check that
returns NULL+0, and the caller in main() now validates the result.
C3: mux_submit (line ~3103) allocated tmp=malloc(maxctx*sizeof(int)) without
a NULL check, then passed it to tok_encode. OOM here writes through NULL.
Added a check matching the sibling allocations in the same function.
C4: serve_ctx_init (line ~3025) allocated s->hist without a NULL check, then
passed it to kv_disk_load which writes token IDs into it. Added a check
matching the falloc() pattern used by kv_alloc.
C5: rope_interleave (line ~896) used a fixed stack buffer float in[256] but
the config checker allows qk_rope up to 1<<16. Added a runtime bounds
check that exits with a clear message instead of silently overflowing.
GLM-5.2 qk_rope=64, well within bounds.
This was referenced Jul 14, 2026
JustVugg
added a commit
to dnnspaul/colibri
that referenced
this pull request
Jul 14, 2026
JustVugg
added a commit
to ZacharyZcR/colibri
that referenced
this pull request
Jul 14, 2026
…shboard decls (JustVugg#126), rope guard (JustVugg#183), COUPLE (JustVugg#176)
maxwell1500
added a commit
to maxwell1500/colibri
that referenced
this pull request
Jul 14, 2026
…locs, null derefs (JustVugg#183) Five crash-class bugs found by static analysis, all in glm.c: C1: forward_all (line ~2709) used a fixed stack buffer float row[8192] for the final RMS norm. The config checker allows hidden_size up to 1<<20; any model with hidden > 8192 would smash the stack. Every other hot path in the file correctly uses falloc(D). Replaced with falloc(D) + free. C2: read_arr (line ~3334) dereferenced json_get() return without a NULL check. If ref_glm.json is missing 'prompt_ids' or 'full_ids', this is a guaranteed NULL-pointer dereference / segfault. Added a NULL check that returns NULL+0, and the caller in main() now validates the result. C3: mux_submit (line ~3103) allocated tmp=malloc(maxctx*sizeof(int)) without a NULL check, then passed it to tok_encode. OOM here writes through NULL. Added a check matching the sibling allocations in the same function. C4: serve_ctx_init (line ~3025) allocated s->hist without a NULL check, then passed it to kv_disk_load which writes token IDs into it. Added a check matching the falloc() pattern used by kv_alloc. C5: rope_interleave (line ~896) used a fixed stack buffer float in[256] but the config checker allows qk_rope up to 1<<16. Added a runtime bounds check that exits with a clear message instead of silently overflowing. GLM-5.2 qk_rope=64, well within bounds. Co-authored-by: woolcoxm <13604288+woolcoxm@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Static analysis of
glm.cfound five crash-class bugs — stack buffer overflows, NULL pointer dereferences, and unchecked mallocs — all in code paths that run at startup or during serve. Each can crash the engine; none affect output correctness (they crash, they don't silently corrupt).Bugs fixed
C1: Stack buffer overflow in
forward_all(line ~2709)Why: The config checker (
CKRat line ~955) allowshidden_sizeup to1<<20, but the fixed stack buffer holds only 8192 floats (32 KB). Any model withhidden > 8192overflows the stack. Every other hot path in the file correctly usesfalloc(D)for this row — this was the one outlier. GLM-5.2 (D=6144) is safe today, but this is a latent crash for larger configs.C2: NULL dereference in
read_arr(line ~3334)Why:
json_getreturns NULL when the key is absent. The code immediately dereferencesa->len— guaranteed segfault. Called frommain()when loadingref_glm.jsonfor oracle validation. If the file is missingprompt_idsorfull_ids, the engine crashes instead of reporting the error. Added a NULL check + the caller now validates the result.C3: Unchecked malloc in
mux_submit(line ~3103)Why:
tmpis used immediately without a NULL check. The sibling allocations in the same function (rawat ~3260,tmpat ~3275) both check for NULL — this one was missed. On a 744B model, OOM is a real scenario.C4: Unchecked malloc for
s->histinserve_ctx_init(line ~3025)Why:
s->histis passed tokv_disk_loadwhich writes token IDs into it. NULL here writes through a null pointer. The adjacentkv_allocusesfallocwhich aborts cleanly; this path silently returns NULL.C5: Stack buffer overflow in
rope_interleave(line ~896)Why: The config checker allows
qk_ropeup to1<<16, but the local buffer holds 256 floats. A config withqk_rope > 256corrupts the stack. GLM-5.2 (qk_rope=64) is safe today. Added a runtime bounds check that fails cleanly instead of silently smashing the stack.Verification
make glm.exe ARCH=native(exit 0)make test-c)SNAP=glm52_i4 NGEN=2 PROMPT="hi" ./glm.exe 8loads and runs correctlyFiles changed
c/glm.c— 5 locations (20 insertions, 6 deletions)Based on
dev(6d3ed7e).