php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #52001 Memory allocation problems after using variable variables
Submitted: 2010-06-05 17:14 UTC Modified: 2010-06-10 11:16 UTC
Votes:128
Avg. Score:4.1 ± 1.2
Reproduced:72 of 80 (90.0%)
Same Version:63 (87.5%)
Same OS:38 (52.8%)
From: lisio at bk dot ru Assigned: dmitry (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5.3.2 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: lisio at bk dot ru
New email:
PHP Version: OS:

 

 [2010-06-05 17:14 UTC] lisio at bk dot ru
Description:
------------
After calling the function using a non-defined variable variable as a second parameter the interpreter goes crazy. Just reproduce the script on any of 5.3.* versions of PHP.

Test script:
---------------
<?php
a(0,$$var);

$temp1=1;
$temp2=2;
echo $temp1;

function a($b,$c) {}
?>

Expected result:
----------------
1

Actual result:
--------------
2

Patches

patch-dont-ruine-uninitialized-ptr (last revision 2010-06-08 02:40 UTC by boldin dot pavel at gmail dot com)
patch-bug-52001-tests (last revision 2010-06-07 23:27 UTC by boldin dot pavel at gmail dot com)
patch-zend-fetch-make-ref-uninitialized-ptr (last revision 2010-06-06 17:03 UTC by boldin dot pavel at gmail dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-06-06 09:10 UTC] akorolyov at gmail dot com
<?php
$test = 0;
$var = 'test';
f(0, $$var);
$x = 1;
$y = 2;
echo $x;
function f($a, $b) {}
?>

In this case I receive correct result.
 [2010-06-06 10:30 UTC] boldin dot pavel at gmail dot com
Even more:
f($$var, 0) will also work.
If you declare function before calling it will work too.

Seems like bug in zend_do_pass_params or so on, causing to corruption of buffer.

These CVs are just missing from the scope (active_symbol_table) after calling function. Seems like they are removed in middle of code execution.
 [2010-06-06 10:36 UTC] boldin dot pavel at gmail dot com
More detailed: when you pass off the function, _get_zval_cv_lookup no longer able to find your CVs, and they are missed. _get_zval_cv_lookup then returns pointer EG(uninitialized_zval_ptr), which is shared among a set of values.

So two values are stored in same place. It is essential that this happens only if you call it with ZEND_FCALL_BY_NAME (i.e. declare after using) and only if dereferenced value is not first.
 [2010-06-06 11:23 UTC] boldin dot pavel at gmail dot com
Here is the problem: Zend/zend_execution.c line 703 (version 5.3.2): incorrect reference count (== 1) in case of bug. Should be == 3 and copy data in 'else' branch.
 [2010-06-06 18:08 UTC] boldin dot pavel at gmail dot com
Version without bug:
(gdb)
zend_send_by_var_helper_SPEC_VAR (execute_data=0x88a28d0)
    at /home/davinchi/php-5.3.2/Zend/zend_vm_execute.h:8257
8257            varptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
(gdb)
8259            if (varptr == &EG(uninitialized_zval)) {
(gdb) p varptr
$24 = (zval *) 0x877fd04
(gdb) p &executor_globals.uninitialized_zval
$25 = (zval *) 0x877fd04
(gdb) p executor_globals.uninitialized_zval_ptr
$26 = (zval *) 0x877fd04

And version with bug:
zend_send_by_var_helper_SPEC_VAR (execute_data=0x88a28d0)
    at /home/davinchi/php-5.3.2/Zend/zend_vm_execute.h:8254
8254            zend_op *opline = EX(opline);
(gdb)
8257            varptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
(gdb) n
8259            if (varptr == &EG(uninitialized_zval)) {
(gdb) p varptr
$27 = (zval *) 0x8876d8c
(gdb) p &executor_globals.uninitialized_zval
$28 = (zval *) 0x877fd04
(gdb) p executor_globals.uninitialized_zval_ptr
$29 = (zval *) 0x8876d8c


See that uninitialized_zval_ptr dont pointers to the uninitialized_zval at all!
 [2010-06-06 18:38 UTC] boldin dot pavel at gmail dot com
Finally: bug is at 
                if (opline->extended_value & ZEND_FETCH_MAKE_REF) {
                        SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
                }

SEPARATE_ZVAL_TO_MAKE_IS_REF seems to ruine *retval (which is executor_globals.uninitialized_ptr). Then this leads to incorrectly working zend_send_by_var_helper and incorrect referencing count in zend_assign_to_variable.

Trying to patch now.
 [2010-06-06 19:06 UTC] boldin dot pavel at gmail dot com
I have attached patch. It must be reviewed by professional PHP developer.

For me it is clearly that call of SEPARATE_ZVAL_TO_MAKE_IS_REF must be predicated with such a check (and it is done in all other cases).
 [2010-06-06 19:15 UTC] boldin dot pavel at gmail dot com
Zend/zend_compile.c 1066:
                if (opline && type == BP_VAR_W && arg_offset) {
                        opline->extended_value = ZEND_FETCH_MAKE_REF;
                }

Is not this bug too? ZEND_FETCH_MAKE_REF is not set for first (arg_offset == 0) arg?
 [2010-06-08 11:18 UTC] tony2001@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: dmitry
 [2010-06-08 11:22 UTC] boldin dot pavel at gmail dot com
old patch brokes tests (Zend/tests/objects_020.phpt), new one don't. Still don't sure if it is absolutely correct.
 [2010-06-10 11:13 UTC] dmitry@php.net
Automatic comment from SVN on behalf of dmitry
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=300345
Log: Fixed bug #52001 (Memory allocation problems after using variable variables)
 [2010-06-10 11:16 UTC] dmitry@php.net
-Status: Assigned +Status: Closed
 [2010-06-10 11:16 UTC] dmitry@php.net
This bug has been fixed in SVN.

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/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 15:01:30 2024 UTC