Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions ext/standard/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -5911,7 +5911,7 @@ PHP_FUNCTION(array_multisort)
for (i = 0; i < MULTISORT_LAST; i++) {
parse_state[i] = 0;
}
func = ARRAYG(multisort_func) = ecalloc(argc, sizeof(bucket_compare_func_t));
func = ecalloc(argc, sizeof(bucket_compare_func_t));

/* Here we go through the input arguments and parse them. Each one can
* be either an array or a sort flag which follows an array. If not
Expand All @@ -5927,7 +5927,7 @@ PHP_FUNCTION(array_multisort)
/* We see the next array, so we update the sort flags of
* the previous array and reset the sort flags. */
if (i > 0) {
ARRAYG(multisort_func)[num_arrays - 1] = php_get_data_compare_func_unstable(sort_type, sort_order != PHP_SORT_ASC);
func[num_arrays - 1] = php_get_data_compare_func_unstable(sort_type, sort_order != PHP_SORT_ASC);
sort_order = PHP_SORT_ASC;
sort_type = PHP_SORT_REGULAR;
}
Expand Down Expand Up @@ -5979,8 +5979,6 @@ PHP_FUNCTION(array_multisort)
MULTISORT_ABORT;
}
}
/* Take care of the last array sort flags. */
ARRAYG(multisort_func)[num_arrays - 1] = php_get_data_compare_func_unstable(sort_type, sort_order != PHP_SORT_ASC);

/* Make sure the arrays are of the same size. */
array_size = zend_hash_num_elements(Z_ARRVAL_P(arrays[0]));
Expand All @@ -5998,6 +5996,11 @@ PHP_FUNCTION(array_multisort)
RETURN_TRUE;
}

/* Take care of the last array sort flags. */
func[num_arrays - 1] = php_get_data_compare_func_unstable(sort_type, sort_order != PHP_SORT_ASC);
bucket_compare_func_t *old_multisort_func = ARRAYG(multisort_func);
ARRAYG(multisort_func) = func;

/* Create the indirection array. This array is of size MxN, where
* M is the number of entries in each input array and N is the number
* of the input arrays + 1. The last column is UNDEF to indicate the end
Expand Down Expand Up @@ -6074,6 +6077,7 @@ PHP_FUNCTION(array_multisort)
efree(indirect);
efree(func);
efree(arrays);
ARRAYG(multisort_func) = old_multisort_func;
}
/* }}} */

Expand Down
40 changes: 40 additions & 0 deletions ext/standard/tests/array/gh19300_1.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
--TEST--
GH-19300 (Nested array_multisort invocation with error breaks) - correct invocation variation
--FILE--
<?php
class MyStringable {
public function __construct(private string $data) {}
public function __tostring() {
array_multisort([]); // Trigger update of array sort globals in happy path
return $this->data;
}
}

$inputs = [
new MyStringable('3'),
new MyStringable('1'),
new MyStringable('2'),
];

var_dump(array_multisort($inputs, SORT_STRING));
var_dump($inputs);
?>
--EXPECT--
bool(true)
array(3) {
[0]=>
object(MyStringable)#2 (1) {
["data":"MyStringable":private]=>
string(1) "1"
}
[1]=>
object(MyStringable)#3 (1) {
["data":"MyStringable":private]=>
string(1) "2"
}
[2]=>
object(MyStringable)#1 (1) {
["data":"MyStringable":private]=>
string(1) "3"
}
}
40 changes: 40 additions & 0 deletions ext/standard/tests/array/gh19300_2.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
--TEST--
GH-19300 (Nested array_multisort invocation with error breaks) - error variation
--FILE--
<?php

function error_handle($level, $message, $file = '', $line = 0){
try {
array_multisort($a, SORT_ASC); // Trigger multisort abort
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
}
set_error_handler('error_handle');

$inputs = [
new stdClass,
new stdClass,
new stdClass,
];

var_dump(array_multisort($inputs, SORT_NUMERIC));
var_dump($inputs);
?>
--EXPECT--
array_multisort(): Argument #1 ($array) must be an array or a sort flag
array_multisort(): Argument #1 ($array) must be an array or a sort flag
array_multisort(): Argument #1 ($array) must be an array or a sort flag
array_multisort(): Argument #1 ($array) must be an array or a sort flag
bool(true)
array(3) {
[0]=>
object(stdClass)#1 (0) {
}
[1]=>
object(stdClass)#2 (0) {
}
[2]=>
object(stdClass)#3 (0) {
}
}
Loading