#4969·antlr4

Lexer::setInputStream calls reset() before updating _input, leading to use-after-free when reusing lexer across multiple statements

Author: xiangy6Created Aug 10, 2026Updated Aug 10, 2026

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:

cpp
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().