|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
Patchesxmlwriter_open_uri_leaks (last revision 2012-05-18 19:30 UTC by jean-pierre dot lozi at lip6 dot fr)Pull RequestsHistoryAllCommentsChangesGit/SVN commits
[2012-05-18 22:39 UTC] felipe@php.net
[2012-05-18 22:41 UTC] felipe@php.net
-Summary: Exploitable memory leak in the XML Writer
module
+Summary: memory leak in the XML Writer module
-Status: Open
+Status: Closed
-Assigned To:
+Assigned To: felipe
[2012-05-18 22:41 UTC] felipe@php.net
[2012-05-18 22:41 UTC] felipe@php.net
[2012-05-20 22:45 UTC] felipe@php.net
[2012-07-24 23:36 UTC] rasmus@php.net
[2013-11-17 09:32 UTC] laruence@php.net
[2014-10-07 23:25 UTC] stas@php.net
[2014-10-07 23:36 UTC] stas@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 09:00:01 2025 UTC |
Description: ------------ Short story : - - - - - - - Calling xmlwriter_open_uri(x) in a PHP script leaks memory when x = "file:///" or x = "file://localhost/". This is due to the fact that a xmlURI object isn't freed in the _xmlwriter_get_valid_file_path() function from 'ext/xmlwriter/php_xmlwriter.c'. In a web server setup with mod_php, the leaked memory isn't released until the web server is restarted. This bug seems to be present in all recent versions of PHP (5.3 and 5.4 branches): I have been able to reproduce it on several versions of PHP 5.3 under GNU/Linux and Mac OS X, and I provide a patch for the 5.4Git-2012-05-18 version. More details : - - - - - - - There seems to be a memory leak in the xmlwriter_open_uri() function when it is called with the "file:///" parameter. This bug is triggered in the internal _xmlwriter_get_valid_file_path() function from 'ext/xmlwriter/php_xmlwriter.c', at line 618 in PHP 5.3.13 (or line 616 in PHP 5.4.3): if (source[sizeof("file:///") - 1] == '\0') { return NULL; } This "return NULL;" statement exits the function without freeing the 'uri' variable that has been allocated with xmlCreateURI(). The following line should be added before "return NULL": xmlFreeURI(uri); The same problem can be found a few lines later, when testing whether the 'source' string is equal to "file://localhost/". Consequently, calling xmlwriter_open_uri() with the "file://localhost/" parameter also triggers the bug. In a web server setup with mod_php, since xmlCreateURI() allocates persistent memory, the leaked memory won't be released until the web server is restarted. On my machine, with Ubuntu 11.10, PHP-5.3.13 (Apache 2 with mod_php) and libxml 2.7.8, after calling xmlwriter_open_uri("file:///") a million times in a PHP script, one of the background apache2 processes eats up ~156.3MB of memory (VmRSS). If this function is called 10 million times instead, the background apache2 process eats up ~1.53GB of memory: each call to xmlwriter_open_uri("file:///") seems to leak around 160 bytes. Calling the function 30 million times is sufficient to completely overwhelm my machine (with 4GB of physical RAM). This bug seems easily exploitable by a malicious user who plans to saturate the memory of a server on which he has the ability to execute PHP scripts. Indeed, a simple loop calling xmlwriter_open_uri("file:///") repeatedly would use up all memory very quickly: looping until the default 30 second PHP timeout results in an apache2 process that consumes 508.4MB on my hardware, and the script can be called many times, concurrently or not. Moreover, if a PHP script uses a HTML form variable as the argument to xmlwriter_open_uri(), a hacker could set this variable to "file:///" (or "file://localhost/") and call the script repeatedly to use up all memory. I have been able to activate this bug on Mac OS X Lion (10.7, PHP 5.3.6), with similar results. The patch submitted here fixes this issue for the latest Git version (5.4 branch). Test script: --------------- <?php // After running this script on PHP-5.3.13 (GNU/Linux) with libxml 2.7.8, // an apache2 process using ~156.3MB of memory runs in the background until // Apache is restarted. With 1,000,000,000 iterations, this process uses // 1.53GB of memory. Each iteration seems to leak around 160 bytes. for ($i = 0; $i < 1000000; $i++) { xmlwriter_open_uri("file:///"); // Or: xmlwriter_open_uri("file://localhost/"); } ?> Expected result: ---------------- After the script is executed, the memory used by apache2 processes shouldn't increase. Actual result: -------------- After the script is executed, an apache2 process that uses around ~160MB of memory runs in the background. Executing the script several times keeps eating up more memory.