Skip to content

heap buffer overflow in JS_ReadBigInt #1018

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
AlonZa opened this issue Apr 8, 2025 · 0 comments · Fixed by #1020
Closed

heap buffer overflow in JS_ReadBigInt #1018

AlonZa opened this issue Apr 8, 2025 · 0 comments · Fixed by #1020

Comments

@AlonZa
Copy link

AlonZa commented Apr 8, 2025

The Bug

There is a heap buffer overflow in JS_ReadBigInt.

ASAN Report

INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 2754686023
INFO: Loaded 1 modules   (80429 inline 8-bit counters): 80429 [0x562120666c40, 0x56212067a66d), 
INFO: Loaded 1 PC tables (80429 PCs): 80429 [0x56212067a670,0x5621207b4940), 
./fuzz: Running 1 inputs 1 time(s) each.
Running: crashes/crash-ef103fd58bb6424db6ffaaaf37565185b03705de
=================================================================
==3106495==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000038 at pc 0x56212032ce1a bp 0x7ffcd0006170 sp 0x7ffcd0006168
WRITE of size 4 at 0x602000000038 thread T0
    #0 0x56212032ce19 in JS_ReadBigInt /home/quickjs-ng/quickjs/quickjs.c:36348:19
    #1 0x5621201fb43a in JS_ReadObjectRec /home/quickjs-ng/quickjs/quickjs.c:37145:15
    #2 0x5621203292c5 in JS_ReadObjectTag /home/quickjs-ng/quickjs/quickjs.c:36775:15
    #3 0x5621201fb54b in JS_ReadObjectRec /home/quickjs-ng/quickjs/quickjs.c:37118:15
    #4 0x5621201f9ad4 in JS_ReadObject2 /home/quickjs-ng/quickjs/quickjs.c:37285:15
    #5 0x56212026e018 in JS_ReadObject /home/quickjs-ng/quickjs/quickjs.c:37300:12
    #6 0x56212026e018 in LLVMFuzzerTestOneInput /home/quickjs-ng/quickjs/fuzz.c:18:19
    #7 0x56212001e663 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/quickjs-ng/quickjs/fuzz+0x373663) (BuildId: baf1fe61c0160916b98321b4bbc75964be8ce411)
    #8 0x5621200083df in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/home/quickjs-ng/quickjs/fuzz+0x35d3df) (BuildId: baf1fe61c0160916b98321b4bbc75964be8ce411)
    #9 0x56212000e136 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/quickjs-ng/quickjs/fuzz+0x363136) (BuildId: baf1fe61c0160916b98321b4bbc75964be8ce411)
    #10 0x562120037f52 in main (/home/quickjs-ng/quickjs/fuzz+0x38cf52) (BuildId: baf1fe61c0160916b98321b4bbc75964be8ce411)
    #11 0x7f56e91c3d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #12 0x7f56e91c3e3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #13 0x562120002ca4 in _start (/home/quickjs-ng/quickjs/fuzz+0x357ca4) (BuildId: baf1fe61c0160916b98321b4bbc75964be8ce411)

0x602000000038 is located 0 bytes to the right of 8-byte region [0x602000000030,0x602000000038)
allocated by thread T0 here:
    #0 0x5621200bacde in malloc (/home/quickjs-ng/quickjs/fuzz+0x40fcde) (BuildId: baf1fe61c0160916b98321b4bbc75964be8ce411)
    #1 0x56212027b793 in js_def_malloc /home/quickjs-ng/quickjs/quickjs.c:1851:12
    #2 0x5621200f6b38 in js_malloc_rt /home/quickjs-ng/quickjs/quickjs.c:1451:11
    #3 0x5621202afad7 in js_malloc /home/quickjs-ng/quickjs/quickjs.c:1534:11
    #4 0x5621202afad7 in js_bigint_new /home/quickjs-ng/quickjs/quickjs.c:10786:9
    #5 0x56212032c579 in JS_ReadBigInt /home/quickjs-ng/quickjs/quickjs.c:36341:9
    #6 0x5621201fb43a in JS_ReadObjectRec /home/quickjs-ng/quickjs/quickjs.c:37145:15
    #7 0x5621203292c5 in JS_ReadObjectTag /home/quickjs-ng/quickjs/quickjs.c:36775:15
    #8 0x5621201fb54b in JS_ReadObjectRec /home/quickjs-ng/quickjs/quickjs.c:37118:15
    #9 0x5621201f9ad4 in JS_ReadObject2 /home/quickjs-ng/quickjs/quickjs.c:37285:15
    #10 0x56212026e018 in JS_ReadObject /home/quickjs-ng/quickjs/quickjs.c:37300:12
    #11 0x56212026e018 in LLVMFuzzerTestOneInput /home/quickjs-ng/quickjs/fuzz.c:18:19
    #12 0x56212001e663 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/quickjs-ng/quickjs/fuzz+0x373663) (BuildId: baf1fe61c0160916b98321b4bbc75964be8ce411)
    #13 0x5621200083df in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/home/quickjs-ng/quickjs/fuzz+0x35d3df) (BuildId: baf1fe61c0160916b98321b4bbc75964be8ce411)
    #14 0x56212000e136 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/quickjs-ng/quickjs/fuzz+0x363136) (BuildId: baf1fe61c0160916b98321b4bbc75964be8ce411)
    #15 0x562120037f52 in main (/home/quickjs-ng/quickjs/fuzz+0x38cf52) (BuildId: baf1fe61c0160916b98321b4bbc75964be8ce411)
    #16 0x7f56e91c3d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/quickjs-ng/quickjs/./quickjs.c:36348:19 in JS_ReadBigInt
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa fd fd fa fa 00[fa]fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: 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
==3106495==ABORTING

Description

This is the same bug as here: bellard/quickjs#399. The issue mentioned contains a fix that can also be applied to quickjs-ng.

Reproducing

using fuzz.c:


// clang -g -O1 -fsanitize=fuzzer -o fuzz fuzz.c
#include "quickjs.h"
#include "quickjs.c"
#include "cutils.c"
#include "libregexp.c"
#include "libunicode.c"
#include "xsum.c"
#include <stdlib.h>

int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
{
    JSRuntime *rt = JS_NewRuntime();
    if (!rt)
        exit(1);
    JSContext *ctx = JS_NewContext(rt);
    if (!ctx)
        exit(1);
    JSValue val = JS_ReadObject(ctx, buf, len, /*flags*/0);
    JS_FreeValue(ctx, val);
    JS_FreeContext(ctx);
    JS_FreeRuntime(rt);
    return 0;
}

with the following input:

echo -ne '\x14\x00\x08\x7f\x00\x0a\xff\xff\xff\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdf\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\x00\x00\x00\x00\x00\x06\x00\xab' > crashing_input.bin
bnoordhuis added a commit to bnoordhuis/quickjs that referenced this issue Apr 8, 2025
Fix buffer overflows in the string and BigInt deserializer caused by a
missing length check and bad size calculation respectively.

Fixes: quickjs-ng#1018
bnoordhuis pushed a commit to bnoordhuis/quickjs that referenced this issue Apr 8, 2025
Fix buffer overflows in the string and BigInt deserializer caused by a
missing length check and bad size calculation respectively.

Fixes: quickjs-ng#1018
bnoordhuis added a commit that referenced this issue Apr 8, 2025
Fix buffer overflows in the string and BigInt deserializer caused by a
missing length check and bad size calculation respectively.

Fixes: #1018
Co-authored-by: Fabrice Bellard <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant