Lexer::setInputStream calls reset() before updating _input, leading to use-after-free when reusing lexer across multiple statements
Environment
- ANTLR 4.13.2 C++ runtime
- Compiler: g++ 13.2.0, C++23
- OS: Ubuntu (Linux)
Summary
In antlr4::Lexer::setInputStream(IntStream *input), the current implementation calls reset() before updating the member _input:
void Lexer::setInputStream(IntStream *input) {
reset(); // <-- reset accesses the old _input
_input = input;
}If the old input stream has already been destroyed (or becomes invalid) before setInputStream is called, reset() will perform operations on a dangling pointer — typically _input->seek(0) — causing a use-after-free and potential crash.
Use Case Where the Bug Manifests
We are building a SQL parser SDK that reuses a single Lexer object to parse multiple independent SQL statements (handle pooling for performance). For each statement we call lexer->setInputStream(&newInput) to attach the new SQL text. The old ANTLRInputStream from the previous statement is a temporary object that has already been destroyed by the time setInputStream is invoked. This reliably triggers the use-after-free inside reset().
Source: antlr/antlr4