| Title | albertodemichelis squirrel master-branch Uncontrolled Recursion |
|---|
| Description | ### Description
We discovered a Stack-overflow vulnerability in the Squirrel compiler. The crash occurs when parsing a script containing a deeply nested sequence of unary operators (e.g., !!!!!!...).
The ASAN report shows an extremely deep recursion chain involving Factor, PrefixedExpr, and UnaryOP, eventually exhausting the stack and triggering a crash in SQLexer::Lex.
### Environment
- OS: Linux x86_64
- Complier: Clang
- Build Configuration: Release mode with ASan enabled.
### Vulnerability Details
- Target: Squirrel (squirrel-lang)
- Vulnerability Type: CWE-674: Uncontrolled Recursion
- Function: SQCompiler::Factor / SQCompiler::UnaryOP
- Location: squirrel/sqcompiler.cpp:863 (recurses to PrefixedExpr)
- Root Cause Analysis: The parser handles unary operators recursively.
```
// Example logic in sqcompiler.cpp
void SQCompiler::Factor() {
if (IsUnaryOp(token)) {
UnaryOP(op);
// UnaryOP calls PrefixedExpr, which calls Factor again
} ...
}
```
The PoC likely contains a long chain of unary operators (e.g., logical NOT ! or negation -). The compiler recurses for each operator without a depth limit check, leading to stack exhaustion.
### Reproduce
1. Build squirrel with Release optimization and ASAN enabled.
2. Run with the crashing [file](https://github.com/oneafter/0122/blob/main/i312/repro):
```
./build/bin/sq repro
```
<details>
<summary>ASAN report</summary>
```
==77839==ERROR: AddressSanitizer: stack-overflow on address 0x7fff82031f60 (pc 0x7f6744d053a8 bp 0x7fff82032390 sp 0x7fff82031f60 T0)
#0 0x7f6744d053a8 in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:718
#1 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#2 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#3 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#4 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#5 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#6 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#7 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#8 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#9 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#10 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#11 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#12 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#13 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#14 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#15 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#16 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#17 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#18 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#19 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#20 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#21 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#22 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#23 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#24 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#25 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#26 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#27 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#28 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#29 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#30 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#31 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#32 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#33 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#34 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#35 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#36 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#37 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#38 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#39 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#40 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#41 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#42 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#43 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#44 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#45 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#46 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#47 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#48 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#49 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#50 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#51 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#52 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#53 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#54 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#55 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#56 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#57 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#58 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#59 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#60 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#61 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#62 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#63 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#64 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#65 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#66 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#67 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#68 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#69 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#70 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#71 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#72 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#73 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#74 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#75 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#76 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#77 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#78 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#79 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#80 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#81 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#82 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#83 0x7f6744d0bbec in SQCompiler::UnaryOP(SQOpcode) /src/squirrel/squirrel/sqcompiler.cpp:907:9
#84 0x7f6744d06a5a in SQCompiler::Factor() /src/squirrel/squirrel/sqcompiler.cpp:863:13
#85 0x7f6744d03a0b in SQCompiler::PrefixedExpr() /src/squirrel/squirrel/sqcompiler.cpp:618:25
#86 0x7f6744d0bbec |
|---|
| Source | ⚠️ https://github.com/albertodemichelis/squirrel/issues/312 |
|---|
| User | Oneafter (UID 92781) |
|---|
| Submission | 02/18/2026 14:49 (2 months ago) |
|---|
| Moderation | 02/28/2026 15:53 (10 days later) |
|---|
| Status | Accepted |
|---|
| VulDB entry | 348274 [Squirrel up to 3.2 squirrel/sqcompiler.cpp UnaryOP recursion] |
|---|
| Points | 20 |
|---|