php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #70078 Memleak when calling PHP functions from XSL with nodes as parameter
Submitted: 2015-07-14 18:55 UTC Modified: 2017-10-24 06:14 UTC
Votes:7
Avg. Score:5.0 ± 0.0
Reproduced:7 of 7 (100.0%)
Same Version:4 (57.1%)
Same OS:3 (42.9%)
From: mplomer at gmx dot de Assigned:
Status: Open Package: XSLT related
PHP Version: 5.6.11 OS: any
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2015-07-14 18:55 UTC] mplomer at gmx dot de
Description:
------------
When calling registered PHP functions in XSLTProcessor from a XSL stylesheet with references to nodes as parameter, you will notice bad performence and - depending on XML structure - a big memleak.

Test-Script see:
https://gist.github.com/not-implemented/bb41831a4892f1459e5b

Until 5.4.23 you have ~25 MB RAM usage of the process at the end
Starting with 5.4.24 you have ~1030 MB RAM usage of the process at the end

Please notice, that this high usage is NOT covered by memory_get_usage().

When passing a fixed string to the function instead of ".", the problem ist not reproducable.

This seems to be introduced in Bug #49634 between 5.4.23 and 5.4.24 (or maybe ~5.5.7 and 5.5.8) where nodes are recursively duplicated now.

Expected result:
----------------
Memory usage ~25 MB RAM

Actual result:
--------------
Memory usage ~1030 MB RAM

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-07-15 20:38 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2015-07-15 20:38 UTC] cmb@php.net
The memory leak (which I can confirm) might be caused by using
xmlDocCopyNodeList() to create a new node list, which would have
to be freed using xmlFreeNodeList() but is actually freed with
xmlFreeNode().

However, I'm not able to reproduce the behavior described in
#49634 with PHP 5.4.23, libxml2-2.7.4 and libxslt-1.1.25
(bug49634.phpt is passing there as well), so I can't go on here
without the risk to reintroduce #49634.
 [2015-07-15 20:57 UTC] mplomer at gmx dot de
I also did not understand why exactly the xmlDocCopyNodeList() has been introduced here. IMHO passing nodes to a PHP function should never implicate such expensive recursive clones.
 [2015-09-09 15:50 UTC] mike@php.net
How did you confirm the memleak? Valgrind doesn't complain for me...
 [2015-09-09 16:29 UTC] mplomer at gmx dot de
As described, I checked the process memory usage (under Windows in Task-Manager - should be the same with "ps" on unix) - memory_get_usage() does not cover this. I don't know what Valgrind checks exactly. And I don't know, which memory allocator libxml/libxslt uses.

By the way you can also reproduce the problem by measuring the performance of transformToXML(), which is much much slower than with 5.4.23.

Just tell me if you need more info.
 [2015-09-09 17:58 UTC] cmb@php.net
To clarify: there may not really be a memory *leak*, but at least
the intermediate memory consumption is enormous:

> Until 5.4.23 you have ~25 MB RAM usage of the process at the end
> Starting with 5.4.24 you have ~1030 MB RAM usage of the process
> at the end
 [2015-09-09 18:40 UTC] mplomer at gmx dot de
Oh, I see, my report was not clear enough:

The memory is not freed, even after processing the request - I re-tested the snippet under Apache (mod_php) / Linux now. (I had to reduce the dummy XML size by factor 10, otherwise the process just crashed - memory_limit also does not apply here).

AFTER the request is complete I see a memory usage (RSS) of ~ 350 MB:

root     28237  0.0  0.0 421800   112 ?        Ss   Sep07   0:06 /usr/sbin/apache2 -k start
www-data 17175  0.0  4.8 510936 24328 ?        S    06:25   0:11  \_ /usr/sbin/apache2 -k start
www-data 18672  0.0 69.7 911320 353168 ?       S    09:10   0:10  \_ /usr/sbin/apache2 -k start
...........

You are right, this still _may_ not be a "real" memleak ... but anyway, I think the recursive clone on the complete DOM node on every function call is wrong - for performance reasons - even if it gets fixed by freeing the clone immediately after the function call.
 [2015-09-10 08:23 UTC] mike@php.net
-Assigned To: +Assigned To: rrichards
 [2015-09-10 08:23 UTC] mike@php.net
Maybe Rob can have a look at it, as we're lost with these ext/libxml internals...
 [2017-10-24 05:15 UTC] kalle@php.net
-Status: Verified +Status: Assigned
 [2017-10-24 06:14 UTC] kalle@php.net
-Status: Assigned +Status: Open -Assigned To: rrichards +Assigned To:
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Wed Nov 13 15:01:28 2019 UTC