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 ---
[EMAIL PROTECTED] cli]$ ./php st.php
Array
(
    [0] => Array
 *RECURSION*
)
Segmentation fault

--- with the patch ---
[EMAIL PROTECTED] cli]$ ./php st.php 
Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )

)
# Array #

Happy hacking,
Morten

-- 
Morten Poulsen <[EMAIL PROTECTED]>
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 Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to