ID: 44182 User updated by: robin_fernandes at uk dot ibm dot com Reported By: robin_fernandes at uk dot ibm dot com -Status: Feedback +Status: Open Bug Type: Arrays related Operating System: * PHP Version: 5.2CVS-2008-02-20 (snap) New Comment:
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) Previous Comments: ------------------------------------------------------------------------ [2008-10-27 13:01:24] [EMAIL PROTECTED] Does this bug exist in HEAD, PHP_5_3 and PHP_5_2 branches? And in today's versions of them? ------------------------------------------------------------------------ [2008-10-25 13:52:02] 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: http://soal.org/php/extract.patch.txt ------------------------------------------------------------------------ [2008-10-25 13:25:36] [EMAIL PROTECTED] That url does not work.. ------------------------------------------------------------------------ [2008-02-20 09:29:24] 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)) { SEPARATE_ZVAL_TO_MAKE_IS_REF(entry); } 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 http://bugs.php.net/44181. Disclaimer: - 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): http://pastebin.ca/910172 ------------------------------------------------------------------------ [2008-02-20 09:26:54] robin_fernandes at uk dot ibm dot com Description: ------------ 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: --------------- <?php $a = array('foo' => 'original.foo'); $nonref = $a['foo']; $ref = &$a; extract($a, EXTR_REFS); $a['foo'] = 'changed.foo'; var_dump($nonref); //expecting original.foo ?> Expected result: ---------------- string(12) "original.foo" Actual result: -------------- string(11) "changed.foo" ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=44182&edit=1