php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #26156 REPLACE_ZVAL_VALUE works on uninit stack-based zvals
Submitted: 2003-11-06 19:41 UTC Modified: 2003-11-13 15:52 UTC
From: jan at kneschke dot de Assigned: moriyoshi (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5CVS-2003-11-06 (dev) OS:
Private report: No CVE-ID: None
 [2003-11-06 19:41 UTC] jan at kneschke dot de
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'); ?>


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-11-06 20:48 UTC] moriyoshi@php.net
This is due to my premature patch lately applied on zend_object_handlers.c. Assigning to me.

 [2003-11-13 15:52 UTC] moriyoshi@php.net
This bug has been fixed in CVS.

In case this was a PHP problem, snapshots of the sources are packaged
every three hours; this change will be in the next snapshot. You can
grab the snapshot at http://snaps.php.net/.
 
In case this was a documentation problem, the fix will show up soon at
http://www.php.net/manual/.

In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites in short time.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 12:01:31 2024 UTC