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

Memory leak in xml extension #14044

Open
YuanchengJiang opened this issue Apr 25, 2024 · 3 comments
Open

Memory leak in xml extension #14044

YuanchengJiang opened this issue Apr 25, 2024 · 3 comments

Comments

@YuanchengJiang
Copy link

Description

The following code:

<?php
$xw = new XMLWriter();
$xw->openMemory();
$xw->startDocument(NULL, "UTF-8");
$xw->endDocument();
trait T {
    public $prop;
}
readonly class C {
    use T;
}
?>

Resulted in this output:

Fatal error: Readonly class C cannot use trait with a non-readonly property T::$prop in test.php on line 9

=================================================================
==3141115==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 80 byte(s) in 1 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fbb5e69b in xmlNewTextWriter (/lib/x86_64-linux-gnu/libxml2.so.2+0x14769b) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)

Indirect leak of 4096 byte(s) in 1 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fbb007ac in xmlBufCreate (/lib/x86_64-linux-gnu/libxml2.so.2+0xe97ac) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)
    #2 0x55a778db8fa4 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER /Zend/zend_vm_execute.h:1879:4
    #3 0x55a778b2e8f7 in execute_ex /Zend/zend_vm_execute.h:57125:7
    #4 0x55a778b2fcc2 in zend_execute /Zend/zend_vm_execute.h:62752:2
    #5 0x55a77897ba68 in zend_execute_script /Zend/zend.c:1888:3
    #6 0x55a7784e6366 in php_execute_script_ex /main/main.c:2507:13
    #7 0x55a7784e6c08 in php_execute_script /main/main.c:2547:9
    #8 0x55a7798a4483 in do_cli /sapi/cli/php_cli.c:966:5
    #9 0x55a7798a0a12 in main /sapi/cli/php_cli.c:1340:18
    #10 0x7f08fb696d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

Indirect leak of 4096 byte(s) in 1 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fba87d58 in xmlBufferCreate (/lib/x86_64-linux-gnu/libxml2.so.2+0x70d58) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)
    #2 0x55a778db8fa4 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER /Zend/zend_vm_execute.h:1879:4
    #3 0x55a778b2e8f7 in execute_ex /Zend/zend_vm_execute.h:57125:7
    #4 0x55a778b2fcc2 in zend_execute /Zend/zend_vm_execute.h:62752:2
    #5 0x55a77897ba68 in zend_execute_script /Zend/zend.c:1888:3
    #6 0x55a7784e6366 in php_execute_script_ex /main/main.c:2507:13
    #7 0x55a7784e6c08 in php_execute_script /main/main.c:2547:9
    #8 0x55a7798a4483 in do_cli /sapi/cli/php_cli.c:966:5
    #9 0x55a7798a0a12 in main /sapi/cli/php_cli.c:1340:18
    #10 0x7f08fb696d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

Indirect leak of 4001 byte(s) in 1 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fbb006c2 in xmlBufCreateSize (/lib/x86_64-linux-gnu/libxml2.so.2+0xe96c2) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)

Indirect leak of 176 byte(s) in 1 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fba792de in xmlNewDoc (/lib/x86_64-linux-gnu/libxml2.so.2+0x622de) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)

Indirect leak of 64 byte(s) in 1 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fbb00753 in xmlBufCreate (/lib/x86_64-linux-gnu/libxml2.so.2+0xe9753) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)
    #2 0x55a778db8fa4 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER /Zend/zend_vm_execute.h:1879:4
    #3 0x55a778b2e8f7 in execute_ex /Zend/zend_vm_execute.h:57125:7
    #4 0x55a778b2fcc2 in zend_execute /Zend/zend_vm_execute.h:62752:2
    #5 0x55a77897ba68 in zend_execute_script /Zend/zend.c:1888:3
    #6 0x55a7784e6366 in php_execute_script_ex /main/main.c:2507:13
    #7 0x55a7784e6c08 in php_execute_script /main/main.c:2547:9
    #8 0x55a7798a4483 in do_cli /sapi/cli/php_cli.c:966:5
    #9 0x55a7798a0a12 in main /sapi/cli/php_cli.c:1340:18
    #10 0x7f08fb696d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

Indirect leak of 64 byte(s) in 1 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fbb00635 in xmlBufCreateSize (/lib/x86_64-linux-gnu/libxml2.so.2+0xe9635) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)

Indirect leak of 56 byte(s) in 1 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fba9495b in xmlAllocOutputBufferInternal (/lib/x86_64-linux-gnu/libxml2.so.2+0x7d95b) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)
    #2 0x55a778db8fa4 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER /Zend/zend_vm_execute.h:1879:4
    #3 0x55a778b2e8f7 in execute_ex /Zend/zend_vm_execute.h:57125:7
    #4 0x55a778b2fcc2 in zend_execute /Zend/zend_vm_execute.h:62752:2
    #5 0x55a77897ba68 in zend_execute_script /Zend/zend.c:1888:3
    #6 0x55a7784e6366 in php_execute_script_ex /main/main.c:2507:13
    #7 0x55a7784e6c08 in php_execute_script /main/main.c:2547:9
    #8 0x55a7798a4483 in do_cli /sapi/cli/php_cli.c:966:5
    #9 0x55a7798a0a12 in main /sapi/cli/php_cli.c:1340:18
    #10 0x7f08fb696d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

Indirect leak of 48 byte(s) in 2 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fba8cff3 in xmlListCreate (/lib/x86_64-linux-gnu/libxml2.so.2+0x75ff3) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)

Indirect leak of 48 byte(s) in 2 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fba8cfd3 in xmlListCreate (/lib/x86_64-linux-gnu/libxml2.so.2+0x75fd3) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)

Indirect leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fba87d23 in xmlBufferCreate (/lib/x86_64-linux-gnu/libxml2.so.2+0x70d23) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)
    #2 0x55a778db8fa4 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER /Zend/zend_vm_execute.h:1879:4
    #3 0x55a778b2e8f7 in execute_ex /Zend/zend_vm_execute.h:57125:7
    #4 0x55a778b2fcc2 in zend_execute /Zend/zend_vm_execute.h:62752:2
    #5 0x55a77897ba68 in zend_execute_script /Zend/zend.c:1888:3
    #6 0x55a7784e6366 in php_execute_script_ex /main/main.c:2507:13
    #7 0x55a7784e6c08 in php_execute_script /main/main.c:2547:9
    #8 0x55a7798a4483 in do_cli /sapi/cli/php_cli.c:966:5
    #9 0x55a7798a0a12 in main /sapi/cli/php_cli.c:1340:18
    #10 0x7f08fb696d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

Indirect leak of 6 byte(s) in 1 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fbafa7f2 in xmlStrdup (/lib/x86_64-linux-gnu/libxml2.so.2+0xe37f2) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)

Indirect leak of 6 byte(s) in 2 object(s) allocated from:
    #0 0x55a776888c0e in malloc (/usr/local/bin/php+0x1c88c0e) (BuildId: c0213df21908f588a04dfadca2142af951d35e31)
    #1 0x7f08fbafa6e3 in xmlStrndup (/lib/x86_64-linux-gnu/libxml2.so.2+0xe36e3) (BuildId: aebf8e42966c3ce475ff9d9d51a762831adcbb61)

SUMMARY: AddressSanitizer: 12773 byte(s) leaked in 16 allocation(s).

PHP Version

PHP 8.4.0-dev

Operating System

ubuntu 22.04

@nielsdos
Copy link
Member

Compilation errors create fatal errors, and fatal errors don't vall destructors because the program may be in an inconsistent state. Normally this doesn't cause leaks because objects and their backing data is allocated with the request allocator. Unfortunately, all extensions using libxml use the system allocator.

When looking into whether it is possible to utilise the request allocator for libxml, there are a few problems:

  • On SAPIs like Apache, other modules may use libxml as well. So we must be careful to reset the allocator back to the system allocator at request end such that other Apache modules don't use PHP's allocator.
  • Even when using the request allocator, we cannot control what third party extensions, or libraries, allocate and how long they keep that data alive. E.g. a third party module could cache some data allocated by libxml longer than the duration of a request, which will cause problems.

@YuanchengJiang
Copy link
Author

@nielsdos Wondering if you developers would appreciate memory leak issues? I still have several such cases. Not sure how to determine if they are expected or known issues. I currently filter out similar leaks that happened in existing tests.

@nielsdos
Copy link
Member

We do appreciate reports for leaks. And thanks for the reports so far.

You'll notice that when using ASAN and USE_ZEND_ALLOC=0 that things like fatal errors will cause leaks. In production code we use USE_ZEND_ALLOC=1 (also by default if unset) to enable Zend's own memory manager which cleans up memory after each request. So the leak for fatal errors doesn't actually happen for production code because the Zend engine cleans the memory and closes resources when its own allocator is used.

This particular case is different because it also leaks under USE_ZEND_ALLOC=1 for the reason written in my previous comment.

When you want to determine if a leak is a real leak, check if the leak reproduces under USE_ZEND_ALLOC=1. The engine will output a message saying it detected leaks when ran in debug mode (or ASAN will already complain if libraries are involved). If you encounter that, you can set USE_ZEND_ALLOC=0 to get a nice ASAN report.

Also, a few tests have leaks that we know about, they are marked with XLEAK. Sometimes they are caused by issues in libraries we use, or by a known bug.

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

3 participants