|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2004-09-13 15:47 UTC] owen dot beresford at murphx dot com
Description:
------------
PHP 5.0.1 (cli) (built: Aug 16 2004 23:07:06),
linux, rh7.3, kernel2.4, libc-2.2.5
The extract function seems incomplete/ broken.
I have a code base which uses arguments arrays, like perl.
Inorder to alter varaibles inside the parameter array in a convient fashion, I extract the variables at the top of the methods.
Some of the boundary cases don't perform correctly. I have NOT experienced this under other releases of php, so assume the problem is induced by the new zend engine.
I am assuming that php 5.0.1 includes prevous fixes for errors reported against php 4.3.8 and php 5.0.0 (there are closed cases with similar problems).
This is a small simple case, there are other failures, but this would exceed the twenty line limit. will post an URL with full senario
The described output ommited some of the english statements for brevity.
I have not tested this under other operating systems, but this is not a platform dependant function (well it shouldn't be), and I don't have any to hand.
in the interests of thoroughness:
Configure Command => './configure' '--prefix=/usr' '--with-config-file-path=/etc' '--enable-cli' '--disable-cgi' '--without-pear' '--enable-force-cgi-redirect' '--with-exec-dir=/usr/bin' '--with-mysql' '--with-curl=/usr/local/lib' '--with-zlib' '--enable-sockets' '--with-openssl' '--enable-pcntl' '--enable-libxml' '--enable-shared'
Reproduce code:
---------------
function x($args) {
$count =extract($args, EXTR_REFS);
echo("inside function x()\n$count items\n");
$count+=10;
echo("altered count to $count\n");
var_dump(array($a, $b));
}
echo("before function x() (second is a null)\n");
$a=array('a'=>1, 'b'=>NULL);
var_dump($a);
x($a);
echo("before function x() (second is undefined variable)\n");
$d=array('a'=>1, 'b'=>NULL);
$e=array('a'=>1, 'b'=>$d['d']);
var_dump($e);
x($e);
Expected result:
----------------
array(2) {
["a"]=>
int(1)
["b"]=>
NULL
}
array(2) {
["a"]=>
int(1)
["b"]=>
NULL
}
Actual result:
--------------
array(2) {
[0]=>
int(1)
[1]=>
NULL
}
array(2) {
[0]=>
int(1)
[1]=>
int(12)
}
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Nov 01 07:00:01 2025 UTC |
Reduced reproduce code looks like this: <?php $result = extract(array('a'=>1, 'b'=>$foo), EXTR_REFS); //extract(array('a'=>1, 'b'=>$foo), EXTR_REFS); // they are not the same var_dump(array($b)); ?>I belive this bug was introduced in PHP 4.3.10, it would seem that when doing EXTR_REFS $a in the example below isn't SEPARATE_ZVAL_TO_MAKE_IS_REF or something when being extracted from the array. Reproduce code: ------------ $a = 1; $b = 1; $arr = array('acopy' => $a, 'bref' => &$b); extract($arr, EXTR_REFS); $acopy++; $bref++; debug_zval_dump($a, $b, $arr, $acopy, $bref); Expected result (As seen on PHP < 4.3.10): ------------ $a: long(1) refcount(2) $b: long(2) refcount(1) $arr: array(2) refcount(2){ ["acopy"]=> &long(2) refcount(2) ["bref"]=> &long(2) refcount(3) } $acopy: long(2) refcount(1) $bref: long(2) refcount(1) Actual result: -------------- $a: long(2) refcount(1) $b: long(2) refcount(1) $arr: array(2) refcount(2){ ["acopy"]=> &long(2) refcount(3) ["bref"]=> &long(2) refcount(3) } $acopy: long(2) refcount(1) $bref: long(2) refcount(1)I'm able to reproduce this using current CVS. The problem appears to be when a CV value is passed into extract() either as the array or an array value. Looks like in this case the IS_CV value is assigned to EG(uninitialized_zval_ptr). The following patch will correct the problem for this case (and still pass a php 'make test'). However I'm not familiar enough with CV to know if there's a better way to correct to this problem: diff --git a/ext/standard/array.c b/ext/standard/array.c index fad4bf2..fdc9a88 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1438,7 +1438,7 @@ PHP_FUNCTION(extract) *orig_var = *entry; } else { - if ((*var_array)->refcount > 1) { + if ((*var_array)->refcount > 1 || *entry == EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_TO_MAKE_IS_REF(entry); } else { (*entry)->is_ref = 1;