Skip to content

Commit 7e3a206

Browse files
committed
Promote the warning of array_key_exists() to exception
1 parent 6d0366a commit 7e3a206

13 files changed

+81
-70
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ php
247247
# Test results generated by `./run-tests.php`
248248
php_test_results_*.txt
249249

250+
# Temporary test information generated by `./run-tests.php`
251+
/run-test-info.php
252+
250253
# Temporary POST data placeholder files generated by `./run-tests.php`
251254
phpt.*
252255

Zend/tests/const_array_with_resource_key.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var_dump(FOO);
88

99
?>
1010
--EXPECTF--
11-
Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
11+
Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
1212
array(1) {
1313
[%d]=>
1414
int(42)

Zend/zend_API.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1531,7 +1531,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
15311531
result = zend_symtable_update(ht, ZSTR_EMPTY_ALLOC(), value);
15321532
break;
15331533
case IS_RESOURCE:
1534-
zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
1534+
zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
15351535
result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
15361536
break;
15371537
case IS_FALSE:

Zend/zend_ast.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
436436
zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr);
437437
break;
438438
case IS_RESOURCE:
439-
zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
439+
zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
440440
zend_hash_index_update(Z_ARRVAL_P(result), Z_RES_HANDLE_P(offset), expr);
441441
break;
442442
default:
@@ -451,7 +451,7 @@ static int zend_ast_add_unpacked_element(zval *result, zval *expr) {
451451
HashTable *ht = Z_ARRVAL_P(expr);
452452
zval *val;
453453
zend_string *key;
454-
454+
455455
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
456456
if (key) {
457457
zend_throw_error(NULL, "Cannot unpack array with string keys");

Zend/zend_execute.c

+15-1
Original file line numberDiff line numberDiff line change
@@ -2369,6 +2369,7 @@ static zend_never_inline zval* ZEND_FASTCALL zend_find_array_dim_slow(HashTable
23692369
hval = 1;
23702370
goto num_idx;
23712371
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
2372+
zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
23722373
hval = Z_RES_HANDLE_P(offset);
23732374
goto num_idx;
23742375
} else if (/*OP2_TYPE == IS_CV &&*/ Z_TYPE_P(offset) == IS_UNDEF) {
@@ -2478,14 +2479,27 @@ static zend_never_inline zend_bool ZEND_FASTCALL zend_array_key_exists_fast(Hash
24782479
} else if (EXPECTED(Z_ISREF_P(key))) {
24792480
key = Z_REFVAL_P(key);
24802481
goto try_again;
2482+
} else if (Z_TYPE_P(key) == IS_DOUBLE) {
2483+
hval = zend_dval_to_lval(Z_DVAL_P(key));
2484+
goto num_key;
2485+
} else if (Z_TYPE_P(key) == IS_FALSE) {
2486+
hval = 0;
2487+
goto num_key;
2488+
} else if (Z_TYPE_P(key) == IS_TRUE) {
2489+
hval = 1;
2490+
goto num_key;
2491+
} else if (Z_TYPE_P(key) == IS_RESOURCE) {
2492+
zend_use_resource_as_offset(key);
2493+
hval = Z_RES_HANDLE_P(key);
2494+
goto num_key;
24812495
} else if (Z_TYPE_P(key) <= IS_NULL) {
24822496
if (UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) {
24832497
ZVAL_UNDEFINED_OP1();
24842498
}
24852499
str = ZSTR_EMPTY_ALLOC();
24862500
goto str_key;
24872501
} else {
2488-
zend_error(E_WARNING, "array_key_exists(): The first argument should be either a string or an integer");
2502+
zend_type_error("Illegal offset type");
24892503
return 0;
24902504
}
24912505
}

ext/spl/spl_array.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ static zval *spl_array_get_dimension_ptr(int check_inherited, spl_array_object *
348348
}
349349
return retval;
350350
case IS_RESOURCE:
351-
zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_P(offset)->handle, Z_RES_P(offset)->handle);
351+
zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_P(offset)->handle, Z_RES_P(offset)->handle);
352352
index = Z_RES_P(offset)->handle;
353353
goto num_index;
354354
case IS_DOUBLE:

ext/spl/tests/bug62978.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Notice: Undefined index: epic_magic in %sbug62978.php on line %d
4646
NULL
4747
bool(false)
4848

49-
Notice: Resource ID#%d used as offset, casting to integer (%d) in %sbug62978.php on line %d
49+
Warning: Resource ID#%d used as offset, casting to integer (%d) in %sbug62978.php on line %d
5050

5151
Notice: Undefined offset: %d in %sbug62978.php on line %d
5252
NULL

ext/standard/array.c

+23-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "php_math.h"
4141
#include "zend_smart_str.h"
4242
#include "zend_bitset.h"
43+
#include "zend_exceptions.h"
4344
#include "ext/spl/spl_array.h"
4445

4546
/* {{{ defines */
@@ -765,6 +766,7 @@ PHP_FUNCTION(count)
765766

766767
switch (Z_TYPE_P(array)) {
767768
case IS_NULL:
769+
/* Intentionally not converted to an exception */
768770
php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
769771
RETURN_LONG(0);
770772
break;
@@ -799,11 +801,13 @@ PHP_FUNCTION(count)
799801
}
800802

801803
/* If There's no handler and it doesn't implement Countable then add a warning */
804+
/* Intentionally not converted to an exception */
802805
php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
803806
RETURN_LONG(1);
804807
break;
805808
}
806809
default:
810+
/* Intentionally not converted to an exception */
807811
php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
808812
RETURN_LONG(1);
809813
break;
@@ -5212,7 +5216,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_
52125216
param_spec = "+f";
52135217
diff_data_compare_func = php_array_user_compare;
52145218
} else {
5215-
php_error_docref(NULL, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
5219+
zend_value_error("data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
52165220
return;
52175221
}
52185222

@@ -6349,9 +6353,25 @@ PHP_FUNCTION(array_key_exists)
63496353
case IS_NULL:
63506354
RETVAL_BOOL(zend_hash_exists_ind(ht, ZSTR_EMPTY_ALLOC()));
63516355
break;
6356+
case IS_DOUBLE:
6357+
RETVAL_BOOL(zend_hash_index_exists(ht, zend_dval_to_lval(Z_DVAL_P(key))));
6358+
break;
6359+
case IS_FALSE:
6360+
RETVAL_BOOL(zend_hash_index_exists(ht, 0));
6361+
break;
6362+
case IS_TRUE:
6363+
RETVAL_BOOL(zend_hash_index_exists(ht, 1));
6364+
break;
6365+
case IS_RESOURCE:
6366+
zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
6367+
RETVAL_BOOL(zend_hash_index_exists(ht, Z_RES_HANDLE_P(key)));
6368+
break;
6369+
case IS_UNDEF:
6370+
RETVAL_BOOL(zend_symtable_exists_ind(ht, ZSTR_EMPTY_ALLOC()));
6371+
break;
63526372
default:
6353-
php_error_docref(NULL, E_WARNING, "The first argument should be either a string or an integer");
6354-
RETVAL_FALSE;
6373+
zend_type_error("Illegal offset type");
6374+
break;
63556375
}
63566376
}
63576377
/* }}} */

ext/standard/basic_functions.stub.php

+3-6
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function krsort(array &$arg, int $sort_flags = SORT_REGULAR): bool {}
6363

6464
function ksort(array &$arg, int $sort_flags = SORT_REGULAR): bool {}
6565

66-
/** @param array|Countable $array */
66+
/** @param array|Countable $var */
6767
function count($var, int $mode = COUNT_NORAML): int {}
6868

6969
function natsort(array &$arg): bool {}
@@ -258,11 +258,8 @@ function array_filter(array $arg, callable $callback = UNKNOWN, int $use_keys =
258258

259259
function array_map(?callable $callback, array $arr1, array ...$arrays): array {}
260260

261-
/**
262-
* @param int|string $key
263-
* @param array|object $search
264-
*/
265-
function array_key_exists($key, $search): bool {}
261+
/** @param mixed $key */
262+
function array_key_exists($key, array $search): bool {}
266263

267264
function array_chunk(array $arg, int $size, bool $preserve_keys = false): array {}
268265

ext/standard/basic_functions_arginfo.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ ZEND_END_ARG_INFO()
341341

342342
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_key_exists, 0, 2, _IS_BOOL, 0)
343343
ZEND_ARG_INFO(0, key)
344-
ZEND_ARG_INFO(0, search)
344+
ZEND_ARG_TYPE_INFO(0, search, IS_ARRAY, 0)
345345
ZEND_END_ARG_INFO()
346346

347347
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_array_chunk, 0, 2, IS_ARRAY, 0)

ext/standard/tests/array/array_key_exists.phpt

+6-9
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,11 @@ foreach ($search_arrays_v as $search_array) {
7070

7171
echo "\n*** Testing error conditions ***\n";
7272
// first args as array
73-
var_dump( array_key_exists(array(), array()) );
74-
// first argument as floating point value
75-
var_dump( array_key_exists(17.5, array(1,23) ) ) ;
73+
try {
74+
array_key_exists(array(), array());
75+
} catch (TypeError $exception) {
76+
echo $exception->getMessage() . "\n";
77+
}
7678

7779
echo "\n*** Testing operation on objects ***\n";
7880
class key_check
@@ -219,12 +221,7 @@ bool(false)
219221
bool(true)
220222

221223
*** Testing error conditions ***
222-
223-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
224-
bool(false)
225-
226-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
227-
bool(false)
224+
Illegal offset type
228225

229226
*** Testing operation on objects ***
230227
array_key_exists() expects parameter 2 to be array, object given

ext/standard/tests/array/array_key_exists_variation1.phpt

+16-34
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Test array_key_exists() function : usage variations - Pass different data types
1515
echo "*** Testing array_key_exists() : usage variations ***\n";
1616

1717
// Initialise function arguments not being substituted
18-
$search = array ('zero', 'key' => 'val', 'two');
18+
$search = array ('zero', 'key' => 'val', 'two', 10 => 'value');
1919

2020
//get an unset variable
2121
$unset_var = 10;
@@ -90,7 +90,11 @@ $inputs = array(
9090
$iterator = 1;
9191
foreach($inputs as $input) {
9292
echo "\n-- Iteration $iterator --\n";
93-
var_dump( array_key_exists($input, $search) );
93+
try {
94+
var_dump( array_key_exists($input, $search) );
95+
} catch (TypeError $exception) {
96+
echo $exception->getMessage() . "\n";
97+
}
9498
$iterator++;
9599
};
96100

@@ -114,29 +118,19 @@ bool(false)
114118
bool(false)
115119

116120
-- Iteration 5 --
117-
118-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
119-
bool(false)
121+
bool(true)
120122

121123
-- Iteration 6 --
122-
123-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
124124
bool(false)
125125

126126
-- Iteration 7 --
127-
128-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
129127
bool(false)
130128

131129
-- Iteration 8 --
132-
133-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
134-
bool(false)
130+
bool(true)
135131

136132
-- Iteration 9 --
137-
138-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
139-
bool(false)
133+
bool(true)
140134

141135
-- Iteration 10 --
142136
bool(false)
@@ -145,24 +139,16 @@ bool(false)
145139
bool(false)
146140

147141
-- Iteration 12 --
148-
149-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
150-
bool(false)
142+
bool(true)
151143

152144
-- Iteration 13 --
153-
154-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
155-
bool(false)
145+
bool(true)
156146

157147
-- Iteration 14 --
158-
159-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
160-
bool(false)
148+
bool(true)
161149

162150
-- Iteration 15 --
163-
164-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
165-
bool(false)
151+
bool(true)
166152

167153
-- Iteration 16 --
168154
bool(false)
@@ -171,9 +157,7 @@ bool(false)
171157
bool(false)
172158

173159
-- Iteration 18 --
174-
175-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
176-
bool(false)
160+
Illegal offset type
177161

178162
-- Iteration 19 --
179163
bool(true)
@@ -185,9 +169,7 @@ bool(true)
185169
bool(true)
186170

187171
-- Iteration 22 --
188-
189-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
190-
bool(false)
172+
Illegal offset type
191173

192174
-- Iteration 23 --
193175
bool(false)
@@ -197,6 +179,6 @@ bool(false)
197179

198180
-- Iteration 25 --
199181

200-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
182+
Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
201183
bool(false)
202184
Done

ext/standard/tests/array/array_key_exists_variation3.phpt

+8-10
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ $iterator = 1;
2323
foreach($keys as $key) {
2424
echo "\n-- Iteration $iterator --\n";
2525
echo "Pass float as \$key:\n";
26-
var_dump(array_key_exists($key, $search));
26+
try {
27+
var_dump(array_key_exists($key, $search));
28+
} catch (TypeError $exception) {
29+
echo $exception->getMessage() . "\n";
30+
}
2731
echo "Cast float to int:\n";
2832
var_dump(array_key_exists((int)$key, $search));
2933
}
@@ -35,25 +39,19 @@ echo "Done";
3539

3640
-- Iteration 1 --
3741
Pass float as $key:
38-
39-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
40-
bool(false)
42+
bool(true)
4143
Cast float to int:
4244
bool(true)
4345

4446
-- Iteration 1 --
4547
Pass float as $key:
46-
47-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
48-
bool(false)
48+
bool(true)
4949
Cast float to int:
5050
bool(true)
5151

5252
-- Iteration 1 --
5353
Pass float as $key:
54-
55-
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
56-
bool(false)
54+
bool(true)
5755
Cast float to int:
5856
bool(true)
5957
Done

0 commit comments

Comments
 (0)