there is an integer overflow in variable exp. The number 1E9600000000000000000000000000 is parsed into 0x80000000, which causes the for loop in jsdtoa.c:727-730 being executed dozens of times. Because -O2 in compile args, the if (exp < -maxExponent) branch has been optimised out by gcc.
poc:
Function(1E9600000000000000000000000000)
compile args:
CC=/usr/bin/gcc make release
AddressSanitizer output:
==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000690638 at pc 0x00000040af2f bp 0x7ffdaa557c60 sp 0x7ffdaa557c50
READ of size 8 at 0x000000690638 thread T0
#0 0x40af2e in js_strtod /data/clean/mujs-1.1.1/jsdtoa.c:729
#1 0x436da2 in lexnumber /data/clean/mujs-1.1.1/jslex.c:383
#2 0x42564b in jsY_lexx /data/clean/mujs-1.1.1/jslex.c:605
#3 0x467fe4 in jsY_lex /data/clean/mujs-1.1.1/jslex.c:742
#4 0x467fe4 in jsP_next /data/clean/mujs-1.1.1/jsparse.c:140
#5 0x467fe4 in callexp /data/clean/mujs-1.1.1/jsparse.c:425
#6 0x467fe4 in postfix /data/clean/mujs-1.1.1/jsparse.c:432
#7 0x467fe4 in unary /data/clean/mujs-1.1.1/jsparse.c:453
#8 0x468cd8 in multiplicative /data/clean/mujs-1.1.1/jsparse.c:460
#9 0x468fe8 in additive /data/clean/mujs-1.1.1/jsparse.c:475
#10 0x469268 in shift /data/clean/mujs-1.1.1/jsparse.c:489
#11 0x46958b in relational /data/clean/mujs-1.1.1/jsparse.c:504
#12 0x469a6b in equality /data/clean/mujs-1.1.1/jsparse.c:522
#13 0x469e2a in bitand /data/clean/mujs-1.1.1/jsparse.c:538
#14 0x46a04a in bitxor /data/clean/mujs-1.1.1/jsparse.c:552
#15 0x46a26b in bitor /data/clean/mujs-1.1.1/jsparse.c:566
#16 0x46a26b in logand /data/clean/mujs-1.1.1/jsparse.c:580
#17 0x46a5b0 in logor /data/clean/mujs-1.1.1/jsparse.c:592
#18 0x46a74b in conditional /data/clean/mujs-1.1.1/jsparse.c:604
#19 0x46a74b in assignment /data/clean/mujs-1.1.1/jsparse.c:620
#20 0x46ba3a in expression /data/clean/mujs-1.1.1/jsparse.c:641
#21 0x428651 in statement /data/clean/mujs-1.1.1/jsparse.c:906
#22 0x429a62 in script /data/clean/mujs-1.1.1/jsparse.c:942
#23 0x429d08 in jsP_parse /data/clean/mujs-1.1.1/jsparse.c:1049
#24 0x429d97 in js_loadstringx /data/clean/mujs-1.1.1/jsstate.c:113
#25 0x434c85 in js_loadstring /data/clean/mujs-1.1.1/jsstate.c:128
#26 0x434c85 in js_loadfile /data/clean/mujs-1.1.1/jsstate.c:188
#27 0x45f252 in js_dofile /data/clean/mujs-1.1.1/jsstate.c:217
#28 0x40256e in main /data/clean/mujs-1.1.1/main.c:354
#29 0x7f88433ab83f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
#30 0x402b78 in _start (/data/clean/mujs-1.1.1/build/sanitize/mujs+0x402b78)
0x000000690638 is located 8 bytes to the left of global variable 'futurewords' defined in 'jscompile.c:35:20' (0x690640) of size 56
0x000000690638 is located 48 bytes to the right of global variable 'strictfuturewords' defined in 'jscompile.c:39:20' (0x6905c0) of size 72
SUMMARY: AddressSanitizer: global-buffer-overflow /data/clean/mujs-1.1.1/jsdtoa.c:729 in js_strtod
Shadow bytes around the buggy address:
0x0000800ca070: 00 00 00 00 00 00 00 00 f9 f9 f9 f9 00 00 00 00
0x0000800ca080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800ca090: 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9
0x0000800ca0a0: 00 00 00 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 00
0x0000800ca0b0: 00 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 00
=>0x0000800ca0c0: 00 f9 f9 f9 f9 f9 f9[f9]00 00 00 00 00 00 00 f9
0x0000800ca0d0: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800ca0e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800ca0f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800ca100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800ca110: 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
Shadow gap: cc
==106141==ABORTING
The text was updated successfully, but these errors were encountered:
GCC with -O2 optimizes away the if(exp<-maxExponent) branch completely,
so we don't end up with the expected '512' value for overflowing
exponents. Limit the exponent parsing to MAX_INT instead to prevent
signed overflow from tripping up over-eager optimizing compilers.
Ugh. Yet another issue caused by over-eager optimizing compilers... This compiler bug is only present in GCC and not in Clang. I've added an explicit overflow check so we shouldn't be triggering the "signed overflow -- now I can do anything!" compiler wankery.
In jsdtoa.c:694-696,
there is an integer overflow in variable
exp. The number1E9600000000000000000000000000is parsed into0x80000000, which causes the for loop in jsdtoa.c:727-730 being executed dozens of times. Because-O2in compile args, theif (exp < -maxExponent)branch has been optimised out by gcc.poc:
compile args:
AddressSanitizer output:
The text was updated successfully, but these errors were encountered: