diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/standard/array.c | 12 | ||||
-rw-r--r-- | ext/standard/tests/array/bug74345.phpt | 27 |
2 files changed, 39 insertions, 0 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c index 297b0c0f38..2658ad68f5 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1013,6 +1013,7 @@ static int php_array_user_compare(const void *a, const void *b) /* {{{ */ BG(user_compare_fci_cache) = empty_fcall_info_cache; \ #define PHP_ARRAY_CMP_FUNC_RESTORE() \ + zend_release_fcall_info_cache(&BG(user_compare_fci_cache)); \ BG(user_compare_fci) = old_user_compare_fci; \ BG(user_compare_fci_cache) = old_user_compare_fci_cache; \ @@ -1502,6 +1503,7 @@ PHP_FUNCTION(array_walk) ); php_array_walk(array, userdata, 0); + zend_release_fcall_info_cache(&BG(array_walk_fci_cache)); BG(array_walk_fci) = orig_array_walk_fci; BG(array_walk_fci_cache) = orig_array_walk_fci_cache; RETURN_TRUE; @@ -1532,6 +1534,7 @@ PHP_FUNCTION(array_walk_recursive) ); php_array_walk(array, userdata, 1); + zend_release_fcall_info_cache(&BG(array_walk_fci_cache)); BG(array_walk_fci) = orig_array_walk_fci; BG(array_walk_fci_cache) = orig_array_walk_fci_cache; RETURN_TRUE; @@ -6017,6 +6020,7 @@ PHP_FUNCTION(array_reduce) if (zend_hash_num_elements(htbl) == 0) { ZVAL_COPY_VALUE(return_value, &result); + zend_release_fcall_info_cache(&fci_cache); return; } @@ -6040,6 +6044,7 @@ PHP_FUNCTION(array_reduce) } } ZEND_HASH_FOREACH_END(); + zend_release_fcall_info_cache(&fci_cache); RETVAL_ZVAL(&result, 1, 1); } /* }}} */ @@ -6069,6 +6074,7 @@ PHP_FUNCTION(array_filter) array_init(return_value); if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) { + zend_release_fcall_info_cache(&fci_cache); return; } @@ -6130,6 +6136,8 @@ PHP_FUNCTION(array_filter) } zval_add_ref(operand); } ZEND_HASH_FOREACH_END(); + + zend_release_fcall_info_cache(&fci_cache); } /* }}} */ @@ -6167,6 +6175,7 @@ PHP_FUNCTION(array_map) /* Short-circuit: if no callback and only one array, just return it. */ if (!ZEND_FCI_INITIALIZED(fci) || !maxlen) { ZVAL_COPY(return_value, &arrays[0]); + zend_release_fcall_info_cache(&fci_cache); return; } @@ -6192,6 +6201,8 @@ PHP_FUNCTION(array_map) zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result); } } ZEND_HASH_FOREACH_END(); + + zend_release_fcall_info_cache(&fci_cache); } else { uint32_t *array_pos = (HashPosition *)ecalloc(n_arrays, sizeof(HashPosition)); @@ -6284,6 +6295,7 @@ PHP_FUNCTION(array_map) } efree(params); + zend_release_fcall_info_cache(&fci_cache); } efree(array_pos); } diff --git a/ext/standard/tests/array/bug74345.phpt b/ext/standard/tests/array/bug74345.phpt new file mode 100644 index 0000000000..144d257f55 --- /dev/null +++ b/ext/standard/tests/array/bug74345.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #74345: Call trampoline leaked if callback not invoked +--FILE-- +<?php + +class Test { + public function __call($name, $args) { + echo "__call()\n"; + } +} + +$name = "foo" . ($x = "bar"); +$cb = [new Test, $name]; +array_map($cb, []); +array_map($cb, [], []); +array_filter([], $cb); +array_reduce([], $cb); + +$array = []; +array_walk($array, $cb); +array_walk_recursive($array, $cb); +usort($array, $cb); + +?> +===DONE=== +--EXPECT-- +===DONE=== |