]> granicus.if.org Git - php/commitdiff
- Fixed bug #50006 (Segfault caused by uksort()) [5_2 only]
authorFelipe Pena <felipe@php.net>
Sun, 1 Nov 2009 17:30:55 +0000 (17:30 +0000)
committerFelipe Pena <felipe@php.net>
Sun, 1 Nov 2009 17:30:55 +0000 (17:30 +0000)
NEWS
ext/standard/array.c
ext/standard/tests/array/bug50006.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 2460f80535b294c59dded4877a5caf7b63fcae98..972841e6adfad4dba7c2d9a93d04f7a876cdca41 100644 (file)
--- 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
index b834b08ffba0f4b488e3f4d95b46c9c27a911bef..58448cfdd45c4038e304959a2683ff591a679c85 100644 (file)
@@ -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 (file)
index 0000000..f03a002
--- /dev/null
@@ -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
+)