Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use after free in php_dom.c #16150

Open
chibinz opened this issue Oct 1, 2024 · 3 comments
Open

Use after free in php_dom.c #16150

chibinz opened this issue Oct 1, 2024 · 3 comments

Comments

@chibinz
Copy link

chibinz commented Oct 1, 2024

Description

The following code:

<?php
$e1 = new DOMElement ( "X" , "x" );
$doc = new DOMDocument ( );
$frag = new DOMDocumentFragment (  );
$e2 = new DOMElement ( "H" );
$e3 = new DOMElement ( "W" );
$doc -> insertBefore ( $e3 , null );
$frag -> append ( $e1 );
$e2 -> append ( $frag );
$e3 -> insertBefore ( $e2 , null );

Resulted in this output:

=================================================================
==76313==ERROR: AddressSanitizer: heap-use-after-free on address 0x60c000007cc8 at pc 0x5575f984ec23 bp 0x7ffd2eab2470 sp 0x7ffd2eab2468
READ of size 4 at 0x60c000007cc8 thread T0
    #0 0x5575f984ec22 in dom_objects_free_storage /tmp/php-afl/ext/dom/php_dom.c:1448:13
    #1 0x5575faa513ff in zend_objects_store_del /tmp/php-afl/Zend/zend_objects_API.c:194:4
    #2 0x5575faaddd93 in rc_dtor_func /tmp/php-afl/Zend/zend_variables.c:57:2
    #3 0x5575faaddd93 in i_zval_ptr_dtor /tmp/php-afl/Zend/zend_variables.h:45:4
    #4 0x5575faaddd93 in zval_ptr_dtor /tmp/php-afl/Zend/zend_variables.c:84:2
    #5 0x5575fa90e37f in _zend_hash_del_el_ex /tmp/php-afl/Zend/zend_hash.c:1487:3
    #6 0x5575fa90e37f in _zend_hash_del_el /tmp/php-afl/Zend/zend_hash.c:1514:2
    #7 0x5575fa92262f in zend_hash_reverse_apply /tmp/php-afl/Zend/zend_hash.c:2230:5
    #8 0x5575fa5e110b in shutdown_destructors /tmp/php-afl/Zend/zend_execute_API.c:262:4
    #9 0x5575faafd109 in zend_call_destructors /tmp/php-afl/Zend/zend.c:1326:3
    #10 0x5575fa1cc40b in php_request_shutdown /tmp/php-afl/main/main.c:1912:3
    #11 0x5575fab0edcb in do_cli /tmp/php-afl/sapi/cli/php_cli.c:1106:3
    #12 0x5575fab09c91 in main /tmp/php-afl/sapi/cli/php_cli.c:1310:18
    #13 0x7f1a30c29d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
    #14 0x7f1a30c29e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
    #15 0x5575f9402a24 in _start (/workspaces/TriFuzz/targets/php-afl/bin/php+0x402a24)

0x60c000007cc8 is located 8 bytes inside of 120-byte region [0x60c000007cc0,0x60c000007d38)
freed by thread T0 here:
    #0 0x5575f9487342 in free /opt/llvm-15-build/llvm-15.x/final/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3
    #1 0x7f1a3111680b in xmlFreeNodeList (/lib/x86_64-linux-gnu/libxml2.so.2+0x6480b) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)

previously allocated by thread T0 here:
    #0 0x5575f94875ee in malloc /opt/llvm-15-build/llvm-15.x/final/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
    #1 0x7f1a311145f4 in xmlNewNode (/lib/x86_64-linux-gnu/libxml2.so.2+0x625f4) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)

SUMMARY: AddressSanitizer: heap-use-after-free /tmp/php-afl/ext/dom/php_dom.c:1448:13 in dom_objects_free_storage
Shadow bytes around the buggy address:
  0x0c187fff8f40: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
  0x0c187fff8f50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c187fff8f60: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c187fff8f70: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
  0x0c187fff8f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c187fff8f90: fa fa fa fa fa fa fa fa fd[fd]fd fd fd fd fd fd
  0x0c187fff8fa0: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa
  0x0c187fff8fb0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
  0x0c187fff8fc0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x0c187fff8fd0: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa
  0x0c187fff8fe0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==76313==ABORTING

But I expected this output instead:

no crash

PHP Version

PHP 8.4.0-dev

Operating System

No response

@nielsdos
Copy link
Member

nielsdos commented Oct 1, 2024

Simplified:

<?php
$e1 = new DOMElement("E1");
$e2 = new DOMElement("E2");
$e3 = new DOMElement("E3");
$doc = new DOMDocument(); // Must be placed here so it is destroyed first
$doc->appendChild($e3);
$e2->append($e1);
$e3->appendChild ($e2);
echo $doc->saveXML();

@nielsdos
Copy link
Member

nielsdos commented Oct 1, 2024

The problem is that when e2 gets appended to the document, only e2 receives the intern document object, e1 doesn't.
The fact that these objects are directly constructable are such a headache...

@cmb69
Copy link
Member

cmb69 commented Oct 1, 2024

@nielsdos, see also #16152 (converse issue; memleak).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants