prism icon indicating copy to clipboard operation
prism copied to clipboard

Out-of-bounds read in parser_lex_magic_comment

Open stevenjohnstone opened this issue 3 weeks ago • 1 comments

On 1da0733f147ed0a4547791576db53c04780cd498, compile and run testcase.c below to see an out-of-bounds read:

// testcase.c
#include <prism.h>

/*
00000000: 2330 2020 3a22 2020 20                   #0  :"
*/

uint8_t input[] = {
  0x23, 0x30, 0x20, 0x20, 0x3a, 0x22, 0x20, 0x20, 0x20
};

int main(int argc, const char **argv) {
    (void)argc;
    (void)argv;
    pm_parse_success_p(input, sizeof(input), NULL);
    return 0;
}
$ clang -Iinclude $(find src -name "*.c") -ggdb3 testcase.c -fsanitize=address -o testcase
$ ./testcase
=================================================================
==315==ERROR: AddressSanitizer: global-buffer-overflow on address 0xaaaadacba4e9 at pc 0xaaaadab10b3c bp 0xffffedbe2010 sp 0xffffedbe2008
READ of size 1 at 0xaaaadacba4e9 thread T0
    #0 0xaaaadab10b38 in parser_lex_magic_comment /prism/src/prism.c:8446:17
    #1 0xaaaadaaf8ca0 in parser_lex /prism/src/prism.c:10756:26
    #2 0xaaaadaaf3364 in parse_program /prism/src/prism.c:22582:5
    #3 0xaaaadaaf3188 in pm_parse /prism/src/prism.c:23015:12
    #4 0xaaaadaaf4188 in pm_parse_success_p /prism/src/prism.c:23132:23
    #5 0xaaaadabfe434 in main /prism/testcase.c:14:5
    #6 0xffff8a2e73fc in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #7 0xffff8a2e74d4 in __libc_start_main csu/../csu/libc-start.c:392:3
    #8 0xaaaada9a302c in _start (/prism/testcase+0x5302c) (BuildId: 4c7d9b6907377a5562c1c5abc735c0746255a118)

0xaaaadacba4e9 is located 0 bytes after global variable 'input' defined in '/prism/testcase.c:7' (0xaaaadacba4e0) of size 9
SUMMARY: AddressSanitizer: global-buffer-overflow /prism/src/prism.c:8446:17 in parser_lex_magic_comment
Shadow bytes around the buggy address:
  0xaaaadacba200: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0xaaaadacba280: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0xaaaadacba300: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0xaaaadacba380: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0xaaaadacba400: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
=>0xaaaadacba480: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 00[01]f9 f9
  0xaaaadacba500: f9 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 00
  0xaaaadacba580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0xaaaadacba600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0xaaaadacba680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0xaaaadacba700: 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
==315==ABORTING

stevenjohnstone avatar Nov 25 '25 18:11 stevenjohnstone

diff --git a/src/prism.c b/src/prism.c
index 186cdd35..3d6cd3e2 100644
--- a/src/prism.c
+++ b/src/prism.c
@@ -8443,7 +8443,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
                 if (*cursor == '\\' && (cursor + 1 < end)) cursor++;
             }
             value_end = cursor;
-            if (*cursor == '"') cursor++;
+            if (cursor < end && *cursor == '"') cursor++;
         } else {
             value_start = cursor;
             while (cursor < end && *cursor != '"' && *cursor != ';' && !pm_char_is_whitespace(*cursor)) cursor++;

seems to fix the issue.

stevenjohnstone avatar Nov 25 '25 18:11 stevenjohnstone