diff --git a/ext/standard/array.c b/ext/standard/array.c index 4d3c03bce5262..a2a0459ec3b29 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -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 @@ -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; } @@ -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])); @@ -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 @@ -6074,6 +6077,7 @@ PHP_FUNCTION(array_multisort) efree(indirect); efree(func); efree(arrays); + ARRAYG(multisort_func) = old_multisort_func; } /* }}} */ diff --git a/ext/standard/tests/array/gh19300_1.phpt b/ext/standard/tests/array/gh19300_1.phpt new file mode 100644 index 0000000000000..18b639bf425b8 --- /dev/null +++ b/ext/standard/tests/array/gh19300_1.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-19300 (Nested array_multisort invocation with error breaks) - correct invocation variation +--FILE-- +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" + } +} diff --git a/ext/standard/tests/array/gh19300_2.phpt b/ext/standard/tests/array/gh19300_2.phpt new file mode 100644 index 0000000000000..41ae7e82bb796 --- /dev/null +++ b/ext/standard/tests/array/gh19300_2.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-19300 (Nested array_multisort invocation with error breaks) - error variation +--FILE-- +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) { + } +}