1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Remove support for array_key_exists() with objects

This commit is contained in:
Nikita Popov
2019-11-04 13:02:28 +01:00
parent 31f1254182
commit c46b2ed677
12 changed files with 65 additions and 292 deletions

View File

@@ -41,6 +41,8 @@ PHP 8.0 UPGRADE NOTES
method, using Closure::fromCallable() or ReflectionMethod::getClosure().
. Also removed ability to unbind $this from proper closures that contain uses
of $this.
. Removed ability to use array_key_exists() with objects. Use one of isset()
or property_exists() instead.
. Any array that has a number n as its first numeric key will use n+1 for
its next implicit key. Even if n is negative.
RFC: https://wiki.php.net/rfc/negative_array_index

View File

@@ -2458,7 +2458,7 @@ str_offset:
}
}
static zend_never_inline uint32_t ZEND_FASTCALL zend_array_key_exists_fast(HashTable *ht, zval *key OPLINE_DC EXECUTE_DATA_DC)
static zend_never_inline zend_bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable *ht, zval *key OPLINE_DC EXECUTE_DATA_DC)
{
zend_string *str;
zend_ulong hval;
@@ -2470,11 +2470,11 @@ try_again:
goto num_key;
}
str_key:
return zend_hash_find_ind(ht, str) != NULL ? IS_TRUE : IS_FALSE;
return zend_hash_find_ind(ht, str) != NULL;
} else if (EXPECTED(Z_TYPE_P(key) == IS_LONG)) {
hval = Z_LVAL_P(key);
num_key:
return zend_hash_index_find(ht, hval) != NULL ? IS_TRUE : IS_FALSE;
return zend_hash_index_find(ht, hval) != NULL;
} else if (EXPECTED(Z_ISREF_P(key))) {
key = Z_REFVAL_P(key);
goto try_again;
@@ -2486,30 +2486,22 @@ num_key:
goto str_key;
} else {
zend_error(E_WARNING, "array_key_exists(): The first argument should be either a string or an integer");
return IS_FALSE;
return 0;
}
}
static zend_never_inline uint32_t ZEND_FASTCALL zend_array_key_exists_slow(zval *subject, zval *key OPLINE_DC EXECUTE_DATA_DC)
static ZEND_COLD void ZEND_FASTCALL zend_array_key_exists_error(
zval *subject, zval *key OPLINE_DC EXECUTE_DATA_DC)
{
if (EXPECTED(Z_TYPE_P(subject) == IS_OBJECT)) {
zend_error(E_DEPRECATED, "array_key_exists(): "
"Using array_key_exists() on objects is deprecated. "
"Use isset() or property_exists() instead");
HashTable *ht = zend_get_properties_for(subject, ZEND_PROP_PURPOSE_ARRAY_CAST);
uint32_t result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC);
zend_release_properties(ht);
return result;
} else {
if (UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) {
ZVAL_UNDEFINED_OP1();
}
if (UNEXPECTED(Z_TYPE_INFO_P(subject) == IS_UNDEF)) {
ZVAL_UNDEFINED_OP2();
}
zend_type_error("array_key_exists() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(subject)));
return IS_NULL;
if (Z_TYPE_P(key) == IS_UNDEF) {
ZVAL_UNDEFINED_OP1();
}
if (Z_TYPE_P(subject) == IS_UNDEF) {
ZVAL_UNDEFINED_OP2();
}
if (!EG(exception)) {
zend_type_error("array_key_exists() expects parameter 2 to be array, %s given",
zend_get_type_by_const(Z_TYPE_P(subject)));
}
}

View File

@@ -1841,7 +1841,6 @@ ZEND_API HashTable *zend_std_get_properties_for(zend_object *obj, zend_prop_purp
case ZEND_PROP_PURPOSE_SERIALIZE:
case ZEND_PROP_PURPOSE_VAR_EXPORT:
case ZEND_PROP_PURPOSE_JSON:
case _ZEND_PROP_PURPOSE_ARRAY_KEY_EXISTS:
ht = obj->handlers->get_properties(obj);
if (ht && !(GC_FLAGS(ht) & GC_IMMUTABLE)) {
GC_ADDREF(ht);

View File

@@ -98,8 +98,6 @@ typedef enum _zend_prop_purpose {
ZEND_PROP_PURPOSE_VAR_EXPORT,
/* Used for json_encode(). */
ZEND_PROP_PURPOSE_JSON,
/* array_key_exists(). Not intended for general use! */
_ZEND_PROP_PURPOSE_ARRAY_KEY_EXISTS,
/* Dummy member to ensure that "default" is specified. */
_ZEND_PROP_PURPOSE_NON_EXHAUSTIVE_ENUM
} zend_prop_purpose;

View File

@@ -6771,7 +6771,7 @@ ZEND_VM_HANDLER(194, ZEND_ARRAY_KEY_EXISTS, CV|TMPVAR|CONST, CV|TMPVAR|CONST)
zval *key, *subject;
HashTable *ht;
uint32_t result;
zend_bool result;
SAVE_OPLINE();
@@ -6789,12 +6789,13 @@ ZEND_VM_C_LABEL(array_key_exists_array):
ZEND_VM_C_GOTO(array_key_exists_array);
}
}
result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
result = 0;
}
FREE_OP2();
FREE_OP1();
ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */

View File

@@ -6180,7 +6180,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CO
zval *key, *subject;
HashTable *ht;
uint32_t result;
zend_bool result;
SAVE_OPLINE();
@@ -6198,11 +6198,12 @@ array_key_exists_array:
goto array_key_exists_array;
}
}
result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
result = 0;
}
ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
@@ -8281,7 +8282,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TM
zval *key, *subject;
HashTable *ht;
uint32_t result;
zend_bool result;
SAVE_OPLINE();
@@ -8299,12 +8300,13 @@ array_key_exists_array:
goto array_key_exists_array;
}
}
result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
result = 0;
}
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
@@ -10525,7 +10527,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CV
zval *key, *subject;
HashTable *ht;
uint32_t result;
zend_bool result;
SAVE_OPLINE();
@@ -10543,11 +10545,12 @@ array_key_exists_array:
goto array_key_exists_array;
}
}
result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
result = 0;
}
ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
@@ -14483,7 +14486,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_C
zval *key, *subject;
HashTable *ht;
uint32_t result;
zend_bool result;
SAVE_OPLINE();
@@ -14501,11 +14504,12 @@ array_key_exists_array:
goto array_key_exists_array;
}
}
result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
result = 0;
}
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
@@ -15863,7 +15867,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_T
zval *key, *subject;
HashTable *ht;
uint32_t result;
zend_bool result;
SAVE_OPLINE();
@@ -15881,12 +15885,13 @@ array_key_exists_array:
goto array_key_exists_array;
}
}
result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
result = 0;
}
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
@@ -17137,7 +17142,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_C
zval *key, *subject;
HashTable *ht;
uint32_t result;
zend_bool result;
SAVE_OPLINE();
@@ -17155,11 +17160,12 @@ array_key_exists_array:
goto array_key_exists_array;
}
}
result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
result = 0;
}
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
@@ -39657,7 +39663,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CONST
zval *key, *subject;
HashTable *ht;
uint32_t result;
zend_bool result;
SAVE_OPLINE();
@@ -39675,11 +39681,12 @@ array_key_exists_array:
goto array_key_exists_array;
}
}
result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
result = 0;
}
ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
@@ -43043,7 +43050,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVA
zval *key, *subject;
HashTable *ht;
uint32_t result;
zend_bool result;
SAVE_OPLINE();
@@ -43061,12 +43068,13 @@ array_key_exists_array:
goto array_key_exists_array;
}
}
result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
result = 0;
}
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
@@ -47888,7 +47896,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_HA
zval *key, *subject;
HashTable *ht;
uint32_t result;
zend_bool result;
SAVE_OPLINE();
@@ -47906,11 +47914,12 @@ array_key_exists_array:
goto array_key_exists_array;
}
}
result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
result = 0;
}
ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */

View File

@@ -804,7 +804,6 @@ static HashTable *spl_array_get_properties_for(zend_object *object, zend_prop_pu
break;
case ZEND_PROP_PURPOSE_VAR_EXPORT:
case ZEND_PROP_PURPOSE_JSON:
case _ZEND_PROP_PURPOSE_ARRAY_KEY_EXISTS:
dup = 0;
break;
default:

View File

@@ -12,7 +12,6 @@ var_dump(isset($b['no_exists'])); //false
var_dump(empty($b['b'])); //true
var_dump(empty($b[37])); //true
var_dump(array_key_exists('b', $b)); //true
var_dump($b['b']);
$a = array('b' => '', 37 => false);
@@ -29,9 +28,6 @@ bool(false)
bool(false)
bool(true)
bool(true)
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(true)
NULL
bool(true)
bool(true)

View File

@@ -6332,23 +6332,13 @@ PHP_FUNCTION(array_map)
PHP_FUNCTION(array_key_exists)
{
zval *key;
zval *array;
HashTable *ht;
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_ZVAL(key)
Z_PARAM_ARRAY_OR_OBJECT(array)
Z_PARAM_ARRAY_HT(ht)
ZEND_PARSE_PARAMETERS_END();
if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) {
ht = Z_ARRVAL_P(array);
} else {
ht = zend_get_properties_for(array, ZEND_PROP_PURPOSE_ARRAY_CAST);
php_error_docref(NULL, E_DEPRECATED,
"Using array_key_exists() on objects is deprecated. "
"Use isset() or property_exists() instead");
}
switch (Z_TYPE_P(key)) {
case IS_STRING:
RETVAL_BOOL(zend_symtable_exists_ind(ht, Z_STR_P(key)));
@@ -6363,10 +6353,6 @@ PHP_FUNCTION(array_key_exists)
php_error_docref(NULL, E_WARNING, "The first argument should be either a string or an integer");
RETVAL_FALSE;
}
if (Z_TYPE_P(array) != IS_ARRAY) {
zend_release_properties(ht);
}
}
/* }}} */

View File

@@ -77,29 +77,16 @@ var_dump( array_key_exists(17.5, array(1,23) ) ) ;
echo "\n*** Testing operation on objects ***\n";
class key_check
{
private $private_var = "Priviate var";
protected $protected_var = "Protected var";
public $public_var = "Public var";
public $arr = array("var" => "value", "1" => "one", ""=>"value");
public function print_member()
{
echo $this->$private_var."\n";
echo $this->$protected_var."\n";
echo $this->$public_var."\n";
}
public $public_var = "Public var";
}
$key_check_obj = new key_check; //new object
/* array_key_exists() on an object, it should work on only public member variables */
var_dump(array_key_exists("private_var", $key_check_obj)); // not found, private member
var_dump(array_key_exists("protected_var", $key_check_obj)); // not found, private member
var_dump(array_key_exists("public_var", $key_check_obj)); // found, public member
var_dump(array_key_exists("print_member", $key_check_obj)); // not found, its a function
var_dump(array_key_exists("arr", $key_check_obj)); //found, public member
var_dump(array_key_exists("var", $key_check_obj->arr)); //found, key is in member array
try {
var_dump(array_key_exists("public_var", $key_check_obj));
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
/* error condition, first argument as object */
var_dump( array_key_exists($key_check_obj, $key_check_obj) );
echo "Done\n";
?>
--EXPECTF--
@@ -240,25 +227,5 @@ Warning: array_key_exists(): The first argument should be either a string or an
bool(false)
*** Testing operation on objects ***
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(false)
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(false)
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(true)
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(false)
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(true)
bool(true)
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
bool(false)
array_key_exists() expects parameter 2 to be array, object given
Done

View File

@@ -1,85 +0,0 @@
--TEST--
Test array_key_exists() function : object functionality
--FILE--
<?php
/* Prototype : bool array_key_exists(mixed $key, array $search)
* Description: Checks if the given key or index exists in the array
* Source code: ext/standard/array.c
* Alias to functions: key_exists
*/
/*
* Test basic functionality of array_key_exists() with objects
*/
echo "*** Testing array_key_exists() : object functionality ***\n";
class myClass {
var $var1;
var $var2;
var $var3;
function __construct($a, $b, $c = null) {
$this->var1 = $a;
$this->var2 = $b;
if (!is_null($c)) {
$this->var3 = $c;
}
}
}
echo "\n-- Do not assign a value to \$class1->var3 --\n";
$class1 = new myClass ('a', 'b');
echo "\$key = var1:\n";
var_dump(array_key_exists('var1', $class1));
echo "\$key = var3:\n";
var_dump(array_key_exists('var3', $class1));
echo "\$class1:\n";
var_dump($class1);
echo "\n-- Assign a value to \$class2->var3 --\n";
$class2 = new myClass('x', 'y', 'z');
echo "\$key = var3:\n";
var_dump(array_key_exists('var3', $class2));
echo "\$class2:\n";
var_dump($class2);
echo "Done";
?>
--EXPECTF--
*** Testing array_key_exists() : object functionality ***
-- Do not assign a value to $class1->var3 --
$key = var1:
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(true)
$key = var3:
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(true)
$class1:
object(myClass)#1 (3) {
["var1"]=>
string(1) "a"
["var2"]=>
string(1) "b"
["var3"]=>
NULL
}
-- Assign a value to $class2->var3 --
$key = var3:
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(true)
$class2:
object(myClass)#2 (3) {
["var1"]=>
string(1) "x"
["var2"]=>
string(1) "y"
["var3"]=>
string(1) "z"
}
Done

View File

@@ -1,91 +0,0 @@
--TEST--
Test array_key_exists() function : object functionality - different visibilities
--FILE--
<?php
/* Prototype : bool array_key_exists(mixed $key, array $search)
* Description: Checks if the given key or index exists in the array
* Source code: ext/standard/array.c
* Alias to functions: key_exists
*/
/*
* Pass array_key_exists() an object with private and protected properties
*/
echo "*** Testing array_key_exists() : object functionality ***\n";
class myClass {
public $var1;
protected $var2;
private $var3;
function __construct($a, $b, $c = null) {
$this->var1 = $a;
$this->var2 = $b;
if (!is_null($c)) {
$this->var3 = $c;
}
}
}
echo "\n-- Do not assign a value to \$class1->var3 --\n";
$class1 = new myClass ('a', 'b');
echo "\$key = var1:\n";
var_dump(array_key_exists('var1', $class1));
echo "\$key = var2:\n";
var_dump(array_key_exists('var2', $class1));
echo "\$key = var3:\n";
var_dump(array_key_exists('var3', $class1));
echo "\$class1:\n";
var_dump($class1);
echo "\n-- Assign a value to \$class2->var3 --\n";
$class2 = new myClass('x', 'y', 'z');
echo "\$key = var3:\n";
var_dump(array_key_exists('var3', $class2));
echo "\$class2:\n";
var_dump($class2);
echo "Done";
?>
--EXPECTF--
*** Testing array_key_exists() : object functionality ***
-- Do not assign a value to $class1->var3 --
$key = var1:
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(true)
$key = var2:
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(false)
$key = var3:
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(false)
$class1:
object(myClass)#1 (3) {
["var1"]=>
string(1) "a"
["var2":protected]=>
string(1) "b"
["var3":"myClass":private]=>
NULL
}
-- Assign a value to $class2->var3 --
$key = var3:
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
bool(false)
$class2:
object(myClass)#2 (3) {
["var1"]=>
string(1) "x"
["var2":protected]=>
string(1) "y"
["var3":"myClass":private]=>
string(1) "z"
}
Done