问答 / 0 / 18 / 创建于 2年前 / 更新于 2年前
问 a 等于什么的时候 if 为true
<?php $a = ?; if($a ==1 && $a==2 && $a==3){ echo 1; }
所以答案是
$a = true;
这不可能呀
这题太难了 phpstorm告诉我答案应该是这个(⊙﹏⊙)
$s = new class { static $s = 1; public function __invoke() { return self::$s++; } }; if ($s() === 1 && $s() === 2 && $s() === 3) { dump("这不是js的题吗"); }
把 === 换成 == ,把数字换成字符串,还是有可能的。
===
==
$a = new class { public function __toString(): string { static $i = 0; ++$i; return (string)$i; } }; if ($a == '1' && $a == '2' && $a == '3') { echo 1; } // 或者转换一下类型 if ((int)(string)$a === 1 && (int)(string)$a === 2 && (int)(string)$a === 3) { echo 1; }
一个比一个骚,laravel的几个经典魔术方法被你们秀了个遍
把仨等号换成俩吧
这问题问的,看代码相当于1什么时候等于2并且等于3,想上去给他邦邦来两拳
最新的php源码,zend_operators.c,2090 行。看了一下,只能从 Z_OBJ_HANDLER_P想办法了。
ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */ { int converted = 0; zval op1_copy, op2_copy; while (1) { switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { case TYPE_PAIR(IS_LONG, IS_LONG): return Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0); case TYPE_PAIR(IS_DOUBLE, IS_LONG): return ZEND_NORMALIZE_BOOL(Z_DVAL_P(op1) - (double)Z_LVAL_P(op2)); case TYPE_PAIR(IS_LONG, IS_DOUBLE): return ZEND_NORMALIZE_BOOL((double)Z_LVAL_P(op1) - Z_DVAL_P(op2)); case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) { return 0; } else { return ZEND_NORMALIZE_BOOL(Z_DVAL_P(op1) - Z_DVAL_P(op2)); } case TYPE_PAIR(IS_ARRAY, IS_ARRAY): return zend_compare_arrays(op1, op2); case TYPE_PAIR(IS_NULL, IS_NULL): case TYPE_PAIR(IS_NULL, IS_FALSE): case TYPE_PAIR(IS_FALSE, IS_NULL): case TYPE_PAIR(IS_FALSE, IS_FALSE): case TYPE_PAIR(IS_TRUE, IS_TRUE): return 0; case TYPE_PAIR(IS_NULL, IS_TRUE): return -1; case TYPE_PAIR(IS_TRUE, IS_NULL): return 1; case TYPE_PAIR(IS_STRING, IS_STRING): if (Z_STR_P(op1) == Z_STR_P(op2)) { return 0; } return zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2)); case TYPE_PAIR(IS_NULL, IS_STRING): return Z_STRLEN_P(op2) == 0 ? 0 : -1; case TYPE_PAIR(IS_STRING, IS_NULL): return Z_STRLEN_P(op1) == 0 ? 0 : 1; case TYPE_PAIR(IS_LONG, IS_STRING): return compare_long_to_string(Z_LVAL_P(op1), Z_STR_P(op2)); case TYPE_PAIR(IS_STRING, IS_LONG): return -compare_long_to_string(Z_LVAL_P(op2), Z_STR_P(op1)); case TYPE_PAIR(IS_DOUBLE, IS_STRING): if (zend_isnan(Z_DVAL_P(op1))) { return 1; } return compare_double_to_string(Z_DVAL_P(op1), Z_STR_P(op2)); case TYPE_PAIR(IS_STRING, IS_DOUBLE): if (zend_isnan(Z_DVAL_P(op2))) { return 1; } return -compare_double_to_string(Z_DVAL_P(op2), Z_STR_P(op1)); case TYPE_PAIR(IS_OBJECT, IS_NULL): return 1; case TYPE_PAIR(IS_NULL, IS_OBJECT): return -1; default: if (Z_ISREF_P(op1)) { op1 = Z_REFVAL_P(op1); continue; } else if (Z_ISREF_P(op2)) { op2 = Z_REFVAL_P(op2); continue; } if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_P(op1) == Z_OBJ_P(op2)) { return 0; } else if (Z_TYPE_P(op1) == IS_OBJECT) { return Z_OBJ_HANDLER_P(op1, compare)(op1, op2); } else if (Z_TYPE_P(op2) == IS_OBJECT) { return Z_OBJ_HANDLER_P(op2, compare)(op1, op2); } if (!converted) { if (Z_TYPE_P(op1) < IS_TRUE) { return zval_is_true(op2) ? -1 : 0; } else if (Z_TYPE_P(op1) == IS_TRUE) { return zval_is_true(op2) ? 0 : 1; } else if (Z_TYPE_P(op2) < IS_TRUE) { return zval_is_true(op1) ? 1 : 0; } else if (Z_TYPE_P(op2) == IS_TRUE) { return zval_is_true(op1) ? 0 : -1; } else { op1 = _zendi_convert_scalar_to_number_silent(op1, &op1_copy); op2 = _zendi_convert_scalar_to_number_silent(op2, &op2_copy); if (EG(exception)) { return 1; /* to stop comparison of arrays */ } converted = 1; } } else if (Z_TYPE_P(op1)==IS_ARRAY) { return 1; } else if (Z_TYPE_P(op2)==IS_ARRAY) { return -1; } else { ZEND_UNREACHABLE(); zend_throw_error(NULL, "Unsupported operand types"); return 1; } } } }
zend_types.h 844行,相当于调用handlers->compare,如何设置这个呢?
#define Z_OBJ(zval) (zval).value.obj #define Z_OBJ_P(zval_p) Z_OBJ(*(zval_p)) #define Z_OBJ_HT(zval) Z_OBJ(zval)->handlers #define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*(zval_p)) #define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf #define Z_OBJ_HANDLER_P(zv_p, hf) Z_OBJ_HANDLER(*(zv_p), hf)
相同的文件 288 行,从这里可以找到(zval).value.obj
typedef union _zend_value { zend_long lval; /* long value */ double dval; /* double value */ zend_refcounted *counted; zend_string *str; zend_array *arr; zend_object *obj; zend_resource *res; zend_reference *ref; zend_ast_ref *ast; zval *zv; void *ptr; zend_class_entry *ce; zend_function *func; struct { uint32_t w1; uint32_t w2; } ww; } zend_value; struct _zval_struct { zend_value value; /* value */ union { uint32_t type_info; struct { ZEND_ENDIAN_LOHI_3( zend_uchar type, /* active type */ zend_uchar type_flags, union { uint16_t extra; /* not further specified */ } u) } v; } u1; union { uint32_t next; /* hash collision chain */ uint32_t cache_slot; /* cache slot (for RECV_INIT) */ uint32_t opline_num; /* opline number (for FAST_CALL) */ uint32_t lineno; /* line number (for ast nodes) */ uint32_t num_args; /* arguments number for EX(This) */ uint32_t fe_pos; /* foreach position */ uint32_t fe_iter_idx; /* foreach iterator index */ uint32_t property_guard; /* single property guard */ uint32_t constant_flags; /* constant flags */ uint32_t extra; /* not further specified */ } u2; };
480行,可以找到handlers
struct _zend_object { zend_refcounted_h gc; uint32_t handle; // TODO: may be removed ??? zend_class_entry *ce; const zend_object_handlers *handlers; HashTable *properties; zval properties_table[1]; };
文件 zend_object_handlers.h,159行终于找到了compare
struct _zend_object_handlers { /* offset of real object header (usually zero) */ int offset; /* object handlers */ zend_object_free_obj_t free_obj; /* required */ zend_object_dtor_obj_t dtor_obj; /* required */ zend_object_clone_obj_t clone_obj; /* optional */ zend_object_read_property_t read_property; /* required */ zend_object_write_property_t write_property; /* required */ zend_object_read_dimension_t read_dimension; /* required */ zend_object_write_dimension_t write_dimension; /* required */ zend_object_get_property_ptr_ptr_t get_property_ptr_ptr; /* required */ zend_object_has_property_t has_property; /* required */ zend_object_unset_property_t unset_property; /* required */ zend_object_has_dimension_t has_dimension; /* required */ zend_object_unset_dimension_t unset_dimension; /* required */ zend_object_get_properties_t get_properties; /* required */ zend_object_get_method_t get_method; /* required */ zend_object_get_constructor_t get_constructor; /* required */ zend_object_get_class_name_t get_class_name; /* required */ zend_object_cast_t cast_object; /* required */ zend_object_count_elements_t count_elements; /* optional */ zend_object_get_debug_info_t get_debug_info; /* optional */ zend_object_get_closure_t get_closure; /* optional */ zend_object_get_gc_t get_gc; /* required */ zend_object_do_operation_t do_operation; /* optional */ zend_object_compare_t compare; /* required */ zend_object_get_properties_for_t get_properties_for; /* optional */ };
zend_object_handlers.c ,1912行,可以看到标准的compare定义
ZEND_API const zend_object_handlers std_object_handlers = { 0, /* offset */ zend_object_std_dtor, /* free_obj */ zend_objects_destroy_object, /* dtor_obj */ zend_objects_clone_obj, /* clone_obj */ zend_std_read_property, /* read_property */ zend_std_write_property, /* write_property */ zend_std_read_dimension, /* read_dimension */ zend_std_write_dimension, /* write_dimension */ zend_std_get_property_ptr_ptr, /* get_property_ptr_ptr */ zend_std_has_property, /* has_property */ zend_std_unset_property, /* unset_property */ zend_std_has_dimension, /* has_dimension */ zend_std_unset_dimension, /* unset_dimension */ zend_std_get_properties, /* get_properties */ zend_std_get_method, /* get_method */ zend_std_get_constructor, /* get_constructor */ zend_std_get_class_name, /* get_class_name */ zend_std_cast_object_tostring, /* cast_object */ NULL, /* count_elements */ zend_std_get_debug_info, /* get_debug_info */ zend_std_get_closure, /* get_closure */ zend_std_get_gc, /* get_gc */ NULL, /* do_operation */ zend_std_compare_objects, /* compare */ NULL, /* get_properties_for */ };
相同文件 1580行,没有全部复制完,余下的代码是比较两个不同对象的,用不上。
ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */ { zend_object *zobj1, *zobj2; if (Z_TYPE_P(o1) != Z_TYPE_P(o2)) { /* Object and non-object */ zval casted; if (Z_TYPE_P(o1) == IS_OBJECT) { ZEND_ASSERT(Z_TYPE_P(o2) != IS_OBJECT); zend_uchar target_type = (Z_TYPE_P(o2) == IS_FALSE || Z_TYPE_P(o2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(o2); if (Z_OBJ_HT_P(o1)->cast_object(Z_OBJ_P(o1), &casted, target_type) == FAILURE) { // TODO: Less crazy. if (target_type == IS_LONG || target_type == IS_DOUBLE) { zend_error(E_NOTICE, "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(o1)->name), zend_get_type_by_const(target_type)); if (target_type == IS_LONG) { ZVAL_LONG(&casted, 1); } else { ZVAL_DOUBLE(&casted, 1.0); } } else { return 1; } } int ret = zend_compare(&casted, o2); zval_ptr_dtor(&casted); return ret; } else { ZEND_ASSERT(Z_TYPE_P(o2) == IS_OBJECT); zend_uchar target_type = (Z_TYPE_P(o1) == IS_FALSE || Z_TYPE_P(o1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(o1); if (Z_OBJ_HT_P(o2)->cast_object(Z_OBJ_P(o2), &casted, target_type) == FAILURE) { // TODO: Less crazy. if (target_type == IS_LONG || target_type == IS_DOUBLE) { zend_error(E_NOTICE, "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(o2)->name), zend_get_type_by_const(target_type)); if (target_type == IS_LONG) { ZVAL_LONG(&casted, 1); } else { ZVAL_DOUBLE(&casted, 1.0); } } else { return -1; } } int ret = zend_compare(o1, &casted); zval_ptr_dtor(&casted); return ret; } return ZEND_UNCOMPARABLE; }
关键的一点是 cast_object 到一个 int类型。但标准的cast只能到string,到int就返回FAILURE。
看了你们的一番操作,一个比一个秀 :+1:
写了好几年严格模式、强类型,表示这个不难
我要举报该,理由是:
高认可度评论:
所以答案是
这不可能呀
这不可能呀
把
===
换成==
,把数字换成字符串,还是有可能的。一个比一个骚,laravel的几个经典魔术方法被你们秀了个遍
把仨等号换成俩吧
这问题问的,看代码相当于1什么时候等于2并且等于3,想上去给他邦邦来两拳
最新的php源码,zend_operators.c,2090 行。看了一下,只能从 Z_OBJ_HANDLER_P想办法了。
所以答案是
看了你们的一番操作,一个比一个秀 :+1:
写了好几年严格模式、强类型,表示这个不难