Skip to content
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

heap-buffer-overflow in js_printf_internal #319

Open
renatahodovan opened this issue Jun 13, 2024 · 0 comments
Open

heap-buffer-overflow in js_printf_internal #319

renatahodovan opened this issue Jun 13, 2024 · 0 comments

Comments

@renatahodovan
Copy link
Contributor

Version: 36911f0
Command: ./qjs --std test.js
Build: CONFIG_ASAN=y make qjs
Test:

std.sprintf("%0100000000A71", 1)

Backtrace:

=================================================================
==1018098==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x50200000074f at pc 0x555555646b94 bp 0x7fffffffb570 sp 0x7fffffffad30
WRITE of size 2 at 0x50200000074f thread T0
    #0 0x555555646b93 in __asan_memcpy (quickjs/qjs+0xf2b93) (BuildId: 068887ad0018bcb6620031875a8531c850732cc6)
    #1 0x5555558d16b1 in memcpy_no_ub quickjs/./cutils.h:77:9
    #2 0x5555558d16b1 in dbuf_put quickjs/cutils.c:143:5
    #3 0x5555558dc18d in js_printf_internal quickjs/quickjs-libc.c:186:13
    #4 0x55555568957c in js_call_c_function quickjs/quickjs.c:16036:19
    #5 0x5555556de975 in JS_CallInternal quickjs/quickjs.c:16231:16
    #6 0x5555556f0ca2 in JS_CallInternal quickjs/quickjs.c:16638:27
    #7 0x55555570eb41 in JS_CallFree quickjs/quickjs.c:18717:19
    #8 0x55555570eb41 in JS_EvalFunctionInternal quickjs/quickjs.c:34401:19
    #9 0x55555572fae0 in __JS_EvalInternal quickjs/quickjs.c:34536:19
    #10 0x55555570ff4b in JS_EvalInternal quickjs/quickjs.c:34554:12
    #11 0x55555570ff4b in JS_EvalThis quickjs/quickjs.c:34585:11
    #12 0x55555570ff4b in JS_Eval quickjs/quickjs.c:34593:12
    #13 0x55555568686d in eval_buf quickjs/qjs.c:71:15
    #14 0x555555686aab in eval_file quickjs/qjs.c:103:11
    #15 0x5555556862fb in main quickjs/qjs.c:516:17
    #16 0x7ffff7c7ed8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #17 0x7ffff7c7ee3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #18 0x5555555ac6b4 in _start (quickjs/qjs+0x586b4) (BuildId: 068887ad0018bcb6620031875a8531c850732cc6)

0x50200000074f is located 1 bytes before 1-byte region [0x502000000750,0x502000000751)
allocated by thread T0 here:
    #0 0x555555648a5e in malloc (quickjs/qjs+0xf4a5e) (BuildId: 068887ad0018bcb6620031875a8531c850732cc6)
    #1 0x55555574a755 in js_def_malloc quickjs/quickjs.c:1729:11
    #2 0x55555574a755 in js_def_realloc quickjs/quickjs.c:1755:16
    #3 0x5555558d134e in dbuf_realloc quickjs/cutils.c:114:19
    #4 0x5555558d16d7 in dbuf_put quickjs/cutils.c:140:13
    #5 0x5555558dc18d in js_printf_internal quickjs/quickjs-libc.c:186:13
    #6 0x55555568957c in js_call_c_function quickjs/quickjs.c:16036:19
    #7 0x5555556de975 in JS_CallInternal quickjs/quickjs.c:16231:16
    #8 0x5555556f0ca2 in JS_CallInternal quickjs/quickjs.c:16638:27
    #9 0x55555570eb41 in JS_CallFree quickjs/quickjs.c:18717:19
    #10 0x55555570eb41 in JS_EvalFunctionInternal quickjs/quickjs.c:34401:19
    #11 0x55555572fae0 in __JS_EvalInternal quickjs/quickjs.c:34536:19
    #12 0x55555570ff4b in JS_EvalInternal quickjs/quickjs.c:34554:12
    #13 0x55555570ff4b in JS_EvalThis quickjs/quickjs.c:34585:11
    #14 0x55555570ff4b in JS_Eval quickjs/quickjs.c:34593:12
    #15 0x55555568686d in eval_buf quickjs/qjs.c:71:15
    #16 0x555555686aab in eval_file quickjs/qjs.c:103:11
    #17 0x5555556862fb in main quickjs/qjs.c:516:17
    #18 0x7ffff7c7ed8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

SUMMARY: AddressSanitizer: heap-buffer-overflow (quickjs/qjs+0xf2b93) (BuildId: 068887ad0018bcb6620031875a8531c850732cc6) in __asan_memcpy
Shadow bytes around the buggy address:
  0x502000000480: fa fa fd fd fa fa fd fa fa fa fd fd fa fa 00 fa
  0x502000000500: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa fd fa
  0x502000000580: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fd
  0x502000000600: fa fa fd fd fa fa fd fd fa fa fd fa fa fa fd fd
  0x502000000680: fa fa fd fd fa fa fd fd fa fa fd fa fa fa fd fd
=>0x502000000700: fa fa fd fd fa fa fd fa fa[fa]01 fa fa fa fa fa
  0x502000000780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000000800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000000880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000000900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000000980: 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
==1018098==ABORTING

The issue was found by libFuzzer.

TooTallNate pushed a commit to TooTallNate/quickjs that referenced this issue Jul 3, 2024
* Improve consistency of JS_NewFloat64 API

- `JS_NewFloat64()` always creates a `JS_TAG_FLOAT64` value
- internal `js_float64()` always creates a `JS_TAG_FLOAT64` value
- add `js_int64` internal function for consistency
- rename `float_is_int32` as `double_is_int32`
- handle `INT32_MIN` in `double_is_int32`, use (somewhat) faster alternative
- add `js_number(d)` to create a `JS_TAG_FLOAT64` or a `JS_TAG_INT` value
  if possible
- add `JS_NewNumber()` API for the same purpose
- use non testing constructor for infinities in `js_atof2`
- always store internal time value as a float64
- merge `JS_NewBigInt64_1` into `JS_NewBigInt64`
- use comparisons instead of `(int32_t)` casts (implementation defined behavior)
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

No branches or pull requests

1 participant