Skip to content

[Bug] Heap-use-after-free in delete_reference (called by destroy_vertex) during cell redefinition #982

@oneafter

Description

@oneafter

Description

We discovered a Heap-use-after-free vulnerability in sc-im. The crash occurs during the file parsing process when the application attempts to destroy a graph vertex, likely due to a cell redefinition.

The ASAN report indicates that delete_reference attempts to read from a memory region that was just freed in the same parser action (yyparse).

Environment

  • OS: Linux x86_64
  • Complier: Clang
  • Build Configuration: Release mode with ASan enabled.

Vulnerability Details

  • Target: sc-im
  • Vulnerability Type: CWE-416: Use After Free
  • Function: delete_reference
  • Location: src/graph.c:434 (called from src/graph.c:387)
  • Root Cause Analysis: The crash happens when parsing a file with repeated let assignments to the same cell (e.g., let A4 = ...).
  1. The parser (gram.y:456) handles the cleanup of the previous cell definition.
  2. The stack trace shows that free is called at gram.y:456, and destroy_vertex is also called from gram.y:456.
  3. It appears the code frees the vertex structure before calling destroy_vertex (or destroy_vertex accesses members of an already freed struct).
  4. Specifically, destroy_vertex calls delete_reference, which tries to access members of the freed vertex to remove back-references, triggering the UAF.

Reproduce

  1. Build sc-im with Release optimization and ASAN enabled.
  2. Run with the crashing file:
poc
leftst1:
let A4 = @avg(A1:B2)
let A4 = @avg(A1:A3)
let A2 = ?"t
let A4 =r
./src/sc-im --nocurses --quit_afterload poc.sc

ASAN report

==43739==ERROR: AddressSanitizer: heap-use-after-free on address 0x504000000270 at pc 0x55a595657e9a bp 0x7ffd8129eb20 sp 0x7ffd8129eb18
READ of size 8 at 0x504000000270 thread T0
    #0 0x55a595657e99 in delete_reference /src/sc-im/src/graph.c:434:31
    #1 0x55a595657e99 in destroy_vertex /src/sc-im/src/graph.c:387:12
    #2 0x55a595640315 in yyparse /src/sc-im/src/gram.y:456:146
    #3 0x55a595617f3b in readfile /src/sc-im/src/file.c:901:36
    #4 0x55a59562fabf in load_tbl /src/sc-im/src/file.c:2287:37
    #5 0x55a59562f5b6 in load_file /src/sc-im/src/file.c:2248:5
    #6 0x55a595686e04 in main /src/sc-im/src/main.c:285:9
    #7 0x7f353e9551c9  (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
    #8 0x7f353e95528a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
    #9 0x55a595526ba4 in _start (/src/sc-im/src/sc-im+0x4eba4) (BuildId: a0e0444e0e3f03f87f10e6f4f651691f85705c2c)

0x504000000270 is located 32 bytes inside of 48-byte region [0x504000000250,0x504000000280)
freed by thread T0 here:
    #0 0x55a5955c673a in free (/src/sc-im/src/sc-im+0xee73a) (BuildId: a0e0444e0e3f03f87f10e6f4f651691f85705c2c)
    #1 0x55a595640315 in yyparse /src/sc-im/src/gram.y:456:146
    #2 0x55a595617f3b in readfile /src/sc-im/src/file.c:901:36
    #3 0x55a59562fabf in load_tbl /src/sc-im/src/file.c:2287:37
    #4 0x55a59562f5b6 in load_file /src/sc-im/src/file.c:2248:5

previously allocated by thread T0 here:
    #0 0x55a5955c69d3 in malloc (/src/sc-im/src/sc-im+0xee9d3) (BuildId: a0e0444e0e3f03f87f10e6f4f651691f85705c2c)
    #1 0x55a5956538a7 in GraphAddVertex /src/sc-im/src/graph.c:130:39
    #2 0x55a59567b0dd in let /src/sc-im/src/interp.c:1551:9

SUMMARY: AddressSanitizer: heap-use-after-free /src/sc-im/src/graph.c:434:31 in delete_reference
Shadow bytes around the buggy address:
  0x503fffffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x504000000000: fa fa 00 00 00 00 00 05 fa fa fd fd fd fd fd fa
  0x504000000080: fa fa 00 00 00 00 06 fa fa fa 00 00 00 00 01 fa
  0x504000000100: fa fa 00 00 00 00 01 fa fa fa 00 00 00 00 03 fa
  0x504000000180: fa fa 00 00 00 00 00 00 fa fa fd fd fd fd fd fd
=>0x504000000200: fa fa fd fd fd fd fd fd fa fa fd fd fd fd[fd]fd
  0x504000000280: fa fa 00 00 00 00 00 00 fa fa 00 00 00 00 00 00
  0x504000000300: fa fa fd fd fd fd fd fa fa fa 00 00 00 00 00 fa
  0x504000000380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x504000000400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x504000000480: 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
==43739==ABORTING

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