. Fixed bug #62814 (It is possible to stiffen child class members visibility).
(Nikita)
. Fixed bug #69989 (Generators don't participate in cycle GC). (Nikita)
+ . Fixed bug #71266 (Missing separation of properties HT in foreach etc).
+ (Dmitry)
. Fixed bug #71604 (Aborted Generators continue after nested finally).
(Nikita)
. Fixed bug #71572 (String offset assignment from an empty string inserts
--- /dev/null
+--TEST--
+Bug #71266 (Missing separation of properties HT in foreach etc)
+--FILE--
+<?php
+$one = 1;
+$two = 2;
+$arr = ['foo' => $one, 'bar' => $two];
+$obj = (object) $arr;
+foreach ($obj as $val) {
+ var_dump($val);
+ $obj->bar = 42;
+}
+
+$arr = ['foo' => $one, 'bar' => $two];
+$obj = (object) $arr;
+next($obj);
+var_dump(current($arr));
+?>
+--EXPECT--
+int(1)
+int(42)
+int(1)
const char *spec_walk = *spec;
char c = *spec_walk++;
int check_null = 0;
+ int separate = 0;
zval *real_arg = arg;
/* scan through modifiers */
if (*spec_walk == '/') {
SEPARATE_ZVAL_NOREF(arg);
real_arg = arg;
+ separate = 1;
} else if (*spec_walk == '!') {
check_null = 1;
} else {
{
HashTable **p = va_arg(*va, HashTable **);
- if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H')) {
+ if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H', separate)) {
return "array";
}
}
/* old "h" */
#define Z_PARAM_ARRAY_HT_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (UNEXPECTED(!zend_parse_arg_array_ht(_arg, &dest, check_null, 0))) { \
+ if (UNEXPECTED(!zend_parse_arg_array_ht(_arg, &dest, check_null, 0, separate))) { \
_expected_type = Z_EXPECTED_ARRAY; \
error_code = ZPP_ERROR_WRONG_ARG; \
break; \
/* old "H" */
#define Z_PARAM_ARRAY_OR_OBJECT_HT_EX(dest, check_null, separate) \
Z_PARAM_PROLOGUE(separate); \
- if (UNEXPECTED(!zend_parse_arg_array_ht(_arg, &dest, check_null, 1))) { \
+ if (UNEXPECTED(!zend_parse_arg_array_ht(_arg, &dest, check_null, 1, separate))) { \
_expected_type = Z_EXPECTED_ARRAY; \
error_code = ZPP_ERROR_WRONG_ARG; \
break; \
return 1;
}
-static zend_always_inline int zend_parse_arg_array_ht(zval *arg, HashTable **dest, int check_null, int or_object)
+static zend_always_inline int zend_parse_arg_array_ht(zval *arg, HashTable **dest, int check_null, int or_object, int separate)
{
if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) {
*dest = Z_ARRVAL_P(arg);
} else if (or_object && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
+ if (separate
+ && Z_OBJ_P(arg)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(arg)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(arg)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(arg)->properties)--;
+ }
+ Z_OBJ_P(arg)->properties = zend_array_dup(Z_OBJ_P(arg)->properties);
+ }
*dest = Z_OBJ_HT_P(arg)->get_properties(arg);
} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
*dest = NULL;
if (OP1_TYPE != IS_TMP_VAR) {
Z_ADDREF_P(array_ptr);
}
+ if (Z_OBJ_P(array_ptr)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--;
+ }
+ Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
+ }
fe_ht = Z_OBJPROP_P(array_ptr);
pos = 0;
p = fe_ht->arData;
array_ptr = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(array_ptr, array_ref);
}
+ if (Z_OBJ_P(array_ptr)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--;
+ }
+ Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
+ }
fe_ht = Z_OBJPROP_P(array_ptr);
p = fe_ht->arData;
while (1) {
if (IS_CONST != IS_TMP_VAR) {
Z_ADDREF_P(array_ptr);
}
+ if (Z_OBJ_P(array_ptr)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--;
+ }
+ Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
+ }
fe_ht = Z_OBJPROP_P(array_ptr);
pos = 0;
p = fe_ht->arData;
array_ptr = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(array_ptr, array_ref);
}
+ if (Z_OBJ_P(array_ptr)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--;
+ }
+ Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
+ }
fe_ht = Z_OBJPROP_P(array_ptr);
p = fe_ht->arData;
while (1) {
if (IS_TMP_VAR != IS_TMP_VAR) {
Z_ADDREF_P(array_ptr);
}
+ if (Z_OBJ_P(array_ptr)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--;
+ }
+ Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
+ }
fe_ht = Z_OBJPROP_P(array_ptr);
pos = 0;
p = fe_ht->arData;
array_ptr = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(array_ptr, array_ref);
}
+ if (Z_OBJ_P(array_ptr)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--;
+ }
+ Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
+ }
fe_ht = Z_OBJPROP_P(array_ptr);
p = fe_ht->arData;
while (1) {
if (IS_VAR != IS_TMP_VAR) {
Z_ADDREF_P(array_ptr);
}
+ if (Z_OBJ_P(array_ptr)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--;
+ }
+ Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
+ }
fe_ht = Z_OBJPROP_P(array_ptr);
pos = 0;
p = fe_ht->arData;
array_ptr = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(array_ptr, array_ref);
}
+ if (Z_OBJ_P(array_ptr)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--;
+ }
+ Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
+ }
fe_ht = Z_OBJPROP_P(array_ptr);
p = fe_ht->arData;
while (1) {
if (IS_CV != IS_TMP_VAR) {
Z_ADDREF_P(array_ptr);
}
+ if (Z_OBJ_P(array_ptr)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--;
+ }
+ Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
+ }
fe_ht = Z_OBJPROP_P(array_ptr);
pos = 0;
p = fe_ht->arData;
array_ptr = EX_VAR(opline->result.var);
ZVAL_COPY_VALUE(array_ptr, array_ref);
}
+ if (Z_OBJ_P(array_ptr)->properties
+ && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
+ if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--;
+ }
+ Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
+ }
fe_ht = Z_OBJPROP_P(array_ptr);
p = fe_ht->arData;
while (1) {