From d1160ca5d1ed170322e6a170fd685f81edd736d1 Mon Sep 17 00:00:00 2001 From: dimgigov Date: Tue, 2 Jun 2026 01:31:18 +0300 Subject: [PATCH] Fix critical segfault: add bounds checking to parser diag buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The self-hosted compiler crashed with SIGSEGV when processing files that generated >=256 parser diagnostics (e.g. truncated source files). The parser allocated a fixed-size diag buffer of 256 entries, but parserExpect, parserExpectIdentOrKeyword, and parserEmitDiag wrote into it without checking bounds. Once diagCount exceeded 256, writes overflowed into adjacent heap objects (Decl structs), corrupting their kind/childDecl2 fields and causing crashes during AST traversal. This fix adds bounds checks to all three sites so excess diagnostics are silently dropped rather than corrupting memory. The file size threshold (7037 vs 7062 bytes) was a red herring — it determined how many parser errors were generated before EOF. Closes: selfhost segfault on 250+ line files --- src_bux/parser.bux | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src_bux/parser.bux b/src_bux/parser.bux index 310131e..878367a 100644 --- a/src_bux/parser.bux +++ b/src_bux/parser.bux @@ -78,10 +78,12 @@ func parserExpect(p: *Parser, kind: int, msg: String) -> LexToken { return parserAdvance(p); } let tok: LexToken = parserCurToken(p); - p.diags[p.diagCount] = ParserDiag { - line: tok.line, column: tok.column, message: msg - }; - p.diagCount = p.diagCount + 1; + if p.diagCount < 256 { + p.diags[p.diagCount] = ParserDiag { + line: tok.line, column: tok.column, message: msg + }; + p.diagCount = p.diagCount + 1; + } return tok; } @@ -103,10 +105,12 @@ func parserExpectIdentOrKeyword(p: *Parser, msg: String) -> LexToken { if tok.kind == tkIdent || parserIsKeyword(tok.kind) { return parserAdvance(p); } - p.diags[p.diagCount] = ParserDiag { - line: tok.line, column: tok.column, message: msg - }; - p.diagCount = p.diagCount + 1; + if p.diagCount < 256 { + p.diags[p.diagCount] = ParserDiag { + line: tok.line, column: tok.column, message: msg + }; + p.diagCount = p.diagCount + 1; + } return tok; }