Skip to content

Commit 4fed57e

Browse files
committed
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.
1 parent 51275be commit 4fed57e

File tree

3 files changed

+21
-0
lines changed

3 files changed

+21
-0
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ PHP NEWS
5454
. Fixed bug GH-19701 (Serialize/deserialize loses some data). (nielsdos)
5555
. Fixed bug GH-19801 (leaks in var_dump() and debug_zval_dump()).
5656
(alexandre-daubois)
57+
. Fixed bug GH-20043 (array_unique assertion failure with RC1 array
58+
causing an exception on sort). (nielsdos)
5759

5860
- Streams:
5961
. Fixed bug GH-19248 (Use strerror_r instead of strerror in main).

ext/standard/array.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4900,6 +4900,11 @@ PHP_FUNCTION(array_unique)
49004900
ZVAL_UNDEF(&arTmp[i].b.val);
49014901
zend_sort((void *) arTmp, i, sizeof(struct bucketindex),
49024902
(compare_func_t) cmp, (swap_func_t) array_bucketindex_swap);
4903+
4904+
if (UNEXPECTED(EG(exception))) {
4905+
goto out;
4906+
}
4907+
49034908
/* go through the sorted array and delete duplicates from the copy */
49044909
lastkept = arTmp;
49054910
for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) {
@@ -4919,6 +4924,8 @@ PHP_FUNCTION(array_unique)
49194924
}
49204925
}
49214926
}
4927+
4928+
out:
49224929
pefree(arTmp, GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT);
49234930

49244931
if (in_place) {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
GH-20043 (array_unique assertion failure with RC1 array causing an exception on sort)
3+
--FILE--
4+
<?php
5+
try {
6+
array_unique([new stdClass, new stdClass], SORT_STRING | SORT_FLAG_CASE);
7+
} catch (Error $e) {
8+
echo $e->getMessage();
9+
}
10+
?>
11+
--EXPECT--
12+
Object of class stdClass could not be converted to string

0 commit comments

Comments
 (0)