lloyd / yajl

A fast streaming JSON parsing library in C.
http://lloyd.github.com/yajl
ISC License
2.16k stars 437 forks source link

Double free vulnerability in yajl_lex_free - 1.0.12 #206

Open zeroinside opened 6 years ago

zeroinside commented 6 years ago

Valgrind output:==7080== Process terminating with default action of signal 11 (SIGSEGV) ==7080== Access not within mapped region at address 0x60540C380 ==7080== at 0x4E3B215: yajl_lex_free (in /lib/libyajl.so.1) ==7080== by 0x4E3B109: yajl_free (in /lib/libyajl.so.1) ==7080== by 0x4013E3: main (input.c:167) ==7080== If you believe this happened as a result of a stack ==7080== overflow in your program's main thread (unlikely but ==7080== possible), you can try to increase the size of the ==7080== main thread stack using the --main-stacksize= flag. ==7080== The main thread stack size used in this run was 8388608. ==7080== ==7080== HEAP SUMMARY: ==7080== in use at exit: 4,248 bytes in 3 blocks ==7080== total heap usage: 23 allocs, 20 frees, 137,032 bytes allocated ==7080== ==7080== Searching for pointers to 3 not-freed blocks ==7080== Checked 130,392 bytes ==7080== ==7080== 48 bytes in 1 blocks are still reachable in loss record 1 of 3 ==7080== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7080== by 0x4E3B1AE: yajl_lex_alloc (in /lib/libyajl.so.1) ==7080== by 0x4E3B029: yajl_alloc (in /lib/libyajl.so.1) ==7080== by 0x4011A2: main (input.c:130) ==7080== ==7080== 104 bytes in 1 blocks are still reachable in loss record 2 of 3 ==7080== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7080== by 0x4E3AFDF: yajl_alloc (in /lib/libyajl.so.1) ==7080== by 0x4011A2: main (input.c:130) ==7080== ==7080== 4,096 bytes in 1 blocks are still reachable in loss record 3 of 3 ==7080== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7080== by 0x50AF1D4: _IO_file_doallocate (filedoalloc.c:127) ==7080== by 0x50BD593: _IO_doallocbuf (genops.c:398) ==7080== by 0x50BB09B: _IO_file_xsgetn (fileops.c:1375) ==7080== by 0x50B0235: fread (iofread.c:38) ==7080== by 0x401262: fread (stdio2.h:295) ==7080== by 0x401262: main (input.c:133) ==7080== ==7080== LEAK SUMMARY: ==7080== definitely lost: 0 bytes in 0 blocks ==7080== indirectly lost: 0 bytes in 0 blocks ==7080== possibly lost: 0 bytes in 0 blocks ==7080== still reachable: 4,248 bytes in 3 blocks ==7080== suppressed: 0 bytes in 0 blocks ==7080== ==7080== Use --track-origins=yes to see where uninitialised values come from ==7080== ERROR SUMMARY: 69 errors from 8 contexts (suppressed: 0 from 0) ==7080== ==7080== 1 errors in context 1 of 8: ==7080== Invalid read of size 8 ==7080== at 0x4E3B215: yajl_lex_free (in /lib/libyajl.so.1) ==7080== by 0x4E3B109: yajl_free (in /lib/libyajl.so.1) ==7080== by 0x4013E3: main (input.c:167) ==7080== Address 0x60540c380 is not stack'd, malloc'd or (recently) free'd ==7080== ==7080== ==7080== 1 errors in context 2 of 8: ==7080== Invalid read of size 4 ==7080== at 0x4E3ED32: yajl_gen_array_close (in /lib/libyajl.so.1) ==7080== by 0x4018B0: reformat_end_array (input.c:70) ==7080== by 0x4E3CFE3: yajl_do_parse (in /lib/libyajl.so.1) ==7080== by 0x4012C0: main (input.c:149) ==7080== Address 0x540c400 is 0 bytes after a block of size 48 alloc'd ==7080== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7080== by 0x4E3B1AE: yajl_lex_alloc (in /lib/libyajl.so.1) ==7080== by 0x4E3B029: yajl_alloc (in /lib/libyajl.so.1) ==7080== by 0x4011A2: main (input.c:130) ==7080== ==7080== ==7080== 3 errors in context 3 of 8: ==7080== Conditional jump or move depends on uninitialised value(s) ==7080== at 0x4E3EB6E: yajl_gen_array_open (in /lib/libyajl.so.1) ==7080== by 0x401900: reformat_start_array (input.c:63) ==7080== by 0x4E3CDCE: yajl_do_parse (in /lib/libyajl.so.1) ==7080== by 0x4012C0: main (input.c:149) ==7080== ==7080== ==7080== 3 errors in context 4 of 8: ==7080== Conditional jump or move depends on uninitialised value(s) ==7080== at 0x4E3EB69: yajl_gen_array_open (in /lib/libyajl.so.1) ==7080== by 0x401900: reformat_start_array (input.c:63) ==7080== by 0x4E3CDCE: yajl_do_parse (in /lib/libyajl.so.1) ==7080== by 0x4012C0: main (input.c:149) ==7080== ==7080== ==7080== 3 errors in context 5 of 8: ==7080== Conditional jump or move depends on uninitialised value(s) ==7080== at 0x4E3EB59: yajl_gen_array_open (in /lib/libyajl.so.1) ==7080== by 0x401900: reformat_start_array (input.c:63) ==7080== by 0x4E3CDCE: yajl_do_parse (in /lib/libyajl.so.1) ==7080== by 0x4012C0: main (input.c:149) ==7080== ==7080== ==7080== 3 errors in context 6 of 8: ==7080== Conditional jump or move depends on uninitialised value(s) ==7080== at 0x4E3EB51: yajl_gen_array_open (in /lib/libyajl.so.1) ==7080== by 0x401900: reformat_start_array (input.c:63) ==7080== by 0x4E3CDCE: yajl_do_parse (in /lib/libyajl.so.1) ==7080== by 0x4012C0: main (input.c:149) ==7080== ==7080== ==7080== 3 errors in context 7 of 8: ==7080== Conditional jump or move depends on uninitialised value(s) ==7080== at 0x4E3EB43: yajl_gen_array_open (in /lib/libyajl.so.1) ==7080== by 0x401900: reformat_start_array (input.c:63) ==7080== by 0x4E3CDCE: yajl_do_parse (in /lib/libyajl.so.1) ==7080== by 0x4012C0: main (input.c:149) ==7080== ==7080== ==7080== 52 errors in context 8 of 8: ==7080== Invalid read of size 4 ==7080== at 0x4E3EB32: yajl_gen_array_open (in /lib/libyajl.so.1) ==7080== by 0x401900: reformat_start_array (input.c:63) ==7080== by 0x4E3CDCE: yajl_do_parse (in /lib/libyajl.so.1) ==7080== by 0x4012C0: main (input.c:149) ==7080== Address 0x540c280 is 0 bytes after a block of size 576 alloc'd ==7080== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==7080== by 0x4E3D85D: yajl_gen_alloc2 (in /lib/libyajl.so.1) ==7080== by 0x40118B: main (input.c:127)

PoC: [[[[[{"ARY":[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],{"AR":[{"URY":[[[], "",{" R":[ "",{" R":{" R":[ "",{" R":[[],{"AR":{" ;":[[[[],{"AR":[{"URY":[[],[[[9],[], "",{" R":[ "",{" R":["",{" R":[ "",{" R":[[],{"AR R":[[],{" URY":[[[9],[:["",{" R":["",{" R":[ "",{" R"D[[],{"AR":[[],{"AR":[{"URAR":{" R":[[], "",[],{"AR":[ ,[{"Y":[[],{"AR":[{"URY":[[],[ "",{" R":[ "",{" [[[[[],{" R":[ "",{" R" [[],{"RY":[[],{"AR":[{"URY":[[],[[[9],[], "",{" R":[ "",{" R":["",{" R":[ "",{" R":[[],{"AR":{" R":[[],{" URY":[[],[[[9],[],{" R":[ ""{"[

berrange commented 1 year ago

Similarly to #204, I can reproduce this on the 1.x branch, but I can't reproduce in master. A git bisect suggests it was fixed by #25, so anyone on any 2.x.y release and/or master should be ok.