jgm/peg-markdown

Heap buffer overflow in the yySet function

danielpyon opened this issue · 0 comments

Problem Description

Note: I am aware that this project is unmaintained. However, I am still opening this issue to follow CVE's guidelines for EOL software.

There is a heap buffer overflow in the yySet function when the parser handles a specially crafted Markdown file. In particular, there's an out-of-bounds write to the heap left redzone, which is part of the heap header metadata.

Here is a minimized proof-of-concept Markdown file that triggers the bug: min_heap_overflow.md. The output is as follows:

=================================================================
==3241393==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x611000000280 at pc 0x0000004c6a36 bp 0x7fffffffe0c0 sp 0x7fffffffe0b8
WRITE of size 8 at 0x611000000280 thread T0
    #0 0x4c6a35 in yySet /home/sanic/peg-markdown/markdown_parser.c:288:80
    #1 0x5d45a1 in yyDone /home/sanic/peg-markdown/markdown_parser.c:255:7
    #2 0x5d45a1 in yyparsefrom /home/sanic/peg-markdown/markdown_parser.c:6736:13
    #3 0x5de691 in parse_markdown /home/sanic/peg-markdown/parsing_functions.c:112:5
    #4 0x5dca1c in markdown_to_g_string /home/sanic/peg-markdown/markdown_lib.c:157:14
    #5 0x5dce84 in markdown_to_string /home/sanic/peg-markdown/markdown_lib.c:175:11
    #6 0x4c4d06 in main /home/sanic/peg-markdown/markdown.c:180:11
    #7 0x7ffff7b25082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
    #8 0x41c50d in _start (/home/sanic/peg-markdown/markdown+0x41c50d)

0x611000000280 is located 0 bytes to the right of 256-byte region [0x611000000180,0x611000000280)
allocated by thread T0 here:
    #0 0x494c4d in malloc (/home/sanic/peg-markdown/markdown+0x494c4d)
    #1 0x5d4164 in yyparsefrom /home/sanic/peg-markdown/markdown_parser.c:6729:31

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/sanic/peg-markdown/markdown_parser.c:288:80 in yySet
Shadow bytes around the buggy address:
  0x0c227fff8000: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c227fff8010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c227fff8020: 00 00 00 00 00 00 00 04 fa fa fa fa fa fa fa fa
  0x0c227fff8030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c227fff8040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c227fff8050:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff80a0: 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
==3241393==ABORTING

Reproduction Steps

  1. Compile the project using ASAN (Address Sanitizer). For example, CC=afl-clang-fast AFL_USE_ASAN=1 make.
  2. Run ./markdown -x min_heap_overflow.md (use the proof-of-concept file attached to this report).
  3. Observe the heap buffer overflow in the output.