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

Segmentation fault #20

Open
floyd-fuh opened this Issue Feb 10, 2015 · 3 comments

Comments

Projects
None yet
3 participants
@floyd-fuh

floyd-fuh commented Feb 10, 2015

Hi there

I fuzzed libjson with American Fuzzy Lop (http://lcamtuf.coredump.cx/afl/ , for no real reason at all, I was just looking for libraries to test AFL). I was running jsonlint with:

jsonlint --tree inputfile

The inputfile with the following content will crash jsonlint (segmentation fault):

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[][[[[[[[[[[[[[[

Best regards,
floyd

@vincenthz

This comment has been minimized.

Show comment
Hide comment
@vincenthz

vincenthz Feb 10, 2015

Owner

I'm not able to reproduce, can you hook this to gdb / lldb to see what's the issue ? also it's probably good to find out if it's coming from jsonlint (a simple "example" / "utility" to test libjson), or from libjson itself.

Owner

vincenthz commented Feb 10, 2015

I'm not able to reproduce, can you hook this to gdb / lldb to see what's the issue ? also it's probably good to find out if it's coming from jsonlint (a simple "example" / "utility" to test libjson), or from libjson itself.

@floyd-fuh

This comment has been minimized.

Show comment
Hide comment
@floyd-fuh

floyd-fuh Feb 11, 2015

Sure. Ok, that example doesn't crash for me on OSX (x86_64) either. I assumed that all my fuzzing results originated from the same bug, that's why I only gave the above example. But let's dig deeper.

My fuzzing environment was ARM on an odroid u3 (and obviously with instrumentation from AFL), where it did crash with 6 different input files (4 segmentation faults and 2 aborts). Here are the original 6 crash input files:

id/000000,sig/11,src/000199,op/havoc,rep/1 - https://gist.github.com/floyd-fuh/fd0f6e312ac03ea38951
id/000000,sig/11,src/000211,op/flip2,pos/1028 - https://gist.github.com/floyd-fuh/f9157515016a21ac4880
id/000001,sig/06,src/000361,op/havoc,rep/1 - https://gist.github.com/floyd-fuh/5f9bd28a098915762803
id/000001,sig/11,src/000346,op/havoc,rep/1 - https://gist.github.com/floyd-fuh/107660969314fa2e7fef
id/000002,sig/11,src/000377,op/havoc,rep/1 - https://gist.github.com/floyd-fuh/3a8222992e6731688198
id/000003,sig/06,src/000199+000366,op/splice,rep/1 - https://gist.github.com/floyd-fuh/c75cbdeb98441bbc2fa7

By now it's really rare, but it can happen that one of the results was due to another issue on the odroid (the odroids run on 100% cpu usage for a very long time). So don't worry if you can't reproduce each and every one of them.

However, I'm still able to produce 2 segmentation faults when I do a fresh compile on OSX with standard clang, added -g to CFLAGS:

$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix

$ make clean
rm -f *.o libjson.a libjson.so.1.0.0 libjson.so libjson.so.1 libjson.so.1.0 jsonlint libjson.pc

$ make 
gcc -g -Wall -Os -fPIC -c -o json.o json.c
ar rc libjson.a json.o
gcc -g -Wall -Os -fPIC -L.  -shared -o libjson.so.1.0.0 json.o
ln -sf libjson.so.1.0.0 libjson.so.1.0
ln -sf libjson.so.1.0 libjson.so.1
ln -sf libjson.so.1 libjson.so
gcc -g -Wall -Os -fPIC   -c -o jsonlint.o jsonlint.c
gcc -g -Wall -Os -fPIC -o jsonlint jsonlint.o json.o
sed -e 's;@PREFIX@;/usr;' -e 's;@LIBJSON_VER_MAJOR@;1;' -e 's;@LIBJSON_VER_MINOR@;0;' < libjson.pc.in > libjson.pc

$ ./jsonlint --tree ../../floyds/crashes-only/id\:000002\,sig\:11\,src\:000377\,op\:havoc\,rep\:1 
Segmentation fault: 11

$ lldb -- ./jsonlint --tree ../../floyds/crashes-only/id\:000002\,sig\:11\,src\:000377\,op\:havoc\,rep\:1 
(lldb) target create "./jsonlint"
Current executable set to './jsonlint' (x86_64).
(lldb) settings set -- target.run-args  "--tree" "../../floyds/crashes-only/id:000002,sig:11,src:000377,op:havoc,rep:1"
(lldb) run
Process 55909 launched: './jsonlint' (x86_64)
jsonlint(55909,0x7fff7dab2310) malloc: *** error for object 0x7ffb83411675c985: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug
Process 55909 stopped
* thread #1: tid = 0x30434c, 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff97ddf866:  jae    0x7fff97ddf870            ; __pthread_kill + 20
   0x7fff97ddf868:  movq   %rax, %rdi
   0x7fff97ddf86b:  jmp    0x7fff97ddc175            ; cerror_nocancel
   0x7fff97ddf870:  retq   
(lldb) bt
* thread #1: tid = 0x30434c, 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff9065c35c libsystem_pthread.dylib`pthread_kill + 92
    frame #2: 0x00007fff8d739b1a libsystem_c.dylib`abort + 125
    frame #3: 0x00007fff9512f451 libsystem_malloc.dylib`realloc + 364
    frame #4: 0x00000001000023d1 jsonlint`tree_append(structure=0x0000000100003431, key=<unavailable>, key_length=<unavailable>, obj=0x00000001e27db888) + 99 at jsonlint.c:323
    frame #5: 0x0000000100002fcf jsonlint`json_parser_dom_callback(userdata=0x00007fff5fbff360, type=<unavailable>, data=<unavailable>, length=<unavailable>) + 272 at json.c:1044
    frame #6: 0x000000010000285a jsonlint`json_parser_string [inlined] do_action + 72 at json.c:656
    frame #7: 0x0000000100002812 jsonlint`json_parser_string(parser=0x00007fff5fbff3a0, s=0x00007fff5fbfe310, length=3462, processed=0x00007fff5fbfe30c) + 397 at json.c:783
    frame #8: 0x000000010000163a jsonlint`process_file(parser=0x00007fff5fbff3a0, input=0x00007fff7d40c2a0, retlines=0x00007fff5fbff358, retcols=0x00007fff5fbff35c) + 134 at jsonlint.c:95
    frame #9: 0x0000000100001f99 jsonlint`do_tree(config=<unavailable>, filename=0x00007fff5fbff91a, root_structure=0x00007fff5fbff488) + 260 at jsonlint.c:358
    frame #10: 0x0000000100001ad5 jsonlint`main(argc=3, argv=0x00007fff5fbff7a0) + 890 at jsonlint.c:542
    frame #11: 0x00007fff8ffd35fd libdyld.dylib`start + 1

$ ./jsonlint --tree ../../floyds/crashes-only/id\:000001\,sig\:11\,src\:000346\,op\:havoc\,rep\:1 
Segmentation fault: 11

$ lldb -- ./jsonlint --tree ../../floyds/crashes-only/id\:000001\,sig\:11\,src\:000346\,op\:havoc\,rep\:1 
(lldb) target create "./jsonlint"
Current executable set to './jsonlint' (x86_64).
(lldb) settings set -- target.run-args  "--tree" "../../floyds/crashes-only/id:000001,sig:11,src:000346,op:havoc,rep:1"
(lldb) run
Process 55965 launched: './jsonlint' (x86_64)
jsonlint(55965,0x7fff7dab2310) malloc: *** error for object 0x7ffb83411675c985: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug
Process 55965 stopped
* thread #1: tid = 0x305e06, 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff97ddf866:  jae    0x7fff97ddf870            ; __pthread_kill + 20
   0x7fff97ddf868:  movq   %rax, %rdi
   0x7fff97ddf86b:  jmp    0x7fff97ddc175            ; cerror_nocancel
   0x7fff97ddf870:  retq   
(lldb) bt
* thread #1: tid = 0x305e06, 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff9065c35c libsystem_pthread.dylib`pthread_kill + 92
    frame #2: 0x00007fff8d739b1a libsystem_c.dylib`abort + 125
    frame #3: 0x00007fff9512f451 libsystem_malloc.dylib`realloc + 364
    frame #4: 0x00000001000023d1 jsonlint`tree_append(structure=0x0000000100003431, key=<unavailable>, key_length=<unavailable>, obj=0x00000001e27db888) + 99 at jsonlint.c:323
    frame #5: 0x0000000100002fcf jsonlint`json_parser_dom_callback(userdata=0x00007fff5fbff360, type=<unavailable>, data=<unavailable>, length=<unavailable>) + 272 at json.c:1044
    frame #6: 0x000000010000285a jsonlint`json_parser_string [inlined] do_action + 72 at json.c:656
    frame #7: 0x0000000100002812 jsonlint`json_parser_string(parser=0x00007fff5fbff3a0, s=0x00007fff5fbfe310, length=4080, processed=0x00007fff5fbfe30c) + 397 at json.c:783
    frame #8: 0x000000010000163a jsonlint`process_file(parser=0x00007fff5fbff3a0, input=0x00007fff7d40c2a0, retlines=0x00007fff5fbff358, retcols=0x00007fff5fbff35c) + 134 at jsonlint.c:95
    frame #9: 0x0000000100001f99 jsonlint`do_tree(config=<unavailable>, filename=0x00007fff5fbff91a, root_structure=0x00007fff5fbff488) + 260 at jsonlint.c:358
    frame #10: 0x0000000100001ad5 jsonlint`main(argc=3, argv=0x00007fff5fbff7a0) + 890 at jsonlint.c:542
    frame #11: 0x00007fff8ffd35fd libdyld.dylib`start + 1

Hope you'll be able to reproduce.

PS: Maybe you should try AFL yourself. It's simply a gcc wrapper, very easy to setup for your tool, see http://lcamtuf.coredump.cx/afl/

floyd-fuh commented Feb 11, 2015

Sure. Ok, that example doesn't crash for me on OSX (x86_64) either. I assumed that all my fuzzing results originated from the same bug, that's why I only gave the above example. But let's dig deeper.

My fuzzing environment was ARM on an odroid u3 (and obviously with instrumentation from AFL), where it did crash with 6 different input files (4 segmentation faults and 2 aborts). Here are the original 6 crash input files:

id/000000,sig/11,src/000199,op/havoc,rep/1 - https://gist.github.com/floyd-fuh/fd0f6e312ac03ea38951
id/000000,sig/11,src/000211,op/flip2,pos/1028 - https://gist.github.com/floyd-fuh/f9157515016a21ac4880
id/000001,sig/06,src/000361,op/havoc,rep/1 - https://gist.github.com/floyd-fuh/5f9bd28a098915762803
id/000001,sig/11,src/000346,op/havoc,rep/1 - https://gist.github.com/floyd-fuh/107660969314fa2e7fef
id/000002,sig/11,src/000377,op/havoc,rep/1 - https://gist.github.com/floyd-fuh/3a8222992e6731688198
id/000003,sig/06,src/000199+000366,op/splice,rep/1 - https://gist.github.com/floyd-fuh/c75cbdeb98441bbc2fa7

By now it's really rare, but it can happen that one of the results was due to another issue on the odroid (the odroids run on 100% cpu usage for a very long time). So don't worry if you can't reproduce each and every one of them.

However, I'm still able to produce 2 segmentation faults when I do a fresh compile on OSX with standard clang, added -g to CFLAGS:

$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix

$ make clean
rm -f *.o libjson.a libjson.so.1.0.0 libjson.so libjson.so.1 libjson.so.1.0 jsonlint libjson.pc

$ make 
gcc -g -Wall -Os -fPIC -c -o json.o json.c
ar rc libjson.a json.o
gcc -g -Wall -Os -fPIC -L.  -shared -o libjson.so.1.0.0 json.o
ln -sf libjson.so.1.0.0 libjson.so.1.0
ln -sf libjson.so.1.0 libjson.so.1
ln -sf libjson.so.1 libjson.so
gcc -g -Wall -Os -fPIC   -c -o jsonlint.o jsonlint.c
gcc -g -Wall -Os -fPIC -o jsonlint jsonlint.o json.o
sed -e 's;@PREFIX@;/usr;' -e 's;@LIBJSON_VER_MAJOR@;1;' -e 's;@LIBJSON_VER_MINOR@;0;' < libjson.pc.in > libjson.pc

$ ./jsonlint --tree ../../floyds/crashes-only/id\:000002\,sig\:11\,src\:000377\,op\:havoc\,rep\:1 
Segmentation fault: 11

$ lldb -- ./jsonlint --tree ../../floyds/crashes-only/id\:000002\,sig\:11\,src\:000377\,op\:havoc\,rep\:1 
(lldb) target create "./jsonlint"
Current executable set to './jsonlint' (x86_64).
(lldb) settings set -- target.run-args  "--tree" "../../floyds/crashes-only/id:000002,sig:11,src:000377,op:havoc,rep:1"
(lldb) run
Process 55909 launched: './jsonlint' (x86_64)
jsonlint(55909,0x7fff7dab2310) malloc: *** error for object 0x7ffb83411675c985: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug
Process 55909 stopped
* thread #1: tid = 0x30434c, 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff97ddf866:  jae    0x7fff97ddf870            ; __pthread_kill + 20
   0x7fff97ddf868:  movq   %rax, %rdi
   0x7fff97ddf86b:  jmp    0x7fff97ddc175            ; cerror_nocancel
   0x7fff97ddf870:  retq   
(lldb) bt
* thread #1: tid = 0x30434c, 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff9065c35c libsystem_pthread.dylib`pthread_kill + 92
    frame #2: 0x00007fff8d739b1a libsystem_c.dylib`abort + 125
    frame #3: 0x00007fff9512f451 libsystem_malloc.dylib`realloc + 364
    frame #4: 0x00000001000023d1 jsonlint`tree_append(structure=0x0000000100003431, key=<unavailable>, key_length=<unavailable>, obj=0x00000001e27db888) + 99 at jsonlint.c:323
    frame #5: 0x0000000100002fcf jsonlint`json_parser_dom_callback(userdata=0x00007fff5fbff360, type=<unavailable>, data=<unavailable>, length=<unavailable>) + 272 at json.c:1044
    frame #6: 0x000000010000285a jsonlint`json_parser_string [inlined] do_action + 72 at json.c:656
    frame #7: 0x0000000100002812 jsonlint`json_parser_string(parser=0x00007fff5fbff3a0, s=0x00007fff5fbfe310, length=3462, processed=0x00007fff5fbfe30c) + 397 at json.c:783
    frame #8: 0x000000010000163a jsonlint`process_file(parser=0x00007fff5fbff3a0, input=0x00007fff7d40c2a0, retlines=0x00007fff5fbff358, retcols=0x00007fff5fbff35c) + 134 at jsonlint.c:95
    frame #9: 0x0000000100001f99 jsonlint`do_tree(config=<unavailable>, filename=0x00007fff5fbff91a, root_structure=0x00007fff5fbff488) + 260 at jsonlint.c:358
    frame #10: 0x0000000100001ad5 jsonlint`main(argc=3, argv=0x00007fff5fbff7a0) + 890 at jsonlint.c:542
    frame #11: 0x00007fff8ffd35fd libdyld.dylib`start + 1

$ ./jsonlint --tree ../../floyds/crashes-only/id\:000001\,sig\:11\,src\:000346\,op\:havoc\,rep\:1 
Segmentation fault: 11

$ lldb -- ./jsonlint --tree ../../floyds/crashes-only/id\:000001\,sig\:11\,src\:000346\,op\:havoc\,rep\:1 
(lldb) target create "./jsonlint"
Current executable set to './jsonlint' (x86_64).
(lldb) settings set -- target.run-args  "--tree" "../../floyds/crashes-only/id:000001,sig:11,src:000346,op:havoc,rep:1"
(lldb) run
Process 55965 launched: './jsonlint' (x86_64)
jsonlint(55965,0x7fff7dab2310) malloc: *** error for object 0x7ffb83411675c985: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug
Process 55965 stopped
* thread #1: tid = 0x305e06, 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff97ddf866:  jae    0x7fff97ddf870            ; __pthread_kill + 20
   0x7fff97ddf868:  movq   %rax, %rdi
   0x7fff97ddf86b:  jmp    0x7fff97ddc175            ; cerror_nocancel
   0x7fff97ddf870:  retq   
(lldb) bt
* thread #1: tid = 0x305e06, 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff97ddf866 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff9065c35c libsystem_pthread.dylib`pthread_kill + 92
    frame #2: 0x00007fff8d739b1a libsystem_c.dylib`abort + 125
    frame #3: 0x00007fff9512f451 libsystem_malloc.dylib`realloc + 364
    frame #4: 0x00000001000023d1 jsonlint`tree_append(structure=0x0000000100003431, key=<unavailable>, key_length=<unavailable>, obj=0x00000001e27db888) + 99 at jsonlint.c:323
    frame #5: 0x0000000100002fcf jsonlint`json_parser_dom_callback(userdata=0x00007fff5fbff360, type=<unavailable>, data=<unavailable>, length=<unavailable>) + 272 at json.c:1044
    frame #6: 0x000000010000285a jsonlint`json_parser_string [inlined] do_action + 72 at json.c:656
    frame #7: 0x0000000100002812 jsonlint`json_parser_string(parser=0x00007fff5fbff3a0, s=0x00007fff5fbfe310, length=4080, processed=0x00007fff5fbfe30c) + 397 at json.c:783
    frame #8: 0x000000010000163a jsonlint`process_file(parser=0x00007fff5fbff3a0, input=0x00007fff7d40c2a0, retlines=0x00007fff5fbff358, retcols=0x00007fff5fbff35c) + 134 at jsonlint.c:95
    frame #9: 0x0000000100001f99 jsonlint`do_tree(config=<unavailable>, filename=0x00007fff5fbff91a, root_structure=0x00007fff5fbff488) + 260 at jsonlint.c:358
    frame #10: 0x0000000100001ad5 jsonlint`main(argc=3, argv=0x00007fff5fbff7a0) + 890 at jsonlint.c:542
    frame #11: 0x00007fff8ffd35fd libdyld.dylib`start + 1

Hope you'll be able to reproduce.

PS: Maybe you should try AFL yourself. It's simply a gcc wrapper, very easy to setup for your tool, see http://lcamtuf.coredump.cx/afl/

@attekett

This comment has been minimized.

Show comment
Hide comment
@attekett

attekett Sep 28, 2016

I can also reproduce this issue.

I have a slightly different repro-file:

["",["",["",[[[["",["",["",[[[[["",[["",[[["",[[[[["",["",[[[[[[[[["",[[[["",[["",["",["",[[[["",["",["",[[[[["",[["",[["",[[[["",[[["",["",[[["",["",[[["",[[["",[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["",["",[[["",["",[[[[["",[

Tested on:

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.1 LTS
Release: 16.04
Codename: xenial

$ git show
commit bd0cad8
Merge: 1553076 1ac9c82
Author: Vincent Hanquez vincent@snarc.org
Date: Tue Apr 19 05:29:49 2016 +0100

Merge pull request #21 from dat/patch-1

Add link to the actual RFC 4627 in README.

If you use --max-nesting 1023 there is no crash, but with --max-nesting 1024 jsonlint crashes.

With GDB, breakpoint at tree_create_structure:

Breakpoint 2, tree_create_structure (nesting=1024, is_object=0) at jsonlint.c:241
241 {
(gdb)
Continuing.

Program received signal SIGSEGV, Segmentation fault.
dom_push (val=0x602000006330, ctx=0x7fffffffd680) at json.c:988
988 ctx->stack[ctx->stack_offset].val = val;

Changing dom->stack_size to a larger value from json.c:1008 fixes the issue, for this repro-file, but the limit should be enforces with some check, instead of just hoping that parsing doesn't reach that higher limit.

The issue is easiest to reproduce by enabling AddressSanitizer from Makefile:

diff --git a/Makefile b/Makefile
index 9ee15b5..ae2b570 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 AR = ar
 CC = gcc
-CFLAGS ?= -Wall -Os -fPIC
+CFLAGS ?= -Wall -Os -fPIC -fsanitize=address
 LDFLAGS = -L.
 SHLIB_CFLAGS = -shared

$ make
.
.
.

$ ./jsonlint --tree SEGV-99d-891-207.json

ASAN:SIGSEGV

==20141==ERROR: AddressSanitizer: SEGV on unknown address 0x61d000024a80 (pc 0x00000040599e bp 0x000000000800 sp 0x7ffe78cdd0b0 T0)
#0 0x40599d in json_parser_dom_callback (/home/attekett/libjson/libjson-asan/jsonlint+0x40599d)
#1 0x404891 in act_ab (/home/attekett/libjson/libjson-asan/jsonlint+0x404891)
#2 0x405207 in json_parser_string (/home/attekett/libjson/libjson-asan/jsonlint+0x405207)
#3 0x402b01 in process_file (/home/attekett/libjson/libjson-asan/jsonlint+0x402b01)
#4 0x402e64 in do_tree (/home/attekett/libjson/libjson-asan/jsonlint+0x402e64)
#5 0x401a8e in main (/home/attekett/libjson/libjson-asan/jsonlint+0x401a8e)
#6 0x7f5bf295582f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#7 0x402018 in _start (/home/attekett/libjson/libjson-asan/jsonlint+0x402018)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 json_parser_dom_callback
==20141==ABORTING

With ASAN_OPTIONS=redzone=1024, the crash appears as

==20614==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x620000015800 at pc 0x00000040599a bp 0x7ffcf2e2d390 sp 0x7ffcf2e2d380
WRITE of size 8 at 0x620000015800 thread T0
#0 0x405999 in dom_push /home/attekett/libjson/libjson-asan/json.c:988
#1 0x405999 in json_parser_dom_callback /home/attekett/libjson/libjson-asan/json.c:1037

Which sounds more correct, at least when comparing to what Valgrind reports with regular build:

$ valgrind ./jsonlint --tree SEGV-99d-891-207.json
==20192== Memcheck, a memory error detector
==20192== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==20192== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==20192== Command: ./jsonlint --tree SEGV-99d-891-207.json
==20192==
==20192== Invalid write of size 8
==20192== at 0x40277A: json_parser_dom_callback (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x40213F: act_ab (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x402481: json_parser_string (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401732: process_file (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401894: do_tree (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x400F27: main (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== Address 0x5227b60 is 22,464 bytes inside an unallocated block of size 4,066,368 in arena "client"
==20192==
==20192== Invalid write of size 8
==20192== at 0x40277D: json_parser_dom_callback (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x40213F: act_ab (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x402481: json_parser_string (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401732: process_file (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401894: do_tree (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x400F27: main (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== Address 0x5227b68 is 22,472 bytes inside an unallocated block of size 4,066,368 in arena "client"
==20192==
==20192== Invalid write of size 4
==20192== at 0x402785: json_parser_dom_callback (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x40213F: act_ab (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x402481: json_parser_string (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401732: process_file (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401894: do_tree (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x400F27: main (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== Address 0x5227b70 is 22,480 bytes inside an unallocated block of size 4,066,368 in arena "client"
==20192==
syntax error
==20192==
==20192== HEAP SUMMARY:
==20192== in use at exit: 26,266 bytes in 1,131 blocks
==20192== total heap usage: 1,136 allocs, 5 frees, 56,730 bytes allocated
==20192==
==20192== LEAK SUMMARY:
==20192== definitely lost: 23,216 bytes in 942 blocks
==20192== indirectly lost: 2,498 bytes in 188 blocks
==20192== possibly lost: 0 bytes in 0 blocks
==20192== still reachable: 552 bytes in 1 blocks
==20192== suppressed: 0 bytes in 0 blocks
==20192== Rerun with --leak-check=full to see details of leaked memory
==20192==
==20192== For counts of detected and suppressed errors, rerun with: -v
==20192== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

attekett commented Sep 28, 2016

I can also reproduce this issue.

I have a slightly different repro-file:

["",["",["",[[[["",["",["",[[[[["",[["",[[["",[[[[["",["",[[[[[[[[["",[[[["",[["",["",["",[[[["",["",["",[[[[["",[["",[["",[[[["",[[["",["",[[["",["",[[["",[[["",[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["",["",[[["",["",[[[[["",[

Tested on:

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.1 LTS
Release: 16.04
Codename: xenial

$ git show
commit bd0cad8
Merge: 1553076 1ac9c82
Author: Vincent Hanquez vincent@snarc.org
Date: Tue Apr 19 05:29:49 2016 +0100

Merge pull request #21 from dat/patch-1

Add link to the actual RFC 4627 in README.

If you use --max-nesting 1023 there is no crash, but with --max-nesting 1024 jsonlint crashes.

With GDB, breakpoint at tree_create_structure:

Breakpoint 2, tree_create_structure (nesting=1024, is_object=0) at jsonlint.c:241
241 {
(gdb)
Continuing.

Program received signal SIGSEGV, Segmentation fault.
dom_push (val=0x602000006330, ctx=0x7fffffffd680) at json.c:988
988 ctx->stack[ctx->stack_offset].val = val;

Changing dom->stack_size to a larger value from json.c:1008 fixes the issue, for this repro-file, but the limit should be enforces with some check, instead of just hoping that parsing doesn't reach that higher limit.

The issue is easiest to reproduce by enabling AddressSanitizer from Makefile:

diff --git a/Makefile b/Makefile
index 9ee15b5..ae2b570 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 AR = ar
 CC = gcc
-CFLAGS ?= -Wall -Os -fPIC
+CFLAGS ?= -Wall -Os -fPIC -fsanitize=address
 LDFLAGS = -L.
 SHLIB_CFLAGS = -shared

$ make
.
.
.

$ ./jsonlint --tree SEGV-99d-891-207.json

ASAN:SIGSEGV

==20141==ERROR: AddressSanitizer: SEGV on unknown address 0x61d000024a80 (pc 0x00000040599e bp 0x000000000800 sp 0x7ffe78cdd0b0 T0)
#0 0x40599d in json_parser_dom_callback (/home/attekett/libjson/libjson-asan/jsonlint+0x40599d)
#1 0x404891 in act_ab (/home/attekett/libjson/libjson-asan/jsonlint+0x404891)
#2 0x405207 in json_parser_string (/home/attekett/libjson/libjson-asan/jsonlint+0x405207)
#3 0x402b01 in process_file (/home/attekett/libjson/libjson-asan/jsonlint+0x402b01)
#4 0x402e64 in do_tree (/home/attekett/libjson/libjson-asan/jsonlint+0x402e64)
#5 0x401a8e in main (/home/attekett/libjson/libjson-asan/jsonlint+0x401a8e)
#6 0x7f5bf295582f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#7 0x402018 in _start (/home/attekett/libjson/libjson-asan/jsonlint+0x402018)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 json_parser_dom_callback
==20141==ABORTING

With ASAN_OPTIONS=redzone=1024, the crash appears as

==20614==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x620000015800 at pc 0x00000040599a bp 0x7ffcf2e2d390 sp 0x7ffcf2e2d380
WRITE of size 8 at 0x620000015800 thread T0
#0 0x405999 in dom_push /home/attekett/libjson/libjson-asan/json.c:988
#1 0x405999 in json_parser_dom_callback /home/attekett/libjson/libjson-asan/json.c:1037

Which sounds more correct, at least when comparing to what Valgrind reports with regular build:

$ valgrind ./jsonlint --tree SEGV-99d-891-207.json
==20192== Memcheck, a memory error detector
==20192== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==20192== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==20192== Command: ./jsonlint --tree SEGV-99d-891-207.json
==20192==
==20192== Invalid write of size 8
==20192== at 0x40277A: json_parser_dom_callback (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x40213F: act_ab (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x402481: json_parser_string (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401732: process_file (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401894: do_tree (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x400F27: main (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== Address 0x5227b60 is 22,464 bytes inside an unallocated block of size 4,066,368 in arena "client"
==20192==
==20192== Invalid write of size 8
==20192== at 0x40277D: json_parser_dom_callback (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x40213F: act_ab (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x402481: json_parser_string (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401732: process_file (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401894: do_tree (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x400F27: main (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== Address 0x5227b68 is 22,472 bytes inside an unallocated block of size 4,066,368 in arena "client"
==20192==
==20192== Invalid write of size 4
==20192== at 0x402785: json_parser_dom_callback (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x40213F: act_ab (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x402481: json_parser_string (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401732: process_file (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x401894: do_tree (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== by 0x400F27: main (in /home/attekett/libjson/libjson-asan/jsonlint)
==20192== Address 0x5227b70 is 22,480 bytes inside an unallocated block of size 4,066,368 in arena "client"
==20192==
syntax error
==20192==
==20192== HEAP SUMMARY:
==20192== in use at exit: 26,266 bytes in 1,131 blocks
==20192== total heap usage: 1,136 allocs, 5 frees, 56,730 bytes allocated
==20192==
==20192== LEAK SUMMARY:
==20192== definitely lost: 23,216 bytes in 942 blocks
==20192== indirectly lost: 2,498 bytes in 188 blocks
==20192== possibly lost: 0 bytes in 0 blocks
==20192== still reachable: 552 bytes in 1 blocks
==20192== suppressed: 0 bytes in 0 blocks
==20192== Rerun with --leak-check=full to see details of leaked memory
==20192==
==20192== For counts of detected and suppressed errors, rerun with: -v
==20192== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment