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

Reply via email to