|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #44182 extract($a, EXTR_REFS) can fail to split copy-on-write references
Submitted: 2008-02-20 09:26 UTC Modified: 2008-11-26 01:03 UTC
Avg. Score:3.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: robin_fernandes at uk dot ibm dot com Assigned:
Status: Closed Package: Arrays related
PHP Version: 5CVS, 6CVS (2008-10-27) OS: *
Private report: No CVE-ID: None
 [2008-02-20 09:26 UTC] robin_fernandes at uk dot ibm dot com
extract($a, EXTR_REFS) does not always respect copy-on-write reference logic.

In the testcase below, $nonRef is initially a copy-on-write reference to an element of $a. After the call to extract, it has become a real reference to an element of $a.

This is reproducible on 5.2, 5.3 and 6.0 snaps.

Reproduce code:
$a = array('foo' => '');

$nonref = $a['foo'];
$ref = &$a;

extract($a, EXTR_REFS);
$a['foo'] = '';

var_dump($nonref); //expecting

Expected result:
string(12) ""

Actual result:
string(11) ""


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2008-02-20 09:29 UTC] robin_fernandes at uk dot ibm dot com
I think the problem is that extract() can set the is_ref flag on zvals without splitting them (i.e. zvals which have more than 1 copy-on-write references can get their is_ref flag set).

From array.c:
} else {
  if (Z_REFCOUNT_P(var_array) > 1 || *entry == EG(uninitialized_zval_ptr)) {
  } else {
    Z_SET_ISREF_PP(entry);  // <-- causes damage if entry has COW references!

I believe that the only reliable way to fix this would be to make extract() take its array argument as PREFER_REF.

This way, we can safely split array elements away from their copy-on-write references, and still end up with a zval that belongs to the original array.

I'm attaching a patch which implements this and fixes this bug, as well as bug

- I am not an internals expert. I might have disregarded some scenarios. Feedback welcome!
- Patch tested on Windows XP 32bit only.

Patch against php6.0-200802191530 snap (includes test cases):
 [2008-10-25 13:25 UTC]
That url does not work..
 [2008-10-25 13:52 UTC] robin_fernandes at uk dot ibm dot com
The patch URL? Seems OK to me, perhaps it was temporarily broken.

In any case, here's another one:
 [2008-10-27 13:01 UTC]
Does this bug exist in HEAD, PHP_5_3 and PHP_5_2 branches? And in today's versions of them?
 [2008-10-27 13:20 UTC] robin_fernandes at uk dot ibm dot com
Confirmed this bug (and bug 44181) still present on:
PHP 5.2.7RC3-dev (cli) (built: Oct 27 2008 11:40:07) 
PHP 5.3.0alpha3-dev (cli) (built: Oct 27 2008 14:06:30) 
PHP 6.0.0-dev (cli) (built: Oct 27 2008 12:39:36)
 [2008-11-26 01:03 UTC]
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
Thank you for the report, and for helping us make PHP better.

Thanks for the patch
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Tue Apr 23 12:01:25 2019 UTC