From: jan at kneschke dot de
Operating system:
PHP version: 5CVS-2003-11-06 (dev)
PHP Bug Type: Zend Engine 2 problem
Bug description: REPLACE_ZVAL_VALUE works on uninit stack-based zvals
Description:
------------
While the summary is a bit technical it the describes the
actual problem very good:
all over the code of the Zend Engine there are temporary
zval's that find there way to REPLACE_ZVAL_VALUE which
'calls' SEPARATE_ZVAL_IF_NOT_REF and even tries to
destrory the temporary zval with zval_dtor().
SEPARATE_ZVAL_IF_NOT_REF expands to ...->is_ref what is an
read to an un-init element, the zval_dtor() is an illegal
free() call.
First occurence:
zend_operators.c:494
zval tmp;
if (op->value.obj.handlers->cast_object(op, &tmp,
IS_STRING, 1 TSRMLS_CC) == SUCCESS) {
...
and '&tmp' is passed to zend_std_cast_object() which will
result in a REPLACE_ZVAL_VALUE()
another path to the same problem:
zend.c:266 zend_print_zval_ex()
zval expr_copy;
zend_make_printable_zval(expr, &expr_copy, &use_copy);
My solution for this kind of coding error is to use pzval
for this job:
diff -u -r1.164 zend_operators.c
--- Zend/zend_operators.c 18 Sep 2003 11:50:05 -0000
1.164
+++ Zend/zend_operators.c 7 Nov 2003 00:39:23 -0000
@@ -492,12 +492,17 @@
break;
case IS_OBJECT:
if
(op->value.obj.handlers->cast_object) {
- zval tmp;
+ zval *tmp;
TSRMLS_FETCH();
- if
(op->value.obj.handlers->cast_object(op, &tmp, IS_STRING,
1 TSRMLS_CC) == SUCCESS) {
+
+ MAKE_STD_ZVAL(tmp);
+
+ if
(op->value.obj.handlers->cast_object(op, tmp, IS_STRING, 1
TSRMLS_CC) == SUCCESS) {
zval_dtor(op);
- *op = tmp;
+ *op = *tmp;
break;
+ } else {
+ zval_dtor(tmp);
}
zend_error(E_NOTICE,
"Object of class %s could not be converted to string",
Z_OBJCE_P(op)->name);
} else {
zend_print_zval_ex() has to be fixed accordingly.
valgrind helped me to catch this bug.
and a last notice: MACROs with such side-effects are evil.
Reproduce code:
---------------
<?php print new reflection_class('stdclass'); ?>
--
Edit bug report at http://bugs.php.net/?id=26156&edit=1
--
Try a CVS snapshot (php4): http://bugs.php.net/fix.php?id=26156&r=trysnapshot4
Try a CVS snapshot (php5): http://bugs.php.net/fix.php?id=26156&r=trysnapshot5
Fixed in CVS: http://bugs.php.net/fix.php?id=26156&r=fixedcvs
Fixed in release: http://bugs.php.net/fix.php?id=26156&r=alreadyfixed
Need backtrace: http://bugs.php.net/fix.php?id=26156&r=needtrace
Try newer version: http://bugs.php.net/fix.php?id=26156&r=oldversion
Not developer issue: http://bugs.php.net/fix.php?id=26156&r=support
Expected behavior: http://bugs.php.net/fix.php?id=26156&r=notwrong
Not enough info: http://bugs.php.net/fix.php?id=26156&r=notenoughinfo
Submitted twice: http://bugs.php.net/fix.php?id=26156&r=submittedtwice
register_globals: http://bugs.php.net/fix.php?id=26156&r=globals
PHP 3 support discontinued: http://bugs.php.net/fix.php?id=26156&r=php3
Daylight Savings: http://bugs.php.net/fix.php?id=26156&r=dst
IIS Stability: http://bugs.php.net/fix.php?id=26156&r=isapi
Install GNU Sed: http://bugs.php.net/fix.php?id=26156&r=gnused
Floating point limitations: http://bugs.php.net/fix.php?id=26156&r=float