> >This is a pretty well known issue indeed.
> >I should have read the archive carefully.
> >
> >Related reports:
> >http://bugs.php.net/bug.php?id=6417
> >http://bugs.php.net/bug.php?id=7412
> >http://bugs.php.net/bug.php?id=7515
> >http://bugs.php.net/bug.php?id=15025
> 
> I wouldn't like to call it 'well-known'.

Misleading words? What I meant was "this turned out to be a pretty well 
known issue"... hardly had I noticed this problem until I saw this report, 
I found several related reports during the investigation. So I regarded it 
as a kind of them.

> And I don't like the implications of 1 perfectly valid statement, impacting
> the scope of an array in a non-documented and plain wrong manner.

Is it okay to always perform separation on all the elements of passed 
arrays? If so, the attached patch should work.

> IF this can't be fixed short term, we surely could detect the statement and
> issue a warning?

AFAIK possible. We'll have to trade off performance against usability.

Moriyoshi
Index: zend_execute.c
===================================================================
RCS file: /repository/Zend/zend_execute.c,v
retrieving revision 1.316.2.2
diff -u -r1.316.2.2 zend_execute.c
--- zend_execute.c      17 Nov 2002 22:00:32 -0000      1.316.2.2
+++ zend_execute.c      14 Dec 2002 07:29:19 -0000
@@ -65,6 +65,7 @@
 static void zend_extension_statement_handler(zend_extension *extension, zend_op_array 
*op_array TSRMLS_DC);
 static void zend_extension_fcall_begin_handler(zend_extension *extension, 
zend_op_array *op_array TSRMLS_DC);
 static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_array 
*op_array TSRMLS_DC);
+static int _zval_array_disref(zval **ppz);
 
 #define RETURN_VALUE_USED(opline) (!((opline)->result.u.EA.type & EXT_TYPE_UNUSED))
 
@@ -1816,6 +1817,7 @@
                                        } else if (PZVAL_IS_REF(*param)) {
                                                
zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), 
BP_VAR_W), param, NULL TSRMLS_CC);
                                        } else {
+                                               _zval_array_disref(param);
                                                zend_assign_to_variable(NULL, 
&EX(opline)->result, NULL, *param, IS_VAR, EX(Ts) TSRMLS_CC);
                                        }
                                }
@@ -2480,4 +2482,57 @@
                }
        }
        zend_error(E_ERROR, "Arrived at end of main loop which shouldn't happen");
+}
+
+static int _zval_ref_check(zval **p, void *flag)
+{
+       if ((*p)->is_ref) {
+               *(int *)flag = 1;
+       }
+       _zval_array_disref(p);
+       return ZEND_HASH_APPLY_KEEP;
+}
+
+static void zval_dis_ref(zval **p)
+{
+       if ((*p)->is_ref) {
+               zval *newzv;
+               ALLOC_ZVAL(newzv);
+               *newzv = **p;
+               zval_copy_ctor(newzv);
+               newzv->refcount = 1;
+               newzv->is_ref = 0;
+               if ((*p)->refcount <= 1) {
+                       zval_dtor((*p));
+                       FREE_ZVAL(*p);
+               }
+               *p = newzv;
+       } else {
+               ((*p))->refcount++;
+       }
+}
+
+static int _zval_array_disref(zval **ppz)
+{
+       TSRMLS_FETCH();
+       if ((*ppz)->type == IS_ARRAY) {
+               int flag = 0;
+               if ((*ppz)->value.ht == &EG(symbol_table)) {
+                       return SUCCESS;
+               }
+               zend_hash_apply_with_argument((*ppz)->value.ht, (apply_func_arg_t) 
+_zval_ref_check, (void *)&flag TSRMLS_CC);
+               if (flag) {
+                       zval *newzv, *tmp;
+                       ALLOC_ZVAL(newzv);
+                       *newzv = **ppz;
+                       ALLOC_HASHTABLE(newzv->value.ht);
+                       zend_hash_init(newzv->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+                       zend_hash_copy(newzv->value.ht, Z_ARRVAL_PP(ppz), 
+(copy_ctor_func_t) zval_dis_ref, (void *) &tmp, sizeof(zval *));
+                       zval_ptr_dtor(ppz);
+                       *ppz = newzv;
+                       newzv->is_ref = 0;
+                       newzv->refcount = 1;
+               }
+       } 
+       return SUCCESS;
 }
-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to