lloyd/yajl

Double free vulnerability in yajl_lex_free - 1.0.12

zeroinside opened this issue · 1 comments

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":[ ""{"[

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.