1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-20043: array_unique assertion failure with RC1 array causing an exception on sort

The reason this happens is because the array_unique operation happens in-place
because the input array is RC1.
At one point during comparison an exception is thrown which will capture the
arguments in the backtrace, which will increment the refcount of the RC1 array
to 2. Then a modification happens after the throw on the RC2 array causing the
assertion failure.
We shouldn't try continue work after an exception happened during the sort.

Closes GH-20059.
This commit is contained in:
Niels Dossche
2025-10-04 14:59:27 +02:00
parent 51275be6c5
commit 4fed57e746
3 changed files with 21 additions and 0 deletions

2
NEWS
View File

@@ -54,6 +54,8 @@ PHP NEWS
. Fixed bug GH-19701 (Serialize/deserialize loses some data). (nielsdos) . Fixed bug GH-19701 (Serialize/deserialize loses some data). (nielsdos)
. Fixed bug GH-19801 (leaks in var_dump() and debug_zval_dump()). . Fixed bug GH-19801 (leaks in var_dump() and debug_zval_dump()).
(alexandre-daubois) (alexandre-daubois)
. Fixed bug GH-20043 (array_unique assertion failure with RC1 array
causing an exception on sort). (nielsdos)
- Streams: - Streams:
. Fixed bug GH-19248 (Use strerror_r instead of strerror in main). . Fixed bug GH-19248 (Use strerror_r instead of strerror in main).

View File

@@ -4900,6 +4900,11 @@ PHP_FUNCTION(array_unique)
ZVAL_UNDEF(&arTmp[i].b.val); ZVAL_UNDEF(&arTmp[i].b.val);
zend_sort((void *) arTmp, i, sizeof(struct bucketindex), zend_sort((void *) arTmp, i, sizeof(struct bucketindex),
(compare_func_t) cmp, (swap_func_t) array_bucketindex_swap); (compare_func_t) cmp, (swap_func_t) array_bucketindex_swap);
if (UNEXPECTED(EG(exception))) {
goto out;
}
/* go through the sorted array and delete duplicates from the copy */ /* go through the sorted array and delete duplicates from the copy */
lastkept = arTmp; lastkept = arTmp;
for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) { for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) {
@@ -4919,6 +4924,8 @@ PHP_FUNCTION(array_unique)
} }
} }
} }
out:
pefree(arTmp, GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT); pefree(arTmp, GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT);
if (in_place) { if (in_place) {

View File

@@ -0,0 +1,12 @@
--TEST--
GH-20043 (array_unique assertion failure with RC1 array causing an exception on sort)
--FILE--
<?php
try {
array_unique([new stdClass, new stdClass], SORT_STRING | SORT_FLAG_CASE);
} catch (Error $e) {
echo $e->getMessage();
}
?>
--EXPECT--
Object of class stdClass could not be converted to string