summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Pena <felipe@php.net>2009-11-01 17:30:55 +0000
committerFelipe Pena <felipe@php.net>2009-11-01 17:30:55 +0000
commitfa23faaca4f8c54c26e7920a1673ac09f26fbc6c (patch)
treed76022301ad060cb2df1cf5388ca3ab761e2d6ac
parentcaa28c2a22ea36205af97fd13e3599caf77f0f76 (diff)
downloadphp-git-fa23faaca4f8c54c26e7920a1673ac09f26fbc6c.tar.gz
- Fixed bug #50006 (Segfault caused by uksort()) [5_2 only]
-rw-r--r--NEWS1
-rw-r--r--ext/standard/array.c40
-rw-r--r--ext/standard/tests/array/bug50006.phpt29
3 files changed, 57 insertions, 13 deletions
diff --git a/NEWS b/NEWS
index 2460f80535..972841e6ad 100644
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,7 @@ PHP NEWS
(Felipe)
- Fixed memory leak in openssl_pkcs12_export_to_file(). (Felipe)
+- Fixed bug #50006 (Segfault caused by uksort()). (Felipe)
- Fixed bug #49990 (SNMP3 warning message about security level printed twice).
(Jani)
- Fixed bug #49985 (pdo_pgsql prepare() re-use previous aborted
diff --git a/ext/standard/array.c b/ext/standard/array.c
index b834b08ffb..58448cfdd4 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -762,17 +762,17 @@ PHP_FUNCTION(uasort)
static int array_user_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{ */
{
+ zend_fcall_info fci;
Bucket *f;
Bucket *s;
zval *key1, *key2;
- zval *args[2];
- zval retval;
- int status;
+ zval **args[2];
+ zval *retval_ptr = NULL;
ALLOC_INIT_ZVAL(key1);
ALLOC_INIT_ZVAL(key2);
- args[0] = key1;
- args[1] = key2;
+ args[0] = &key1;
+ args[1] = &key2;
f = *((Bucket **) a);
s = *((Bucket **) b);
@@ -793,16 +793,30 @@ static int array_user_key_compare(const void *a, const void *b TSRMLS_DC) /* {{{
Z_LVAL_P(key2) = s->h;
Z_TYPE_P(key2) = IS_LONG;
}
-
- status = call_user_function(EG(function_table), NULL, *BG(user_compare_func_name), &retval, 2, args TSRMLS_CC);
- zval_ptr_dtor(&key1);
- zval_ptr_dtor(&key2);
-
- if (status == SUCCESS) {
- convert_to_long(&retval);
- return Z_LVAL(retval);
+ fci.size = sizeof(fci);
+ fci.function_table = EG(function_table);
+ fci.function_name = *BG(user_compare_func_name);
+ fci.symbol_table = NULL;
+ fci.object_pp = NULL;
+ fci.retval_ptr_ptr = &retval_ptr;
+ fci.param_count = 2;
+ fci.params = args;
+ fci.no_separation = 0;
+
+ if (zend_call_function(&fci, &BG(user_compare_fci_cache) TSRMLS_CC)== SUCCESS
+ && retval_ptr) {
+ long retval;
+
+ convert_to_long_ex(&retval_ptr);
+ retval = Z_LVAL_P(retval_ptr);
+ zval_ptr_dtor(&retval_ptr);
+ zval_ptr_dtor(&key1);
+ zval_ptr_dtor(&key2);
+ return retval;
} else {
+ zval_ptr_dtor(&key1);
+ zval_ptr_dtor(&key2);
return 0;
}
}
diff --git a/ext/standard/tests/array/bug50006.phpt b/ext/standard/tests/array/bug50006.phpt
new file mode 100644
index 0000000000..f03a002629
--- /dev/null
+++ b/ext/standard/tests/array/bug50006.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Bug #50006 (Segfault caused by uksort())
+--FILE--
+<?php
+
+$data = array(
+ 'bar-bazbazbaz.' => 0,
+ 'bar-bazbazbaz-' => 0,
+ 'foo' => 0,
+);
+uksort($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
+(
+ [foo] => 0
+ [bar-bazbazbaz-] => 0
+ [bar-bazbazbaz.] => 0
+)