Repository navigation
Conversation
Signed-off-by: obsidian_nomad <abdul@sproutxp.com>
|
Do you have an example of the Antlr4 Tool generating a corrupt ATN? |
|
No, the tool itself emits well-formed ATNs, so this isn't about a corrupt blob coming out of the ANTLR tool. The concern is the deserializer treating the serialized stream as trusted input: state, rule, and edge indices are read straight from the bytes and used as unchecked operator[] offsets, so a corrupted or hand-crafted ATN (anything not produced by the tool) drives an out-of-bounds read that then gets dereferenced and written through. Java stays memory-safe on the same bytes because List.get/array access throw IndexOutOfBounds; only the C++ port has UB there. It's straightforward to trigger with a minimal malformed blob. For example {4,0,0,0,1,100} (version 4, one non-greedy state numbered 100 against an empty states vector) reaches downCast<DecisionState*>(atn->states[100]) and segfaults under AddressSanitizer at ATNDeserializer.cpp:321; a second case with an edge target of 9 hits the same pattern in edgeFactory. The gtest in the PR constructs those blobs directly, so it fails under ASan against the current code and passes after switching those 17 sites to at(). Happy to fold that repro into the PR description if that's useful. |
The C++ ATN deserializer indexes its state and rule tables with numbers read straight from the serialized data, using unchecked vector
operator[]:ATNState*out of bounds, then dereferences and writes through it (->nonGreedy = true,->isLeftRecursiveRule = true, ...)ruleToStopState[state->ruleIndex]is an out-of-bounds heap write when a state carries a rule index past the rule countIndexOutOfBoundson the same input; only the C++ port has undefined behavior at these sitesSwitched those accesses to
at()so a corrupt ATN throwsstd::out_of_rangebefore any out-of-bounds access. Valid grammars deserialize unchanged. Added a gtest underruntime/teststhat reproduces the fault (it segfaults under AddressSanitizer against the current code and passes after the change).