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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
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

Add a Patch

Pull Requests

Add a Pull Request

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: Thu Mar 28 12:01:27 2024 UTC