diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Zend/tests/const_array_with_resource_key.phpt | 2 | ||||
-rw-r--r-- | Zend/tests/isset_003.phpt | 2 | ||||
-rw-r--r-- | Zend/tests/isset_array.phpt | 48 | ||||
-rw-r--r-- | Zend/zend_API.c | 2 | ||||
-rw-r--r-- | Zend/zend_ast.c | 4 | ||||
-rw-r--r-- | Zend/zend_execute.c | 16 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_helpers.c | 2 | ||||
-rw-r--r-- | ext/spl/spl_array.c | 2 | ||||
-rw-r--r-- | ext/spl/tests/bug62978.phpt | 2 | ||||
-rw-r--r-- | ext/standard/array.c | 23 | ||||
-rwxr-xr-x | ext/standard/basic_functions.stub.php | 9 | ||||
-rwxr-xr-x | ext/standard/basic_functions_arginfo.h | 2 | ||||
-rw-r--r-- | ext/standard/tests/array/array_key_exists.phpt | 15 | ||||
-rw-r--r-- | ext/standard/tests/array/array_key_exists_variation1.phpt | 50 | ||||
-rw-r--r-- | ext/standard/tests/array/array_key_exists_variation3.phpt | 18 |
16 files changed, 128 insertions, 72 deletions
diff --git a/.gitignore b/.gitignore index df0fc80a5c..587f4abc42 100644 --- a/.gitignore +++ b/.gitignore @@ -247,6 +247,9 @@ php # Test results generated by `./run-tests.php` php_test_results_*.txt +# Temporary test information generated by `./run-tests.php` +/run-test-info.php + # Temporary POST data placeholder files generated by `./run-tests.php` phpt.* diff --git a/Zend/tests/const_array_with_resource_key.phpt b/Zend/tests/const_array_with_resource_key.phpt index 0bf546af50..1e3dee4734 100644 --- a/Zend/tests/const_array_with_resource_key.phpt +++ b/Zend/tests/const_array_with_resource_key.phpt @@ -8,7 +8,7 @@ var_dump(FOO); ?> --EXPECTF-- -Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d array(1) { [%d]=> int(42) diff --git a/Zend/tests/isset_003.phpt b/Zend/tests/isset_003.phpt index c80a174daf..7b29c1e6b8 100644 --- a/Zend/tests/isset_003.phpt +++ b/Zend/tests/isset_003.phpt @@ -1,5 +1,5 @@ --TEST-- -Testing isset accessing undefined array itens and properties +Testing isset accessing undefined array items and properties --FILE-- <?php diff --git a/Zend/tests/isset_array.phpt b/Zend/tests/isset_array.phpt new file mode 100644 index 0000000000..c7c1876410 --- /dev/null +++ b/Zend/tests/isset_array.phpt @@ -0,0 +1,48 @@ +--TEST-- +Using isset() with arrays +--FILE-- +<?php + +$array = [ + 0 => true, + "a" => true, +]; + +var_dump(isset($array[0])); + +var_dump(isset($array["a"])); + +var_dump(isset($array[false])); + +var_dump(isset($array[0.6])); + +var_dump(isset($array[true])); + +var_dump(isset($array[null])); + +var_dump(isset($array[STDIN])); + +try { + isset($array[[]]); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + isset($array[new stdClass()]); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) + +Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d +bool(false) +Illegal offset type in isset or empty +Illegal offset type in isset or empty diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 5781a95bfd..387f6e1a98 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1531,7 +1531,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */ result = zend_symtable_update(ht, ZSTR_EMPTY_ALLOC(), value); break; case IS_RESOURCE: - zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key)); + zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key)); result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value); break; case IS_FALSE: diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 660e6d5b6f..f0b524b30e 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -436,7 +436,7 @@ static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr) zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr); break; case IS_RESOURCE: - zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset)); + zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset)); zend_hash_index_update(Z_ARRVAL_P(result), Z_RES_HANDLE_P(offset), expr); break; default: @@ -451,7 +451,7 @@ static int zend_ast_add_unpacked_element(zval *result, zval *expr) { HashTable *ht = Z_ARRVAL_P(expr); zval *val; zend_string *key; - + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { if (key) { zend_throw_error(NULL, "Cannot unpack array with string keys"); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 345335b708..8278f698cd 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2369,6 +2369,7 @@ str_idx: hval = 1; goto num_idx; } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); hval = Z_RES_HANDLE_P(offset); goto num_idx; } else if (/*OP2_TYPE == IS_CV &&*/ Z_TYPE_P(offset) == IS_UNDEF) { @@ -2478,6 +2479,19 @@ num_key: } else if (EXPECTED(Z_ISREF_P(key))) { key = Z_REFVAL_P(key); goto try_again; + } else if (Z_TYPE_P(key) == IS_DOUBLE) { + hval = zend_dval_to_lval(Z_DVAL_P(key)); + goto num_key; + } else if (Z_TYPE_P(key) == IS_FALSE) { + hval = 0; + goto num_key; + } else if (Z_TYPE_P(key) == IS_TRUE) { + hval = 1; + goto num_key; + } else if (Z_TYPE_P(key) == IS_RESOURCE) { + zend_use_resource_as_offset(key); + hval = Z_RES_HANDLE_P(key); + goto num_key; } else if (Z_TYPE_P(key) <= IS_NULL) { if (UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); @@ -2485,7 +2499,7 @@ num_key: str = ZSTR_EMPTY_ALLOC(); goto str_key; } else { - zend_error(E_WARNING, "array_key_exists(): The first argument should be either a string or an integer"); + zend_type_error("Illegal offset type"); return 0; } } diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index da96660a10..f581841aab 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -400,7 +400,7 @@ static int ZEND_FASTCALL zend_jit_fetch_dim_isset_helper(zend_array *ht, zval *d hval = zend_dval_to_lval(Z_DVAL_P(dim)); goto num_index; case IS_RESOURCE: - //zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim)); + zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim)); hval = Z_RES_HANDLE_P(dim); goto num_index; case IS_FALSE: diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 4e9f9bde3c..bf33287fd0 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -348,7 +348,7 @@ fetch_dim_string: } return retval; case IS_RESOURCE: - zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_P(offset)->handle, Z_RES_P(offset)->handle); + zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_P(offset)->handle, Z_RES_P(offset)->handle); index = Z_RES_P(offset)->handle; goto num_index; case IS_DOUBLE: diff --git a/ext/spl/tests/bug62978.phpt b/ext/spl/tests/bug62978.phpt index ec6275346e..7e61d27b89 100644 --- a/ext/spl/tests/bug62978.phpt +++ b/ext/spl/tests/bug62978.phpt @@ -46,7 +46,7 @@ Notice: Undefined index: epic_magic in %sbug62978.php on line %d NULL bool(false) -Notice: Resource ID#%d used as offset, casting to integer (%d) in %sbug62978.php on line %d +Warning: Resource ID#%d used as offset, casting to integer (%d) in %sbug62978.php on line %d Notice: Undefined offset: %d in %sbug62978.php on line %d NULL diff --git a/ext/standard/array.c b/ext/standard/array.c index ffa695f26d..b8e727d103 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -40,6 +40,7 @@ #include "php_math.h" #include "zend_smart_str.h" #include "zend_bitset.h" +#include "zend_exceptions.h" #include "ext/spl/spl_array.h" /* {{{ defines */ @@ -765,6 +766,7 @@ PHP_FUNCTION(count) switch (Z_TYPE_P(array)) { case IS_NULL: + /* Intentionally not converted to an exception */ php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable"); RETURN_LONG(0); break; @@ -799,11 +801,13 @@ PHP_FUNCTION(count) } /* If There's no handler and it doesn't implement Countable then add a warning */ + /* Intentionally not converted to an exception */ php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable"); RETURN_LONG(1); break; } default: + /* Intentionally not converted to an exception */ php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable"); RETURN_LONG(1); break; @@ -5212,7 +5216,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_ param_spec = "+f"; diff_data_compare_func = php_array_user_compare; } else { - php_error_docref(NULL, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type); + ZEND_ASSERT(0 && "Invalid data_compare_type"); return; } @@ -6349,9 +6353,22 @@ PHP_FUNCTION(array_key_exists) case IS_NULL: RETVAL_BOOL(zend_hash_exists_ind(ht, ZSTR_EMPTY_ALLOC())); break; + case IS_DOUBLE: + RETVAL_BOOL(zend_hash_index_exists(ht, zend_dval_to_lval(Z_DVAL_P(key)))); + break; + case IS_FALSE: + RETVAL_BOOL(zend_hash_index_exists(ht, 0)); + break; + case IS_TRUE: + RETVAL_BOOL(zend_hash_index_exists(ht, 1)); + break; + case IS_RESOURCE: + zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key)); + RETVAL_BOOL(zend_hash_index_exists(ht, Z_RES_HANDLE_P(key))); + break; default: - php_error_docref(NULL, E_WARNING, "The first argument should be either a string or an integer"); - RETVAL_FALSE; + zend_type_error("Illegal offset type"); + break; } } /* }}} */ diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index de4d22bc3c..c596d216e8 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -63,7 +63,7 @@ function krsort(array &$arg, int $sort_flags = SORT_REGULAR): bool {} function ksort(array &$arg, int $sort_flags = SORT_REGULAR): bool {} -/** @param array|Countable $array */ +/** @param array|Countable $var */ function count($var, int $mode = COUNT_NORAML): int {} function natsort(array &$arg): bool {} @@ -258,11 +258,8 @@ function array_filter(array $arg, callable $callback = UNKNOWN, int $use_keys = function array_map(?callable $callback, array $arr1, array ...$arrays): array {} -/** - * @param int|string $key - * @param array|object $search - */ -function array_key_exists($key, $search): bool {} +/** @param mixed $key */ +function array_key_exists($key, array $search): bool {} function array_chunk(array $arg, int $size, bool $preserve_keys = false): array {} diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 103b44f152..200891a563 100755 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -341,7 +341,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_key_exists, 0, 2, _IS_BOOL, 0) ZEND_ARG_INFO(0, key) - ZEND_ARG_INFO(0, search) + ZEND_ARG_TYPE_INFO(0, search, IS_ARRAY, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_chunk, 0, 2, IS_ARRAY, 0) diff --git a/ext/standard/tests/array/array_key_exists.phpt b/ext/standard/tests/array/array_key_exists.phpt index 551ef85a67..a436e7363e 100644 --- a/ext/standard/tests/array/array_key_exists.phpt +++ b/ext/standard/tests/array/array_key_exists.phpt @@ -70,9 +70,11 @@ foreach ($search_arrays_v as $search_array) { echo "\n*** Testing error conditions ***\n"; // first args as array -var_dump( array_key_exists(array(), array()) ); -// first argument as floating point value -var_dump( array_key_exists(17.5, array(1,23) ) ) ; +try { + array_key_exists(array(), array()); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} echo "\n*** Testing operation on objects ***\n"; class key_check @@ -219,12 +221,7 @@ bool(false) bool(true) *** Testing error conditions *** - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +Illegal offset type *** Testing operation on objects *** array_key_exists() expects parameter 2 to be array, object given diff --git a/ext/standard/tests/array/array_key_exists_variation1.phpt b/ext/standard/tests/array/array_key_exists_variation1.phpt index c6e8ba7806..2f25dbadee 100644 --- a/ext/standard/tests/array/array_key_exists_variation1.phpt +++ b/ext/standard/tests/array/array_key_exists_variation1.phpt @@ -15,7 +15,7 @@ Test array_key_exists() function : usage variations - Pass different data types echo "*** Testing array_key_exists() : usage variations ***\n"; // Initialise function arguments not being substituted -$search = array ('zero', 'key' => 'val', 'two'); +$search = array ('zero', 'key' => 'val', 'two', 10 => 'value'); //get an unset variable $unset_var = 10; @@ -90,7 +90,11 @@ $inputs = array( $iterator = 1; foreach($inputs as $input) { echo "\n-- Iteration $iterator --\n"; - var_dump( array_key_exists($input, $search) ); + try { + var_dump( array_key_exists($input, $search) ); + } catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; + } $iterator++; }; @@ -114,29 +118,19 @@ bool(false) bool(false) -- Iteration 5 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +bool(true) -- Iteration 6 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d bool(false) -- Iteration 7 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d bool(false) -- Iteration 8 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +bool(true) -- Iteration 9 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +bool(true) -- Iteration 10 -- bool(false) @@ -145,24 +139,16 @@ bool(false) bool(false) -- Iteration 12 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +bool(true) -- Iteration 13 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +bool(true) -- Iteration 14 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +bool(true) -- Iteration 15 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +bool(true) -- Iteration 16 -- bool(false) @@ -171,9 +157,7 @@ bool(false) bool(false) -- Iteration 18 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +Illegal offset type -- Iteration 19 -- bool(true) @@ -185,9 +169,7 @@ bool(true) bool(true) -- Iteration 22 -- - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +Illegal offset type -- Iteration 23 -- bool(false) @@ -197,6 +179,6 @@ bool(false) -- Iteration 25 -- -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d +Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d bool(false) Done diff --git a/ext/standard/tests/array/array_key_exists_variation3.phpt b/ext/standard/tests/array/array_key_exists_variation3.phpt index 867b4d9848..11f0125be2 100644 --- a/ext/standard/tests/array/array_key_exists_variation3.phpt +++ b/ext/standard/tests/array/array_key_exists_variation3.phpt @@ -23,7 +23,11 @@ $iterator = 1; foreach($keys as $key) { echo "\n-- Iteration $iterator --\n"; echo "Pass float as \$key:\n"; - var_dump(array_key_exists($key, $search)); + try { + var_dump(array_key_exists($key, $search)); + } catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; + } echo "Cast float to int:\n"; var_dump(array_key_exists((int)$key, $search)); } @@ -35,25 +39,19 @@ echo "Done"; -- Iteration 1 -- Pass float as $key: - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +bool(true) Cast float to int: bool(true) -- Iteration 1 -- Pass float as $key: - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +bool(true) Cast float to int: bool(true) -- Iteration 1 -- Pass float as $key: - -Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d -bool(false) +bool(true) Cast float to int: bool(true) Done |