Browse Source

proper fix for bug #50006

add modify protection to all user array sorts
experimental/5.3-FPM
Stanislav Malyshev 17 years ago
parent
commit
8b64f74baa
  1. 25
      ext/standard/array.c
  2. 29
      ext/standard/tests/array/bug50006_1.phpt
  3. 29
      ext/standard/tests/array/bug50006_2.phpt

25
ext/standard/array.c

@ -768,6 +768,7 @@ static int php_array_user_key_compare(const void *a, const void *b TSRMLS_DC) /*
PHP_FUNCTION(uksort)
{
zval *array;
int refcount;
PHP_ARRAY_CMP_FUNC_VARS;
PHP_ARRAY_CMP_FUNC_BACKUP();
@ -777,13 +778,31 @@ PHP_FUNCTION(uksort)
return;
}
/* Clear the is_ref flag, so the attemts to modify the array in user
* comaprison function will create a copy of array and won't affect the
* original array. The fact of modification is detected using refcount
* comparison. The result of sorting in such case is undefined and the
* function returns FALSE.
*/
Z_UNSET_ISREF_P(array);
refcount = Z_REFCOUNT_P(array);
if (zend_hash_sort(Z_ARRVAL_P(array), zend_qsort, php_array_user_key_compare, 0 TSRMLS_CC) == FAILURE) {
PHP_ARRAY_CMP_FUNC_RESTORE();
RETURN_FALSE;
RETVAL_FALSE;
} else {
if (refcount > Z_REFCOUNT_P(array)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array was modified by the user comparison function");
RETVAL_FALSE;
} else {
RETVAL_TRUE;
}
}
if (Z_REFCOUNT_P(array) > 1) {
Z_SET_ISREF_P(array);
}
PHP_ARRAY_CMP_FUNC_RESTORE();
RETURN_TRUE;
}
/* }}} */

29
ext/standard/tests/array/bug50006_1.phpt

@ -0,0 +1,29 @@
--TEST--
Bug #50006 (Segfault caused by uksort()) - usort variant
--FILE--
<?php
$data = array(
'bar-bazbazbaz.',
'bar-bazbazbaz-',
'foo'
);
usort($data, 'magic_sort_cmp');
print_r($data);
function magic_sort_cmp($a, $b) {
$a = substr($a, 1);
$b = substr($b, 1);
if (!$a) return $b ? -1 : 0;
if (!$b) return 1;
return magic_sort_cmp($a, $b);
}
?>
--EXPECTF--
Array
(
[0] => foo
[1] => bar-bazbazbaz-
[2] => bar-bazbazbaz.
)

29
ext/standard/tests/array/bug50006_2.phpt

@ -0,0 +1,29 @@
--TEST--
Bug #50006 (Segfault caused by uksort()) - uasort variant
--FILE--
<?php
$data = array(
'bar-bazbazbaz.',
'bar-bazbazbaz-',
'foo'
);
uasort($data, 'magic_sort_cmp');
print_r($data);
function magic_sort_cmp($a, $b) {
$a = substr($a, 1);
$b = substr($b, 1);
if (!$a) return $b ? -1 : 0;
if (!$b) return 1;
return magic_sort_cmp($a, $b);
}
?>
--EXPECTF--
Array
(
[2] => foo
[1] => bar-bazbazbaz-
[0] => bar-bazbazbaz.
)
Loading…
Cancel
Save