|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2017-04-17 10:13 UTC] marcel dot boehme at acm dot org
Description: ------------ Dear all, In a fuzzing session with AFLGo, a directed version of AFL/AFLFast, we found a stack-based buffer overflow in LibXML2 (git master) -- causing an invalid WRITE of size 4925. Thanks also to Thuan Pham! Our upstream bug report (currently non-public): https://bugzilla.gnome.org/show_bug.cgi?id=781333 $ ../libxml2/xmllint --version /src/libxml2/.libs/lt-xmllint: using libxml version 20904-GITv2.9.4-16-g0741801 compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude Iconv ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug $ sapi/cli/php --version PHP 7.2.0-dev (cli) (built: Apr 17 2017 09:22:02) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.2.0-dev, Copyright (c) 1998-2017 Zend Technologies How to reproduce: * Configure and build Libxml2 with ASAN * Configure PHP --with-libxml-dir .. * Build PHP with ASAN $ php test.xml (see below) Test script: --------------- <?php $doc = new DOMDocument(); $doc->validateOnParse = TRUE; $doc->loadXML('<!DOCTYPEa[<!ELEMENT a (F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)><!ATTLIST a><!ELEMENT b EMPTY><!ATTLIST b s CDATA #IMPLIED>]><a/>'); var_dump($err) ?> Expected result: ---------------- Warning: DOMDocument::loadXML(): Element a content does not follow the DTD, expecting (F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000: ..., got in Entity, line: 1 in /src/php-src/test.php on line 4 NULL Actual result: -------------- ==131756==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffeb7f9dec8 at pc 0x0000004bb620 bp 0x7ffeb7f9ca60 sp 0x7ffeb7f9c210 WRITE of size 4925 at 0x7ffeb7f9dec8 thread T0 #0 0x4bb61f in __interceptor_strcat /src/llvm/projects/compiler-rt/lib/asan/asan_interceptors.cc:491 #1 0x7f43cee2485c in xmlSnprintfElementContent__internal_alias /src/libxml2/valid.c:1279:3 #2 0x7f43cee59cc8 in xmlValidateElementContent /src/libxml2/valid.c:5445:6 #3 0x7f43cee59cc8 in xmlValidateOneElement__internal_alias /src/libxml2/valid.c:6152 #4 0x7f43cf2bb096 in xmlSAX2EndElementNs__internal_alias /src/libxml2/SAX2.c:2467:24 #5 0x7f43ced3a4ca in xmlParseElement__internal_alias /src/libxml2/parser.c:10212:3 #6 0x7f43ced53748 in xmlParseDocument__internal_alias /src/libxml2/parser.c:10962:2 #7 0x1212387 in dom_document_parser /src/php-src/ext/dom/document.c:1449:2 #8 0x1212387 in dom_parse_document /src/php-src/ext/dom/document.c:1505 #9 0x20da413 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER /src/php-src/Zend/zend_vm_execute.h:954:4 #10 0x1ee529e in execute_ex /src/php-src/Zend/zend_vm_execute.h:432:7 #11 0x1ee663e in zend_execute /src/php-src/Zend/zend_vm_execute.h:474:2 #12 0x1cfa501 in zend_execute_scripts /src/php-src/Zend/zend.c:1537:4 #13 0x1a17ae4 in php_execute_script /src/php-src/main/main.c:2548:14 #14 0x236834c in do_cli /src/php-src/sapi/cli/php_cli.c:997:5 #15 0x23640df in main /src/php-src/sapi/cli/php_cli.c:1390:18 #16 0x7f43ce1e482f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #17 0x43b238 in _start (/src/php-src/sapi/cli/php+0x43b238) Address 0x7ffeb7f9dec8 is located in stack of thread T0 at offset 5128 in frame #0 0x7f43cee52dcf in xmlValidateOneElement__internal_alias /src/libxml2/valid.c:5943 This frame has 5 object(s): [32, 82) 'fn.i' (line 5288) [128, 5128) 'expr.i' (line 5441) [5392, 10392) 'list.i' (line 5442) <== Memory access at offset 5128 partially underflows this variable [10656, 10660) 'extsubset' (line 5950) [10672, 10722) 'fn' (line 6063) HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow /src/llvm/projects/compiler-rt/lib/asan/asan_interceptors.cc:491 in __interceptor_strcat PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Dec 07 16:00:01 2025 UTC |
Upstream is not responding. Attaching a patch and analysis here. Here is a quick analysis: The function xmlSnprintfElementContent in valid.c is supposed to recursively dump the element content definition into a char buffer 'buf' of size 'size'. The variable len is assigned strlen(buf). If the content->type is XML_ELEMENT_CONTENT_ELEMENT, then (i) the content->prefix is appended to buf (if it actually fits) whereupon (ii) content->name is written to the buffer. However, the check whether the content->name actually fits also uses 'len' rather than the updated buffer length strlen(buf). This allows us to write about "size" many bytes beyond the allocated memory. Proposed Patch: diff --git a/valid.c b/valid.c index 8bd8336..e04479e 100644 --- a/valid.c +++ b/valid.c @@ -1270,6 +1270,7 @@ xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int } strcat(buf, (char *) content->prefix); strcat(buf, ":"); + len += xmlStrlen(content->prefix); } if (size - len < xmlStrlen(content->name) + 10) { strcat(buf, " ...");