From: Operating system: GNU/Linux PHP version: 5.4Git-2012-05-18 (Git) Package: XML Writer Bug Type: Bug Bug description:Exploitable memory leak in the XML Writer module
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. -- Edit bug report at https://bugs.php.net/bug.php?id=62064&edit=1 -- Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=62064&r=trysnapshot54 Try a snapshot (PHP 5.3): https://bugs.php.net/fix.php?id=62064&r=trysnapshot53 Try a snapshot (trunk): https://bugs.php.net/fix.php?id=62064&r=trysnapshottrunk Fixed in SVN: https://bugs.php.net/fix.php?id=62064&r=fixed Fixed in SVN and need be documented: https://bugs.php.net/fix.php?id=62064&r=needdocs Fixed in release: https://bugs.php.net/fix.php?id=62064&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=62064&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=62064&r=needscript Try newer version: https://bugs.php.net/fix.php?id=62064&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=62064&r=support Expected behavior: https://bugs.php.net/fix.php?id=62064&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=62064&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=62064&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=62064&r=globals PHP 4 support discontinued: https://bugs.php.net/fix.php?id=62064&r=php4 Daylight Savings: https://bugs.php.net/fix.php?id=62064&r=dst IIS Stability: https://bugs.php.net/fix.php?id=62064&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=62064&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=62064&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=62064&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=62064&r=mysqlcfg