php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #44181 extract($a, EXTR_OVERWRITE|EXTR_REFS) can fail to create references to $a
Submitted: 2008-02-20 09:25 UTC Modified: 2008-10-25 13:26 UTC
From: robin_fernandes at uk dot ibm dot com Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 5.2CVS-2008-02-20 (snap) OS: *
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: robin_fernandes at uk dot ibm dot com
New email:
PHP Version: OS:

 

 [2008-02-20 09:25 UTC] robin_fernandes at uk dot ibm dot com
Description:
------------
Using extract() with EXTR_OVERWRITE|EXTR_REFS does not create references to the array elements if the following conditions are true:
 - $a is referenced by some other variable (its is_ref flag is true).
 - A variable already exists in the current scope with a name matching the key.

This is reproducible on 5.2, 5.3 and 6.0 snaps.

Reproduce code:
---------------
<?php
$a = array('foo' => 'original.foo');

$foo = 'test';
$ref = &$a;

extract($a, EXTR_OVERWRITE|EXTR_REFS);
$foo = 'changed.foo';

var_dump($a['foo']); //expecting changed.foo
?>

Expected result:
----------------
string(11) "changed.foo"

Actual result:
--------------
string(12) "original.foo"

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-02-20 09:30 UTC] robin_fernandes at uk dot ibm dot com
I think this is because $a is passed by value, and the call to SEPARATE_ZVAL_TO_MAKE_IS_REF(entry) below splits the array element from the original array.

The reference is therefore created to the element of the argument array which, after the split, is not the same as the element of the original array.

From array.c:
...
if (zend_u_hash_find(EG(active_symbol_table), Z_TYPE(final_name), Z_UNIVAL(final_name), Z_UNILEN(final_name) + 1, (void **) &orig_var) == SUCCESS) {
  SEPARATE_ZVAL_TO_MAKE_IS_REF(entry);    // <-- Split! entry no longer refers to element of $a.
  zval_add_ref(entry);
  zval_ptr_dtor(orig_var);
  *orig_var = *entry;
} else {
...

I believe the root cause for this bug is the same as bug http://bugs.php.net/44182.

I have submitted a patch for that bug which fixes this one too.
 [2008-10-25 13:26 UTC] jani@php.net
No need for several open reports about this issue.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Nov 24 03:01:32 2024 UTC