|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2016-09-26 04:26 UTC] stas@php.net
-Assigned To:
+Assigned To: stas
[2016-09-26 04:26 UTC] stas@php.net
[2016-09-26 06:28 UTC] nguyenluan dot vnn at gmail dot com
[2016-10-11 23:45 UTC] stas@php.net
[2016-10-11 23:45 UTC] stas@php.net
-Status: Assigned
+Status: Closed
[2016-10-12 14:26 UTC] ab@php.net
[2016-10-12 23:26 UTC] ab@php.net
[2016-10-12 23:35 UTC] ab@php.net
[2016-10-14 01:02 UTC] ab@php.net
[2016-10-14 02:23 UTC] ab@php.net
[2016-10-14 02:23 UTC] ab@php.net
[2016-10-14 02:23 UTC] ab@php.net
[2016-10-17 10:06 UTC] bwoebi@php.net
[2016-10-17 10:07 UTC] bwoebi@php.net
[2016-10-17 10:07 UTC] bwoebi@php.net
[2017-02-13 02:07 UTC] stas@php.net
-Type: Security
+Type: Bug
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 16:00:01 2025 UTC |
Description: ------------ As you can see in the code below in dom_document_save_html function: } else { #if LIBXML_VERSION >= 20623 htmlDocDumpMemoryFormat(docp, &mem, &size, format); #else htmlDocDumpMemory(docp, &mem, &size); #endif if (!size) { RETVAL_FALSE; } else { RETVAL_STRINGL((const char*) mem, size, 1); // missing NULL check for *mem when size != 0 } if (mem) xmlFree(mem); } If size != 0, a string will be retured. I tested with a HTML file > 2Gb and break at RETVAL_STRINGL((const char*) mem, size, 1);. The *mem is NULL and size != 0. This lead to a memory access violation when RETVAL_STRINGL call memcpy. If *mem is not NULL, a string with size > 2GB is returned. This is also considered as security issue in PHP. Test script: --------------- Python script to create HTML file: #! /usr/bin/env python3 f = open('html.html', 'w'); f.write('<html>\n') for _ in range(0x100): f.write('\t<p>') for _ in range(0x100): f.write('a'*(0x8000)) f.write('</p>\n') f.write('</html>') f.close() PHP script: <?php ini_set('memory_limit', -1); $doc = new DOMDocument(); $doc->loadHTMLFile('/home/user/Desktop/test/string/html.html'); $str = $doc->saveHTML(); var_dump(strlen($str)); ?> Expected result: ---------------- No crash, no string return since HTML string input is larger than 2Gb. Actual result: -------------- gdb-peda$ r ../test/string/test_domhtml.php Starting program: /home/user/Desktop/php-5.6.26/sapi/cli/php ../test/string/test_domhtml.php [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [----------------------------------registers-----------------------------------] RAX: 0x80000985 RBX: 0xa66943 (<execute_ex>: push rbp) RCX: 0x0 RDX: 0x7ffff4f1d778 --> 0x163a8b0 --> 0x20 (' ') RSI: 0xffffffff RDI: 0x0 RBP: 0x7fffffffa610 --> 0x7fffffffa680 --> 0x7fffffffa6a0 --> 0x7fffffffa6d0 --> 0x7fffffffa700 --> 0x7fffffffa860 --> 0x7fffffffcad0 --> 0x7fffffffde10 --> 0x7fffffffdf70 --> 0x0 RSP: 0x7fffffffa530 --> 0x14a2650 --> 0x5d00000001 RIP: 0x60c425 (<zif_dom_document_save_html+1061>: mov rax,QWORD PTR [rbp-0x80]) R8 : 0x7fffff00 R9 : 0x163a8c0 --> 0x0 R10: 0x7ffff4f1d7b8 --> 0x1656fc0 ("aaaaaaaaAPy\001") R11: 0x7ffff4f1d7b0 --> 0x0 R12: 0x4397d0 (<_start>: xor ebp,ebp) R13: 0x7fffffffe050 --> 0x2 R14: 0x0 R15: 0x0 EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x60c41b <zif_dom_document_save_html+1051>: mov rax,QWORD PTR [rbp-0x18] 0x60c41f <zif_dom_document_save_html+1055>: mov BYTE PTR [rax+0x14],0x3 0x60c423 <zif_dom_document_save_html+1059>: jmp 0x60c48d <zif_dom_document_save_html+1165> => 0x60c425 <zif_dom_document_save_html+1061>: mov rax,QWORD PTR [rbp-0x80] 0x60c429 <zif_dom_document_save_html+1065>: mov QWORD PTR [rbp-0x10],rax 0x60c42d <zif_dom_document_save_html+1069>: mov eax,DWORD PTR [rbp-0xa4] 0x60c433 <zif_dom_document_save_html+1075>: mov DWORD PTR [rbp-0x94],eax 0x60c439 <zif_dom_document_save_html+1081>: mov rax,QWORD PTR [rbp-0xc0] [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa530 --> 0x14a2650 --> 0x5d00000001 0008| 0x7fffffffa538 --> 0x103e510 ("/home/user/Desktop/php-5.6.26/Zend/zend_vm_execute.h") 0016| 0x7fffffffa540 --> 0x7ffff7faff50 --> 0x5a5a5a5a00000001 0024| 0x7fffffffa548 --> 0x7ffff7f77250 --> 0x7ffff7fafed8 ('Z' <repeats 16 times>, "\001") 0032| 0x7fffffffa550 --> 0x7ffff7fafed8 ('Z' <repeats 16 times>, "\001") 0040| 0x7fffffffa558 --> 0x1 0048| 0x7fffffffa560 --> 0x7ffff7fafe88 --> 0x7fff6def5880 ('a' <repeats 200 times>...) 0056| 0x7fffffffa568 --> 0x8000098500000078 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Breakpoint 1, zif_dom_document_save_html (ht=0x0, return_value=0x7ffff7fafed8, return_value_ptr=0x7ffff7f77250, this_ptr=0x7ffff7faff50, return_value_used=0x1) at /home/user/Desktop/php-5.6.26/ext/dom/document.c:2333 2333 RETVAL_STRINGL((const char*) mem, size, 1); gdb-peda$ p size $1 = 0x80000985 <- size is larger than 2Gb gdb-peda$ b zend_alloc.c:2664 Breakpoint 2 at 0x9e7f82: file /home/user/Desktop/php-5.6.26/Zend/zend_alloc.c, line 2664. gdb-peda$ c Continuing. [----------------------------------registers-----------------------------------] RAX: 0x0 RBX: 0xa66943 (<execute_ex>: push rbp) RCX: 0x7ffff4c5387a (<mmap64+10>: cmp rax,0xfffffffffffff001) RDX: 0x8003eb38 RSI: 0x7fff3261aa00 --> 0x7fffa8740c08 ('a' <repeats 200 times>...) RDI: 0x13c0670 --> 0x1 RBP: 0x7fffffffa520 --> 0x7fffffffa610 --> 0x7fffffffa680 --> 0x7fffffffa6a0 --> 0x7fffffffa6d0 --> 0x7fffffffa700 --> 0x7fffffffa860 --> 0x7fffffffcad0 --> 0x7fffffffde10 --> 0x7fffffffdf70 --> 0x0 RSP: 0x7fffffffa4e0 --> 0x0 RIP: 0x9e7f82 (<_estrndup+156>: mov edx,DWORD PTR [rbp-0x1c]) R8 : 0xffffffff R9 : 0x0 R10: 0x22 ('"') R11: 0xf4f1d701 R12: 0x4397d0 (<_start>: xor ebp,ebp) R13: 0x7fffffffe050 --> 0x2 R14: 0x0 R15: 0x0 EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x9e7f7a <_estrndup+148>: call rax 0x9e7f7c <_estrndup+150>: mov rax,QWORD PTR [rbp-0x8] 0x9e7f80 <_estrndup+154>: jmp 0x9e7fc4 <_estrndup+222> => 0x9e7f82 <_estrndup+156>: mov edx,DWORD PTR [rbp-0x1c] 0x9e7f85 <_estrndup+159>: mov rcx,QWORD PTR [rbp-0x18] 0x9e7f89 <_estrndup+163>: mov rax,QWORD PTR [rbp-0x8] 0x9e7f8d <_estrndup+167>: mov rsi,rcx 0x9e7f90 <_estrndup+170>: mov rdi,rax [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa4e0 --> 0x0 0008| 0x7fffffffa4e8 --> 0x0 0016| 0x7fffffffa4f0 --> 0x0 0024| 0x7fffffffa4f8 --> 0xbdf3a8 ("/home/user/Desktop/php-5.6.26/ext/dom/document.c") 0032| 0x7fffffffa500 --> 0x800009850000091d 0040| 0x7fffffffa508 --> 0x0 0048| 0x7fffffffa510 --> 0xa66943 (<execute_ex>: push rbp) 0056| 0x7fffffffa518 --> 0x7ffeb261a070 --> 0x0 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Breakpoint 2, _estrndup (s=0x0, length=0x80000985, __zend_filename=0xbdf3a8 "/home/user/Desktop/php-5.6.26/ext/dom/document.c", __zend_lineno=0x91d, __zend_orig_filename=0x0, __zend_orig_lineno=0x0) at /home/user/Desktop/php-5.6.26/Zend/zend_alloc.c:2664 2664 memcpy(p, s, length); gdb-peda$ p length $2 = 0x80000985 <- alloc length is larger than 2Gb gdb-peda$ p p $3 = 0x7ffeb261a070 "" gdb-peda$ p s $4 = 0x0 <- source string is NULL gdb-peda$ c Continuing. Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] RAX: 0xffff8000cd9e560b RBX: 0xa66943 (<execute_ex>: push rbp) RCX: 0x10000130a RDX: 0x80000985 RSI: 0x0 RDI: 0x7ffeb261a070 --> 0x0 RBP: 0x7fffffffa520 --> 0x7fffffffa610 --> 0x7fffffffa680 --> 0x7fffffffa6a0 --> 0x7fffffffa6d0 --> 0x7fffffffa700 --> 0x7fffffffa860 --> 0x7fffffffcad0 --> 0x7fffffffde10 --> 0x7fffffffdf70 --> 0x0 RSP: 0x7fffffffa4d8 --> 0x9e7f98 (<_estrndup+178>: mov edx,DWORD PTR [rbp-0x1c]) RIP: 0x7ffff4bf6ee0 (<__memcpy_sse2_unaligned+32>: movdqu xmm8,XMMWORD PTR [rsi]) R8 : 0xffffffff R9 : 0x0 R10: 0x22 ('"') R11: 0xf4f1d701 R12: 0x4397d0 (<_start>: xor ebp,ebp) R13: 0x7fffffffe050 --> 0x2 R14: 0x0 R15: 0x0 EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x7ffff4bf6ed0 <__memcpy_sse2_unaligned+16>: jb 0x7ffff4bf6fdd <__memcpy_sse2_unaligned+285> 0x7ffff4bf6ed6 <__memcpy_sse2_unaligned+22>: cmp rdx,0x10 0x7ffff4bf6eda <__memcpy_sse2_unaligned+26>: jbe 0x7ffff4bf706b <__memcpy_sse2_unaligned+427> => 0x7ffff4bf6ee0 <__memcpy_sse2_unaligned+32>: movdqu xmm8,XMMWORD PTR [rsi] 0x7ffff4bf6ee5 <__memcpy_sse2_unaligned+37>: cmp rdx,0x20 0x7ffff4bf6ee9 <__memcpy_sse2_unaligned+41>: movdqu XMMWORD PTR [rdi],xmm8 0x7ffff4bf6eee <__memcpy_sse2_unaligned+46>: movdqu xmm8,XMMWORD PTR [rsi+rdx*1-0x10] 0x7ffff4bf6ef5 <__memcpy_sse2_unaligned+53>: movdqu XMMWORD PTR [rdi+rdx*1-0x10],xmm8 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffa4d8 --> 0x9e7f98 (<_estrndup+178>: mov edx,DWORD PTR [rbp-0x1c]) 0008| 0x7fffffffa4e0 --> 0x0 0016| 0x7fffffffa4e8 --> 0x0 0024| 0x7fffffffa4f0 --> 0x0 0032| 0x7fffffffa4f8 --> 0xbdf3a8 ("/home/user/Desktop/php-5.6.26/ext/dom/document.c") 0040| 0x7fffffffa500 --> 0x800009850000091d 0048| 0x7fffffffa508 --> 0x0 0056| 0x7fffffffa510 --> 0xa66943 (<execute_ex>: push rbp) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:33 33 ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S: No such file or directory. gdb-peda$ bt #0 __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:33 #1 0x00000000009e7f98 in _estrndup (s=0x0, length=0x80000985, __zend_filename=0xbdf3a8 "/home/user/Desktop/php-5.6.26/ext/dom/document.c", __zend_lineno=0x91d, __zend_orig_filename=0x0, __zend_orig_lineno=0x0) at /home/user/Desktop/php-5.6.26/Zend/zend_alloc.c:2664 #2 0x000000000060c47b in zif_dom_document_save_html (ht=0x0, return_value=0x7ffff7fafed8, return_value_ptr=0x7ffff7f77250, this_ptr=0x7ffff7faff50, return_value_used=0x1) at /home/user/Desktop/php-5.6.26/ext/dom/document.c:2333 #3 0x0000000000a67334 in zend_do_fcall_common_helper_SPEC ( execute_data=0x7ffff7f77368) at /home/user/Desktop/php-5.6.26/Zend/zend_vm_execute.h:558 #4 0x0000000000a67b05 in ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER ( execute_data=0x7ffff7f77368) at /home/user/Desktop/php-5.6.26/Zend/zend_vm_execute.h:693 #5 0x0000000000a669a3 in execute_ex (execute_data=0x7ffff7f77368) at /home/user/Desktop/php-5.6.26/Zend/zend_vm_execute.h:363 #6 0x0000000000a66a2c in zend_execute (op_array=0x7ffff7fb0da0) at /home/user/Desktop/php-5.6.26/Zend/zend_vm_execute.h:388 #7 0x0000000000a21a50 in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at /home/user/Desktop/php-5.6.26/Zend/zend.c:1341 #8 0x0000000000986fbe in php_execute_script (primary_file=0x7fffffffcc10) at /home/user/Desktop/php-5.6.26/main/main.c:2613 #9 0x0000000000ad6225 in do_cli (argc=0x2, argv=0x13c03a0) at /home/user/Desktop/php-5.6.26/sapi/cli/php_cli.c:994 #10 0x0000000000ad757e in main (argc=0x2, argv=0x13c03a0) at /home/user/Desktop/php-5.6.26/sapi/cli/php_cli.c:1378 #11 0x00007ffff4b80f45 in __libc_start_main (main=0xad6d66 <main>, argc=0x2, argv=0x7fffffffe058, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe048) at libc-start.c:287 #12 0x00000000004397f9 in _start ()