ID: 43450
Updated by: [EMAIL PROTECTED]
Reported By: [EMAIL PROTECTED]
Status: Open
Bug Type: Scripting Engine problem
Operating System: Any
PHP Version: 5.2.5
New Comment:
I'm still not sure if this has anything to do with the new Zend parsing
API, but I've tested the md5 function with the zend_get_parameters_ex
(the old API) and the leak didn't occur. See the two version for a
comparison.
-------------------- currently --------------------
PHP_NAMED_FUNCTION(php_if_md5)
{
char *arg;
int arg_len;
zend_bool raw_output = 0;
char md5str[33];
PHP_MD5_CTX context;
unsigned char digest[16];
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"s|b", &arg, &arg_len, &raw_output) == FAILURE) {
return;
}
md5str[0] = '\0';
PHP_MD5Init(&context);
PHP_MD5Update(&context, arg, arg_len);
PHP_MD5Final(digest, &context);
if (raw_output) {
RETURN_STRINGL(digest, 16, 1);
} else {
make_digest_ex(md5str, digest, 16);
RETVAL_STRING(md5str, 1);
}
}
----------- hacked rewrite ------------------------
PHP_NAMED_FUNCTION(php_if_md5)
{
zval **zarg;
zend_bool raw_output = 0;
char md5str[33];
PHP_MD5_CTX context;
unsigned char digest[16];
if (ZEND_NUM_ARGS() != 1 ||
zend_get_parameters_ex(1, &zarg) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string_ex(zarg);
md5str[0] = '\0';
PHP_MD5Init(&context);
PHP_MD5Update(&context, Z_STRVAL_PP(zarg), Z_STRLEN_PP(zarg));
PHP_MD5Final(digest, &context);
if (raw_output) {
RETURN_STRINGL(digest, 16, 1);
} else {
make_digest_ex(md5str, digest, 16);
RETVAL_STRING(md5str, 1);
}
}
Previous Comments:
------------------------------------------------------------------------
[2007-11-29 14:59:48] [EMAIL PROTECTED]
Description:
------------
Under certain circumenstances, the implicit call to __toString() on an
object may lead to memory leaks.
In the reproducable example, the following line leaks ($o is a simply
object):
md5($o);
But this line doesn't:
md5($o->__toString());
This only applies to certain functions, I've identifier md5, sha1 and
crc32.
If I try other examples like strstr or strlen, there's no leak at all.
A wild guess is that this maybe has to do whether the function
internally uses zend_parse_parameters() or zend_get_parameters_ex().
The function which leak use zend_parse_parameters(), the others don't.
But this may completely accidental.
It seems very related to bug#38591. However I don't see how bug#38604
is related to this issue (mentioned in bug#38591).
This leak was most notable found in an application which is supposed to
run for a long time, even hours. So usually within web application this
is not an issue.
Reproduce code:
---------------
<?php
class Foo {
function __toString() {
return 'foo';
}
}
for ($i = 0; $i < 1e5; $i++) {
$o = new Foo;
# leaks
md5($o);
# does not leak
#md5($o->__toString());
# does not leak either way
# strstr($o, 'f');
#strstr($o->__toString(), 'f');
if ($i % 1e3 == 0) {
printf("%u: %1.2f KB\n",
$i, memory_get_usage(true) / 1024);
}
}
Expected result:
----------------
Constant memory usage.
Actual result:
--------------
Memory grows and grows.
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=43450&edit=1