[PATCH] fixes crash in PHP-4.3.4
| From: | Morten Poulsen | Date: | Wed, 05 Nov 2003 17:00:29 +0000 |
| Subject: | [PATCH] fixes crash in PHP-4.3.4 | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-5234@lists.php.net to get a copy of this message | ||
Hi,
One of my co-workers, Brian Fløe, found that PHP could be crashed by
passing an array to strip_tags() and other native functions expecting a
string.
I debugged the issue, and it turns out that the problem is in the way
_convert_to_string() calls zend_error() to emit a notice about the
conversion of an array or an object. It destructs op and sets the value
to "Array" or "Object", calls zend_error() with the argument stack
borked, and THEN sets op->type to IS_STRING.
The problem is that any error handler looking at the output of
debug_backtrace() will get wrong results, and in some situations crash
PHP. This is a problem, because many sites run strip_tags() and other
functions on variables from $_GET and $_POST, without explicitly casting
them to strings - which should be safe.
The problem can be solved by calling zend_error() before messing with
op. See attached patch.
The following code will show the (wrong) contents of ['args'] to the
strip_tags() call, and crash at foreach without the patch.
--- st.php ---
<?php
function myErrorHandler()
{
$backtrace = debug_backtrace();
print_r($backtrace[1]['args']);
foreach ($backtrace[1]['args'] as $arg) {
print("# $arg #\n");
}
}
set_error_handler('myErrorHandler');
$tmp = array('a', 'b', 'c');
strip_tags($tmp);
?>
--- without the patch ---
[mopo@flimmer cli]$ ./php st.php
Array
(
[0] => Array
*RECURSION*
)
Segmentation fault
--- with the patch ---
[mopo@flimmer cli]$ ./php st.php
Array
(
[0] => Array
(
[0] => a
[1] => b
[2] => c
)
)
# Array #
Happy hacking,
Morten
--
Morten Poulsen <morten-J1g3Blga@afdelingp.dk>
http://www.afdelingp.dk/
--- php-4.3.4-orig/Zend/zend_operators.c Wed Nov 5 14:20:38 2003 +++ php-4.3.4/Zend/zend_operators.c Wed Nov 5 14:15:32 2003 @@ -460,16 +460,16 @@ break; } case IS_ARRAY: + zend_error(E_NOTICE, "Array to string conversion"); zval_dtor(op); op->value.str.val = estrndup_rel("Array", sizeof("Array")-1); op->value.str.len = sizeof("Array")-1; - zend_error(E_NOTICE, "Array to string conversion"); break; case IS_OBJECT: + zend_error(E_NOTICE, "Object to string conversion"); zval_dtor(op); op->value.str.val = estrndup_rel("Object", sizeof("Object")-1); op->value.str.len = sizeof("Object")-1; - zend_error(E_NOTICE, "Object to string conversion"); break; default: zval_dtor(op);
--- php-4.3.4-orig/Zend/zend_operators.c Wed Nov 5 14:20:38 2003 +++ php-4.3.4/Zend/zend_operators.c Wed Nov 5 14:15:32 2003 @@ -460,16 +460,16 @@ break; } case IS_ARRAY: + zend_error(E_NOTICE, "Array to string conversion"); zval_dtor(op); op->value.str.val = estrndup_rel("Array", sizeof("Array")-1); op->value.str.len = sizeof("Array")-1; - zend_error(E_NOTICE, "Array to string conversion"); break; case IS_OBJECT: + zend_error(E_NOTICE, "Object to string conversion"); zval_dtor(op); op->value.str.val = estrndup_rel("Object", sizeof("Object")-1); op->value.str.len = sizeof("Object")-1; - zend_error(E_NOTICE, "Object to string conversion"); break; default: zval_dtor(op);