| 标题 | wren-lang wren main-branch Buffer Overflow |
|---|
| 描述 | ### Description
We discovered a Global-buffer-overflow vulnerability in the Wren compiler. The crash occurs in the emitOp function when it attempts to access the global stackEffects array using an invalid or out-of-bounds opcode index.
The ASAN report indicates a READ violation of size 4, occurring exactly 4 bytes after the end of the global stackEffects array.
### Environment
- OS: Linux x86_64
- Complier: Clang
- Build Configuration: Release mode with ASan enabled.
### Vulnerability Details
- Target: Wren (wren-lang)
- Vulnerability Type: CWE-125: Out-of-bounds Read
- Function: emitOp
- Location: src/vm/wren_compiler.c:1329
- Global Variable: stackEffects (defined at src/vm/wren_compiler.c:414)
- Root Cause Analysis: The function emitOp likely uses the passed instruction (opcode) as an index to lookup stack adjustments:
```
// Example code in emitOp
int effect = stackEffects[instruction];
```
The ASAN report shows the read happens at 0x55ab9c6f8558, which is 4 bytes after the 308-byte stackEffects array. This implies that the compiler attempted to emit an instruction with an ID corresponding to MAX_OPCODES (or one slot past the valid range), causing the array index out-of-bounds read.
The call stack points to subscript -> callSignature -> emitShortArg -> emitOp. This suggests the issue arises when compiling a subscript/method call that requires a 16-bit argument (Extended Opcode), but the opcode calculation is incorrect.
### Reproduce
1. Build wren and harness with Release optimization and ASAN enabled.
<details>
<summary>harness.c</summary>
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wren.h"
void writeFn(WrenVM* vm, const char* text) {
}
void errorFn(WrenVM* vm, WrenErrorType type, const char* module, int line, const char* message) {
}
int main(int argc, char** argv) {
if (argc < 2) return 1;
FILE* f = fopen(argv[1], "rb");
if (!f) return 1;
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char* buffer = (char*)malloc(length + 1);
if (!buffer) {
fclose(f);
return 1;
}
if (fread(buffer, 1, length, f) != (size_t)length) {
free(buffer);
fclose(f);
return 1;
}
buffer[length] = '\0';
fclose(f);
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = writeFn;
config.errorFn = errorFn;
WrenVM* vm = wrenNewVM(&config);
WrenInterpretResult result = wrenInterpret(vm, "main", buffer);
wrenFreeVM(vm);
free(buffer);
return 0;
}
```
</details>
2. Run with the crashing [file](https://github.com/oneafter/0122/blob/main/i1219/repro):
```
./bin/harness repro
```
<details>
<summary>ASAN report</summary>
```
==8453==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55a049c3f558 at pc 0x55a049bd9ca7 bp 0x7ffdd6dd1190 sp 0x7ffdd6dd1188
READ of size 4 at 0x55a049c3f558 thread T0
#0 0x55a049bd9ca6 in emitOp /src/wren/projects/make/../../src/vm/wren_compiler.c:1329:25
#1 0x55a049bd9ca6 in emitShortArg /src/wren/projects/make/../../src/vm/wren_compiler.c:1355:3
#2 0x55a049bc554b in callSignature /src/wren/projects/make/../../src/vm/wren_compiler.c:1984:3
#3 0x55a049bc554b in subscript /src/wren/projects/make/../../src/vm/wren_compiler.c:2532:3
#4 0x55a049be16ba in parsePrecedence /src/wren/projects/make/../../src/vm/wren_compiler.c:2855:5
#5 0x55a049be16ba in expression /src/wren/projects/make/../../src/vm/wren_compiler.c:2863:3
#6 0x55a049be16ba in bareName /src/wren/projects/make/../../src/vm/wren_compiler.c:2313:5
#7 0x55a049bd536c in parsePrecedence /src/wren/projects/make/../../src/vm/wren_compiler.c:2849:3
#8 0x55a049bd536c in expression /src/wren/projects/make/../../src/vm/wren_compiler.c:2863:3
#9 0x55a049beeaa3 in statement /src/wren/projects/make/../../src/vm/wren_compiler.c:3266:5
#10 0x55a049bd5d7b in definition /src/wren/projects/make/../../src/vm/wren_compiler.c:3764:5
#11 0x55a049bcf03d in wrenCompile /src/wren/projects/make/../../src/vm/wren_compiler.c:3815:7
#12 0x55a049bbbaa3 in compileInModule /src/wren/projects/make/../../src/vm/wren_vm.c:484:15
#13 0x55a049bbaf26 in wrenCompileSource /src/wren/projects/make/../../src/vm/wren_vm.c:1538:25
#14 0x55a049bbaf26 in wrenInterpret /src/wren/projects/make/../../src/vm/wren_vm.c:1517:25
#15 0x55a049bafca5 in main /src/wren/fuzz_wren.c:51:34
#16 0x7efc834031c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#17 0x7efc8340328a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#18 0x55a049ace5c4 in _start (/src/wren/bin/fuzz_wren+0x365c4) (BuildId: 5d78be029a4b6a34067ee0d0f65b83b8780504cc)
0x55a049c3f558 is located 4 bytes after global variable 'stackEffects' defined in '/src/wren/projects/make/../../src/vm/wren_compiler.c:414' (0x55a049c3f420) of size 308
SUMMARY: AddressSanitizer: global-buffer-overflow /src/wren/projects/make/../../src/vm/wren_compiler.c:1329:25 in emitOp
Shadow bytes around the buggy address:
0x55a049c3f280: f9 f9 f9 f9 00 03 f9 f9 00 00 01 f9 f9 f9 f9 f9
0x55a049c3f300: 00 00 07 f9 f9 f9 f9 f9 00 00 00 07 f9 f9 f9 f9
0x55a049c3f380: 00 00 00 02 f9 f9 f9 f9 00 00 00 00 02 f9 f9 f9
0x55a049c3f400: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
0x55a049c3f480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x55a049c3f500: 00 00 00 00 00 00 00 00 00 00 04[f9]f9 f9 f9 f9
0x55a049c3f580: f9 f9 f9 f9 00 00 00 00 07 f9 f9 f9 02 f9 f9 f9
0x55a049c3f600: 06 f9 f9 f9 06 f9 f9 f9 06 f9 f9 f9 00 01 f9 f9
0x55a049c3f680: 05 f9 f9 f9 06 f9 f9 f9 05 f9 f9 f9 00 02 f9 f9
0x55a049c3f700: 00 03 f9 f9 00 00 01 f9 f9 f9 f9 f9 00 02 f9 f9
0x55a049c3f780: 05 f9 f9 f9 06 f9 f9 f9 07 f9 f9 f9 00 01 f9 f9
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==8453==ABORTING
```
</details> |
|---|
| 来源 | ⚠️ https://github.com/wren-lang/wren/issues/1219 |
|---|
| 用户 | Oneafter (UID 92781) |
|---|
| 提交 | 2026-02-18 14時45分 (2 月前) |
|---|
| 管理 | 2026-02-28 15時50分 (10 days later) |
|---|
| 状态 | 已接受 |
|---|
| VulDB条目 | 348272 [wren-lang wren 直到 0.4.0 src/vm/wren_compiler.c emitOp 信息公开] |
|---|
| 积分 | 20 |
|---|