Skip to content

Commit 8c1a96f

Browse files
committed
Make array_multisort() stable
1 parent 1db9c24 commit 8c1a96f

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

ext/standard/array.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5570,7 +5570,7 @@ PHPAPI int php_multisort_compare(const void *a, const void *b) /* {{{ */
55705570
r++;
55715571
} while (Z_TYPE(ab[r].val) != IS_UNDEF);
55725572

5573-
return 0;
5573+
return stable_sort_fallback(&ab[r], &bb[r]);
55745574
}
55755575
/* }}} */
55765576

@@ -5707,8 +5707,8 @@ PHP_FUNCTION(array_multisort)
57075707

57085708
/* Create the indirection array. This array is of size MxN, where
57095709
* M is the number of entries in each input array and N is the number
5710-
* of the input arrays + 1. The last column is NULL to indicate the end
5711-
* of the row. */
5710+
* of the input arrays + 1. The last column is UNDEF to indicate the end
5711+
* of the row. It also stores the original position for stable sorting. */
57125712
indirect = (Bucket **)safe_emalloc(array_size, sizeof(Bucket *), 0);
57135713
for (i = 0; i < array_size; i++) {
57145714
indirect[i] = (Bucket *)safe_emalloc((num_arrays + 1), sizeof(Bucket), 0);
@@ -5724,6 +5724,7 @@ PHP_FUNCTION(array_multisort)
57245724
}
57255725
for (k = 0; k < array_size; k++) {
57265726
ZVAL_UNDEF(&indirect[k][num_arrays].val);
5727+
Z_EXTRA_P(&indirect[k][num_arrays].val) = k;
57275728
}
57285729

57295730
/* Do the actual sort magic - bada-bim, bada-boom. */
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
array_multisort() is stable
3+
--FILE--
4+
<?php
5+
6+
// Something of a dummy example where 0 and '0' are used as equal elements.
7+
8+
$ary1 = array_fill(0, 100, 0);
9+
$origAry2 = $ary2 = array_merge(...array_fill(0, 50, [0, '0']));
10+
array_multisort($ary1, $ary2);
11+
var_dump($ary2 === $origAry2);
12+
13+
?>
14+
--EXPECT--
15+
bool(true)

0 commit comments

Comments
 (0)