|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2017-06-25 18:29 UTC] nikic@php.net
[2017-06-27 16:59 UTC] nguyenluan dot vnn at gmail dot com
[2017-07-02 21:28 UTC] stas@php.net
-Status: Open
+Status: Duplicate
[2017-07-02 21:28 UTC] stas@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 16:00:02 2025 UTC |
Description: ------------ I found a problem with wddx extension while processing boolean element with empty value. Please refer to this code: static void php_wddx_push_element(void *user_data, const XML_Char *name, const XML_Char **atts) { ... } else if (!strcmp(name, EL_BOOLEAN)) { int i; if (atts) for (i = 0; atts[i]; i++) { if (!strcmp(atts[i], EL_VALUE) && atts[i+1] && atts[i+1][0]) { ent.type = ST_BOOLEAN; SET_STACK_VARNAME; ALLOC_ZVAL(ent.data); INIT_PZVAL(ent.data); Z_TYPE_P(ent.data) = IS_BOOL; wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry)); php_wddx_process_data(user_data, atts[i+1], strlen(atts[i+1])); break; } } else { (1) code to process empty value ent.type = ST_BOOLEAN; SET_STACK_VARNAME; ZVAL_FALSE(&ent.data); (2) bug here wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry)); } } ... } When opening boolean element with empty value php_wddx_push_element() function try to set an empty st_entry.data and push it to the wddx_stack using ZVAL_FALSE. In this case, I guess the ZVAL_FALSE failed to identify data type and set wrong value to st_entry ent structure, it sets 0x300000000 to st_entry ent.data. Later, when wddx_stack_destroy(&stack) is called in php_wddx_deserialize_ex(), efree() will try to free this invalid st_entry ent.data pointer and crashes PHP. static int wddx_stack_destroy(wddx_stack *stack) { register int i; if (stack->elements) { for (i = 0; i < stack->top; i++) { if (((st_entry *)stack->elements[i])->data && ((st_entry *)stack->elements[i])->type != ST_FIELD) { zval_ptr_dtor(&((st_entry *)stack->elements[i])->data); } if (((st_entry *)stack->elements[i])->varname) { efree(((st_entry *)stack->elements[i])->varname); (3) Free and crash here } efree(stack->elements[i]); } efree(stack->elements); } return SUCCESS; } Please refer to the gdb trace back and PHP test script for more information. Test script: --------------- <?php $xml = <<<EOF <boolean> EOF; $wddx = wddx_deserialize($xml); var_dump($wddx); ?> Expected result: ---------------- No crash. Return NULL. Actual result: -------------- user@user:~/Desktop/php-5.6.30_pure$ gdb -q sapi/cli/php Reading symbols from sapi/cli/php...done. warning: File "/home/user/Desktop/php-5.6.30_pure/.gdbinit" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load". To enable execution of this file add add-auto-load-safe-path /home/user/Desktop/php-5.6.30_pure/.gdbinit line to your configuration file "/home/user/.gdbinit". To completely disable this security protection add set auto-load safe-path / line to your configuration file "/home/user/.gdbinit". For more information about this security protection see the "Auto-loading safe path" section in the GDB manual. E.g., run from the shell: info "(gdb)Auto-loading safe path" gdb-peda$ b wddx.c:816 Breakpoint 1 at 0x7c5a69: file /home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c, line 816. gdb-peda$ r ../crash1.php Starting program: /home/user/Desktop/php-5.6.30_pure/sapi/cli/php ../crash1.php [----------------------------------registers-----------------------------------] RAX: 0x0 RBX: 0x120f187 --> 0x6e61656c6f6f62 ('boolean') RCX: 0x7fffffffa6d0 --> 0x4000000000 ('') RDX: 0x0 RSI: 0xd36cd1 --> 0x6e61656c6f6f62 ('boolean') RDI: 0x120f5a0 --> 0x6e61656c6f6f62 ('boolean') RBP: 0x7fffffffa3a0 --> 0x7fffffffa420 --> 0x120e9d0 --> 0x120ed90 --> 0x0 RSP: 0x7fffffffa2e0 --> 0x0 RIP: 0x7c5a69 (<php_wddx_push_element+2126>: mov rax,QWORD PTR [rbp-0x70]) R8 : 0x120f187 --> 0x6e61656c6f6f62 ('boolean') R9 : 0x120ffb1 ("boolean>") R10: 0x7ffff72eeb88 --> 0x120f5b0 --> 0x0 R11: 0x7ffff73c8820 (<xmlStrdup>: push rbp) R12: 0x120ffb0 ("<boolean>") R13: 0x120ffb8 --> 0x3e ('>') R14: 0x1 R15: 0x0 EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x7c5a57 <php_wddx_push_element+2108>: jne 0x7c5861 <php_wddx_push_element+1606> 0x7c5a5d <php_wddx_push_element+2114>: jmp 0x7c66bb <php_wddx_push_element+5280> 0x7c5a62 <php_wddx_push_element+2119>: mov DWORD PTR [rbp-0x38],0x1 => 0x7c5a69 <php_wddx_push_element+2126>: mov rax,QWORD PTR [rbp-0x70] 0x7c5a6d <php_wddx_push_element+2130>: mov rax,QWORD PTR [rax+0x8] 0x7c5a71 <php_wddx_push_element+2134>: test rax,rax 0x7c5a74 <php_wddx_push_element+2137>: je 0x7c5ad6 <php_wddx_push_element+2235> 0x7c5a76 <php_wddx_push_element+2139>: mov rax,QWORD PTR [rbp-0x70] [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa2e0 --> 0x0 0008| 0x7fffffffa2e8 --> 0x0 0016| 0x7fffffffa2f0 --> 0x120f5a0 --> 0x6e61656c6f6f62 ('boolean') 0024| 0x7fffffffa2f8 --> 0x7fffffffa6d0 --> 0x4000000000 ('') 0032| 0x7fffffffa300 --> 0x0 0040| 0x7fffffffa308 --> 0x7c00000077 ('w') 0048| 0x7fffffffa310 --> 0x7fffffffa460 --> 0xffff800000005b51 0056| 0x7fffffffa318 --> 0x7ffff742efbe (add rbp,QWORD PTR [rbx+0x8]) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Breakpoint 1, php_wddx_push_element (user_data=0x7fffffffa6d0, name=0x120f5a0 "boolean", atts=0x0) at /home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c:816 816 SET_STACK_VARNAME; gdb-peda$ p *&ent $1 = { data = 0x0, type = ST_BOOLEAN, varname = 0x120ffb1 "boolean>" } gdb-peda$ n [----------------------------------registers-----------------------------------] RAX: 0x0 RBX: 0x120f187 --> 0x6e61656c6f6f62 ('boolean') RCX: 0x7fffffffa6d0 --> 0x4000000000 ('') RDX: 0x0 RSI: 0xd36cd1 --> 0x6e61656c6f6f62 ('boolean') RDI: 0x120f5a0 --> 0x6e61656c6f6f62 ('boolean') RBP: 0x7fffffffa3a0 --> 0x7fffffffa420 --> 0x120e9d0 --> 0x120ed90 --> 0x0 RSP: 0x7fffffffa2e0 --> 0x0 RIP: 0x7c5ade (<php_wddx_push_element+2243>: lea rax,[rbp-0x40]) R8 : 0x120f187 --> 0x6e61656c6f6f62 ('boolean') R9 : 0x120ffb1 ("boolean>") R10: 0x7ffff72eeb88 --> 0x120f5b0 --> 0x0 R11: 0x7ffff73c8820 (<xmlStrdup>: push rbp) R12: 0x120ffb0 ("<boolean>") R13: 0x120ffb8 --> 0x3e ('>') R14: 0x1 R15: 0x0 EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x7c5acc <php_wddx_push_element+2225>: mov QWORD PTR [rax+0x8],0x0 0x7c5ad4 <php_wddx_push_element+2233>: jmp 0x7c5ade <php_wddx_push_element+2243> 0x7c5ad6 <php_wddx_push_element+2235>: mov QWORD PTR [rbp-0x30],0x0 => 0x7c5ade <php_wddx_push_element+2243>: lea rax,[rbp-0x40] 0x7c5ae2 <php_wddx_push_element+2247>: mov QWORD PTR [rbp-0x68],rax 0x7c5ae6 <php_wddx_push_element+2251>: mov rax,QWORD PTR [rbp-0x68] 0x7c5aea <php_wddx_push_element+2255>: mov QWORD PTR [rax],0x0 0x7c5af1 <php_wddx_push_element+2262>: mov rax,QWORD PTR [rbp-0x68] [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa2e0 --> 0x0 0008| 0x7fffffffa2e8 --> 0x0 0016| 0x7fffffffa2f0 --> 0x120f5a0 --> 0x6e61656c6f6f62 ('boolean') 0024| 0x7fffffffa2f8 --> 0x7fffffffa6d0 --> 0x4000000000 ('') 0032| 0x7fffffffa300 --> 0x0 0040| 0x7fffffffa308 --> 0x7c00000077 ('w') 0048| 0x7fffffffa310 --> 0x7fffffffa460 --> 0xffff800000005b51 0056| 0x7fffffffa318 --> 0x7ffff742efbe (add rbp,QWORD PTR [rbx+0x8]) [------------------------------------------------------------------------------] Legend: code, data, rodata, value 817 ZVAL_FALSE(&ent.data); gdb-peda$ p *&ent (1) everything stills good here $2 = { data = 0x0, type = ST_BOOLEAN, varname = 0x0 } gdb-peda$ n [----------------------------------registers-----------------------------------] RAX: 0x7fffffffa360 --> 0x0 RBX: 0x120f187 --> 0x6e61656c6f6f62 ('boolean') RCX: 0x7fffffffa6d0 --> 0x4000000000 ('') RDX: 0x0 RSI: 0xd36cd1 --> 0x6e61656c6f6f62 ('boolean') RDI: 0x120f5a0 --> 0x6e61656c6f6f62 ('boolean') RBP: 0x7fffffffa3a0 --> 0x7fffffffa420 --> 0x120e9d0 --> 0x120ed90 --> 0x0 RSP: 0x7fffffffa2e0 --> 0x0 RIP: 0x7c5af9 (<php_wddx_push_element+2270>: lea rcx,[rbp-0x40]) R8 : 0x120f187 --> 0x6e61656c6f6f62 ('boolean') R9 : 0x120ffb1 ("boolean>") R10: 0x7ffff72eeb88 --> 0x120f5b0 --> 0x0 R11: 0x7ffff73c8820 (<xmlStrdup>: push rbp) R12: 0x120ffb0 ("<boolean>") R13: 0x120ffb8 --> 0x3e ('>') R14: 0x1 R15: 0x0 EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x7c5aea <php_wddx_push_element+2255>: mov QWORD PTR [rax],0x0 0x7c5af1 <php_wddx_push_element+2262>: mov rax,QWORD PTR [rbp-0x68] 0x7c5af5 <php_wddx_push_element+2266>: mov BYTE PTR [rax+0x14],0x3 => 0x7c5af9 <php_wddx_push_element+2270>: lea rcx,[rbp-0x40] 0x7c5afd <php_wddx_push_element+2274>: mov rax,QWORD PTR [rbp-0x70] 0x7c5b01 <php_wddx_push_element+2278>: mov edx,0x18 0x7c5b06 <php_wddx_push_element+2283>: mov rsi,rcx 0x7c5b09 <php_wddx_push_element+2286>: mov rdi,rax [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa2e0 --> 0x0 0008| 0x7fffffffa2e8 --> 0x0 0016| 0x7fffffffa2f0 --> 0x120f5a0 --> 0x6e61656c6f6f62 ('boolean') 0024| 0x7fffffffa2f8 --> 0x7fffffffa6d0 --> 0x4000000000 ('') 0032| 0x7fffffffa300 --> 0x0 0040| 0x7fffffffa308 --> 0x7c00000077 ('w') 0048| 0x7fffffffa310 --> 0x7fffffffa460 --> 0xffff800000005b51 0056| 0x7fffffffa318 --> 0x7ffff742efbe (add rbp,QWORD PTR [rbx+0x8]) [------------------------------------------------------------------------------] Legend: code, data, rodata, value 818 wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry)); gdb-peda$ p *&ent (2) ZVAL_FALSE set varname to an invalid address 0x300000000 which is not in any valid memory region $3 = { data = 0x0, type = ST_BOOLEAN, varname = 0x300000000 <error: Cannot access memory at address 0x300000000> } gdb-peda$ c Continuing. Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0x2ffffffb0 RBX: 0x0 RCX: 0xd369e8 ("/home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c") RDX: 0x1 RSI: 0x300000000 RDI: 0x108ef80 --> 0x1 RBP: 0x7fffffffa5a0 --> 0x7fffffffa620 --> 0x7fffffffa650 --> 0x7fffffffa680 --> 0x7fffffffa700 --> 0x7fffffffa770 (--> ...) RSP: 0x7fffffffa520 --> 0x0 RIP: 0x83ccf6 (<zend_mm_check_ptr+339>: mov rdx,QWORD PTR [rax+0x8]) R8 : 0xee R9 : 0x0 R10: 0x2a2 R11: 0x7ffff70bf390 --> 0xfffda380fffda0af R12: 0x4207d0 (<_start>: xor ebp,ebp) R13: 0x7fffffffe1a0 --> 0x2 R14: 0x0 R15: 0x0 EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x83ccea <zend_mm_check_ptr+327>: sub rax,0x50 0x83ccee <zend_mm_check_ptr+331>: mov QWORD PTR [rbp-0x30],rax 0x83ccf2 <zend_mm_check_ptr+335>: mov rax,QWORD PTR [rbp-0x30] => 0x83ccf6 <zend_mm_check_ptr+339>: mov rdx,QWORD PTR [rax+0x8] 0x83ccfa <zend_mm_check_ptr+343>: mov rax,QWORD PTR [rbp-0x30] 0x83ccfe <zend_mm_check_ptr+347>: mov rax,QWORD PTR [rax+0x8] 0x83cd02 <zend_mm_check_ptr+351>: and rax,0xfffffffffffffffc 0x83cd06 <zend_mm_check_ptr+355>: mov rcx,rax [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa520 --> 0x0 0008| 0x7fffffffa528 --> 0x0 0016| 0x7fffffffa530 --> 0xd369e8 ("/home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c") 0024| 0x7fffffffa538 --> 0x1000000ee 0032| 0x7fffffffa540 --> 0x300000000 0040| 0x7fffffffa548 --> 0x108ef80 --> 0x1 0048| 0x7fffffffa550 --> 0xf7fd3f68 0056| 0x7fffffffa558 --> 0x100000000 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x000000000083ccf6 in zend_mm_check_ptr (heap=0x108ef80, ptr=0x300000000, silent=0x1, __zend_filename=0xd369e8 "/home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c", __zend_lineno=0xee, __zend_orig_filename=0x0, __zend_orig_lineno=0x0) at /home/user/Desktop/php-5.6.30_pure/Zend/zend_alloc.c:1384 1384 if (p->info._size != ZEND_MM_NEXT_BLOCK(p)->info._prev) { gdb-peda$ bt #0 0x000000000083ccf6 in zend_mm_check_ptr (heap=0x108ef80, ptr=0x300000000, silent=0x1, __zend_filename=0xd369e8 "/home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c", __zend_lineno=0xee, __zend_orig_filename=0x0, __zend_orig_lineno=0x0) at /home/user/Desktop/php-5.6.30_pure/Zend/zend_alloc.c:1384 #1 0x000000000083e95d in _zend_mm_free_int (heap=0x108ef80, p=0x300000000, __zend_filename=0xd369e8 "/home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c", __zend_lineno=0xee, __zend_orig_filename=0x0, __zend_orig_lineno=0x0) at /home/user/Desktop/php-5.6.30_pure/Zend/zend_alloc.c:2068 #2 0x000000000083ff6e in _efree (ptr=0x300000000, __zend_filename=0xd369e8 "/home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c", __zend_lineno=0xee, __zend_orig_filename=0x0, __zend_orig_lineno=0x0) at /home/user/Desktop/php-5.6.30_pure/Zend/zend_alloc.c:2440 #3 0x00000000007bfe21 in wddx_stack_destroy (stack=0x7fffffffa6d0) at /home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c:238 #4 0x00000000007c7960 in php_wddx_deserialize_ex (value=0x7ffff7ebc0a8 "<boolean>", vallen=0x9, return_value=0x7ffff7fd13c8) at /home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c:1206 #5 0x00000000007c8cc9 in zif_wddx_deserialize (ht=0x1, return_value=0x7ffff7fd13c8, return_value_ptr=0x7ffff7f9a220, this_ptr=0x0, return_value_used=0x1) at /home/user/Desktop/php-5.6.30_pure/ext/wddx/wddx.c:1405 #6 0x00000000008c38a7 in zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7f9a258) at /home/user/Desktop/php-5.6.30_pure/Zend/zend_vm_execute.h:558 #7 0x00000000008c93d2 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0x7ffff7f9a258) at /home/user/Desktop/php-5.6.30_pure/Zend/zend_vm_execute.h:2602 #8 0x00000000008c2f0f in execute_ex (execute_data=0x7ffff7f9a258) at /home/user/Desktop/php-5.6.30_pure/Zend/zend_vm_execute.h:363 #9 0x00000000008c2f96 in zend_execute (op_array=0x7ffff7fd22f8) at /home/user/Desktop/php-5.6.30_pure/Zend/zend_vm_execute.h:388 #10 0x000000000087b946 in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at /home/user/Desktop/php-5.6.30_pure/Zend/zend.c:1341 #11 0x00000000007dc96b in php_execute_script (primary_file=0x7fffffffcd70) at /home/user/Desktop/php-5.6.30_pure/main/main.c:2613 #12 0x00000000009386b6 in do_cli (argc=0x2, argv=0x108ecc0) at /home/user/Desktop/php-5.6.30_pure/sapi/cli/php_cli.c:998 #13 0x0000000000939a19 in main (argc=0x2, argv=0x108ecc0) at /home/user/Desktop/php-5.6.30_pure/sapi/cli/php_cli.c:1382 #14 0x00007ffff6f4b830 in __libc_start_main (main=0x9391fc <main>, argc=0x2, argv=0x7fffffffe1a8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe198) at ../csu/libc-start.c:291 #15 0x00000000004207f9 in _start ()