I found a bug in the RustPython compiler.
Sometimes, for some reason, the internal symbol_table_stack becomes completely empty. Then the compiler tries to take an item out of that stack using .expect("compiler bug"). That means if the stack is empty, the whole RustPython process will crash. And that's exactly what happens.
I ran a specific test – the test is called assert_without_message_raises_class_directly. When that test runs, the compiler crashes and shows this error:
thread 'compile::tests::assert_without_message_raises_class_directly' (23444) panicked at crates\codegen\src\compile.rs:1016:39:
compiler bug
stack backtrace:
0: std::panicking::panic_handler
1: core::panicking::panic_fmt
2: core::panicking::panic_display
3: core::option::expect_failed
This is wrong. The compiler should never crash like this. Even if its internal state gets corrupted, it should log an error or show a proper Python-style error (like "Internal compiler error, please report"), but it should not kill the whole process.
My environment
Windows 11
Rust stable
Latest RustPython main branch
I reproduced this crash on my own machine.
What I expect
When this situation happens, the compiler should NOT panic. It should have a fallback – for example, create a dummy scope, print an error message, and continue. It should not stop.
Steps to reproduce
- Clone the RustPython repository.
- Run this command:
cargo test -p rustpython-codegen -- --nocapture
- The test mentioned above will fail and show the panic.
Proposed fix
This way the compiler won't crash – it will just create a dummy scope and keep going. If there are any real errors, they will show up later.
In the file crates/codegen/src/compile.rs, around line 1016, there is this line:
let parent_scope = self.symbol_table_stack.pop().expect("compiler bug");
Change it to something like this:
let parent_scope = match self.symbol_table_stack.pop() {
Some(scope) => scope,
None => {
log::error!("Compiler bug: popped empty symbol table stack. Creating dummy scope.");
SymbolTable::new(ScopeType::Function, None)
}
};
I found a bug in the RustPython compiler.
Sometimes, for some reason, the internal
symbol_table_stackbecomes completely empty. Then the compiler tries to take an item out of that stack using.expect("compiler bug"). That means if the stack is empty, the whole RustPython process will crash. And that's exactly what happens.I ran a specific test – the test is called
assert_without_message_raises_class_directly. When that test runs, the compiler crashes and shows this error:thread 'compile::tests::assert_without_message_raises_class_directly' (23444) panicked at crates\codegen\src\compile.rs:1016:39:
compiler bug
stack backtrace:
0: std::panicking::panic_handler
1: core::panicking::panic_fmt
2: core::panicking::panic_display
3: core::option::expect_failed
This is wrong. The compiler should never crash like this. Even if its internal state gets corrupted, it should log an error or show a proper Python-style error (like "Internal compiler error, please report"), but it should not kill the whole process.
My environment
Windows 11
Rust stable
Latest RustPython main branch
I reproduced this crash on my own machine.
What I expect
When this situation happens, the compiler should NOT panic. It should have a fallback – for example, create a dummy scope, print an error message, and continue. It should not stop.
Steps to reproduce
cargo test -p rustpython-codegen -- --nocaptureProposed fix
This way the compiler won't crash – it will just create a dummy scope and keep going. If there are any real errors, they will show up later.
In the file
crates/codegen/src/compile.rs, around line 1016, there is this line: