summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_execute.c41
-rw-r--r--Zend/zend_object_handlers.c2
-rw-r--r--Zend/zend_vm_def.h10
-rw-r--r--Zend/zend_vm_execute.h76
-rw-r--r--ext/spl/php_spl.c23
-rw-r--r--ext/standard/array.c46
6 files changed, 116 insertions, 82 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 7fca796137..282781a9ab 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -697,34 +697,23 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p
if (Z_TYPE_P(object) == IS_NULL ||
Z_TYPE_P(object) == IS_FALSE ||
(Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
-//??? The following block may handle only non-interned empty string,
-//??? but it doesn't work anyway
-//??? see: Zend/tests/bug54265.phpt
-#if 0
- if (Z_REFCOUNTED_P(object)) {
- if (!Z_ISREF_P(object_ptr)) {
- SEPARATE_ZVAL(object);
- }
- Z_ADDREF_P(object);
- zend_error(E_WARNING, "Creating default object from empty value");
- if (Z_REFCOUNT_P(object) == 1) {
- /* object was removed by error handler, nothing to assign to */
- zval_ptr_dtor(object);
- if (retval) {
- ZVAL_NULL(retval);
- }
- FREE_OP(free_value);
- return;
+ zend_object *obj;
+
+ zval_ptr_dtor(object);
+ object_init(object);
+ Z_ADDREF_P(object);
+ obj = Z_OBJ_P(object);
+ zend_error(E_WARNING, "Creating default object from empty value");
+ if (GC_REFCOUNT(obj) == 1) {
+ /* the enclosing container was deleted, obj is unreferenced */
+ if (retval) {
+ ZVAL_NULL(retval);
}
- Z_DELREF_P(object);
- } else {
- zend_error(E_WARNING, "Creating default object from empty value");
+ FREE_OP(free_value);
+ OBJ_RELEASE(obj);
+ return;
}
-#else
- zend_error(E_WARNING, "Creating default object from empty value");
-#endif
- zval_dtor(object);
- object_init(object);
+ Z_DELREF_P(object);
} else {
zend_error(E_WARNING, "Attempt to assign property of non-object");
if (retval) {
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 30794a3054..ff8d99addc 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -597,7 +597,7 @@ found:
if (Z_REFCOUNTED_P(value) && Z_REFCOUNT_P(value) > 0) {
zval_copy_ctor(Z_REFVAL_P(variable_ptr));
}
- zval_dtor(&garbage);
+ zval_ptr_dtor(&garbage);
} else {
zval garbage;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 2865a78ad7..e4ba9597a6 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3471,7 +3471,7 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY)
// This solution breaks the following test (emit warning message) ???
// ext/pdo_sqlite/tests/pdo_005.phpt
#endif
- (!Z_ISREF_P(arg) && Z_REFCOUNT_P(arg) > 1)) {
+ (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
@@ -4839,8 +4839,9 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
FREE_OP1();
}
- if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (opline->extended_value & ZEND_ISSET) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -4937,6 +4938,9 @@ ZEND_VM_C_LABEL(num_index_prop):
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 7ca929f722..761f4c630c 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4454,7 +4454,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -6248,7 +6249,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -6929,7 +6931,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -9840,7 +9843,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -11515,7 +11519,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -12080,7 +12085,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -13628,7 +13634,7 @@ static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
// This solution breaks the following test (emit warning message) ???
// ext/pdo_sqlite/tests/pdo_005.phpt
#endif
- (!Z_ISREF_P(arg) && Z_REFCOUNT_P(arg) > 1)) {
+ (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
@@ -16612,7 +16618,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -16709,6 +16716,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -18692,6 +18702,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -20945,7 +20958,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -21042,6 +21056,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -22269,7 +22286,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -24265,6 +24283,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -25722,6 +25743,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -26998,6 +27022,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -28276,6 +28303,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -30063,6 +30093,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -30955,7 +30988,7 @@ static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
// This solution breaks the following test (emit warning message) ???
// ext/pdo_sqlite/tests/pdo_005.phpt
#endif
- (!Z_ISREF_P(arg) && Z_REFCOUNT_P(arg) > 1)) {
+ (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
@@ -33559,7 +33592,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -33656,6 +33690,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -35550,6 +35587,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -37683,7 +37723,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -37780,6 +37821,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
@@ -38889,7 +38933,8 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
}
if (opline->extended_value & ZEND_ISSET) {
- if (isset && Z_TYPE_P(value) != IS_NULL) {
+ if (isset && Z_TYPE_P(value) != IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
ZVAL_BOOL(EX_VAR(opline->result.var), 1);
} else {
ZVAL_BOOL(EX_VAR(opline->result.var), 0);
@@ -40747,6 +40792,9 @@ num_index_prop:
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (IS_CV == IS_CV || IS_CV == IS_VAR) {
+ ZVAL_DEREF(offset);
+ }
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c
index d765d6b754..62cf6ae144 100644
--- a/ext/spl/php_spl.c
+++ b/ext/spl/php_spl.c
@@ -441,24 +441,11 @@ PHP_FUNCTION(spl_autoload_call)
#define HT_MOVE_TAIL_TO_HEAD(ht) \
do { \
- uint first = 0; \
- uint last = (ht)->nNumUsed; \
- while (first < last) { \
- if (Z_TYPE((ht)->arData[first].val) != IS_UNDEF) \
- break; \
- first++; \
- } \
- while (last > first) { \
- last--; \
- if (Z_TYPE((ht)->arData[last].val) != IS_UNDEF) \
- break; \
- } \
- if (first != last) { \
- Bucket tmp = (ht)->arData[first]; \
- (ht)->arData[first] = (ht)->arData[last]; \
- (ht)->arData[last] = tmp; \
- zend_hash_rehash(ht); \
- } \
+ Bucket tmp = (ht)->arData[(ht)->nNumUsed-1]; \
+ memmove((ht)->arData + 1, (ht)->arData, \
+ sizeof(Bucket) * ((ht)->nNumUsed - 1)); \
+ (ht)->arData[0] = tmp; \
+ zend_hash_rehash(ht); \
} while (0)
/* {{{ proto bool spl_autoload_register([mixed autoload_function = "spl_autoload" [, throw = true [, prepend]]])
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 0e01b2ec68..731c374582 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -607,6 +607,7 @@ static int php_array_user_compare(const void *a, const void *b TSRMLS_DC) /* {{{
PHP_FUNCTION(usort)
{
zval *array;
+ zend_refcounted *arr;
unsigned int refcount;
PHP_ARRAY_CMP_FUNC_VARS;
@@ -617,30 +618,31 @@ PHP_FUNCTION(usort)
return;
}
- /* Clear the is_ref flag, so the attemts to modify the array in user
+ /* Increase reference counter, so the attemts to modify the array in user
* comparison function will create a copy of array and won't affect the
* original array. The fact of modification is detected using refcount
* comparison. The result of sorting in such case is undefined and the
* function returns FALSE.
*/
-//??? Z_UNSET_ISREF_P(array);
+ Z_ADDREF_P(array);
refcount = Z_REFCOUNT_P(array);
+ arr = Z_COUNTED_P(array);
if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_user_compare, 1 TSRMLS_CC) == FAILURE) {
RETVAL_FALSE;
} else {
if (refcount > Z_REFCOUNT_P(array)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array was modified by the user comparison function");
+ if (--GC_REFCOUNT(arr) <= 0) {
+ _zval_dtor_func(arr ZEND_FILE_LINE_CC);
+ }
RETVAL_FALSE;
} else {
+ Z_DELREF_P(array);
RETVAL_TRUE;
}
}
- if (Z_REFCOUNT_P(array) > 1) {
-//??? Z_SET_ISREF_P(array);
- }
-
PHP_ARRAY_CMP_FUNC_RESTORE();
}
/* }}} */
@@ -650,6 +652,7 @@ PHP_FUNCTION(usort)
PHP_FUNCTION(uasort)
{
zval *array;
+ zend_refcounted *arr;
unsigned int refcount;
PHP_ARRAY_CMP_FUNC_VARS;
@@ -660,30 +663,31 @@ PHP_FUNCTION(uasort)
return;
}
- /* Clear the is_ref flag, so the attemts to modify the array in user
- * comaprison function will create a copy of array and won't affect the
+ /* Increase reference counter, so the attemts to modify the array in user
+ * comparison function will create a copy of array and won't affect the
* original array. The fact of modification is detected using refcount
* comparison. The result of sorting in such case is undefined and the
* function returns FALSE.
*/
-//??? Z_UNSET_ISREF_P(array);
+ Z_ADDREF_P(array);
refcount = Z_REFCOUNT_P(array);
+ arr = Z_COUNTED_P(array);
if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_user_compare, 0 TSRMLS_CC) == FAILURE) {
RETVAL_FALSE;
} else {
if (refcount > Z_REFCOUNT_P(array)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array was modified by the user comparison function");
+ if (--GC_REFCOUNT(arr) <= 0) {
+ _zval_dtor_func(arr ZEND_FILE_LINE_CC);
+ }
RETVAL_FALSE;
} else {
+ Z_DELREF_P(array);
RETVAL_TRUE;
}
}
- if (Z_REFCOUNT_P(array) > 1) {
-//??? Z_SET_ISREF_P(array);
- }
-
PHP_ARRAY_CMP_FUNC_RESTORE();
}
/* }}} */
@@ -736,6 +740,7 @@ static int php_array_user_key_compare(const void *a, const void *b TSRMLS_DC) /*
PHP_FUNCTION(uksort)
{
zval *array;
+ zend_refcounted *arr;
unsigned int refcount;
PHP_ARRAY_CMP_FUNC_VARS;
@@ -746,30 +751,31 @@ PHP_FUNCTION(uksort)
return;
}
- /* Clear the is_ref flag, so the attemts to modify the array in user
- * comaprison function will create a copy of array and won't affect the
+ /* Increase reference counter, so the attemts to modify the array in user
+ * comparison function will create a copy of array and won't affect the
* original array. The fact of modification is detected using refcount
* comparison. The result of sorting in such case is undefined and the
* function returns FALSE.
*/
-//??? Z_UNSET_ISREF_P(array);
+ Z_ADDREF_P(array);
refcount = Z_REFCOUNT_P(array);
+ arr = Z_COUNTED_P(array);
if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_user_key_compare, 0 TSRMLS_CC) == FAILURE) {
RETVAL_FALSE;
} else {
if (refcount > Z_REFCOUNT_P(array)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array was modified by the user comparison function");
+ if (--GC_REFCOUNT(arr) <= 0) {
+ _zval_dtor_func(arr ZEND_FILE_LINE_CC);
+ }
RETVAL_FALSE;
} else {
+ Z_DELREF_P(array);
RETVAL_TRUE;
}
}
- if (Z_REFCOUNT_P(array) > 1) {
-//??? Z_SET_ISREF_P(array);
- }
-
PHP_ARRAY_CMP_FUNC_RESTORE();
}
/* }}} */