Skip to content

Commit a8bcc2c

Browse files
committed
Added __bitwiseNot handler
1 parent a468b92 commit a8bcc2c

File tree

5 files changed

+41
-13
lines changed

5 files changed

+41
-13
lines changed

Zend/zend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ struct _zend_class_entry {
154154
zend_function *__bitwiseOr;
155155
zend_function *__bitwiseAnd;
156156
zend_function *__bitwiseXor;
157+
zend_function *__bitwiseNot;
157158

158159
zend_function *serialize_func;
159160
zend_function *unserialize_func;

Zend/zend_API.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,6 +2015,10 @@ ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce,
20152015
if (fptr->common.num_args != 2) {
20162016
zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ZSTR_VAL(ce->name), "__bitwiseXor");
20172017
}
2018+
} else if (name_len == sizeof(ZEND_NOT_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_NOT_FUNC_NAME, sizeof(ZEND_NOT_FUNC_NAME) - 1)) {
2019+
if (fptr->common.num_args != 1) {
2020+
zend_error(error_type, "Method %s::%s() must take exactly 1 arguments", ZSTR_VAL(ce->name), "__bitwiseNot");
2021+
}
20182022
}
20192023
}
20202024
/* }}} */

Zend/zend_compile.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6128,6 +6128,9 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo
61286128
} else if (zend_string_equals_literal(lcname, ZEND_XOR_FUNC_NAME)) {
61296129
zend_check_magic_method_attr(fn_flags, "__bitwiseXor", 1);
61306130
ce->__bitwiseXor = (zend_function *) op_array;
6131+
} else if (zend_string_equals_literal(lcname, ZEND_NOT_FUNC_NAME)) {
6132+
zend_check_magic_method_attr(fn_flags, "__bitwiseNot", 1);
6133+
ce->__bitwiseNot = (zend_function *) op_array;
61316134
}
61326135

61336136
zend_string_release_ex(lcname, 0);

Zend/zend_compile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,7 @@ END_EXTERN_C()
10541054
#define ZEND_OR_FUNC_NAME "__bitwiseor"
10551055
#define ZEND_AND_FUNC_NAME "__bitwiseand"
10561056
#define ZEND_XOR_FUNC_NAME "__bitwisexor"
1057+
#define ZEND_NOT_FUNC_NAME "__bitwisenot"
10571058

10581059

10591060
/* The following constants may be combined in CG(compiler_options)

Zend/zend_object_handlers.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,22 @@ static int zend_std_call_op_handler(zend_uchar opcode, zval *result, zval *op1,
194194
zend_class_entry *orig_fake_scope = EG(fake_scope);
195195
zend_fcall_info fci;
196196
zend_fcall_info_cache fcic;
197-
zval params[2] = {*op1, *op2};
198197

199198
EG(fake_scope) = NULL;
200199

201-
/* op handlers like __add are called with two operands op1, op2 */
200+
/* __bitwiseNot is a unary operator and only have one argument */
201+
if (opcode == ZEND_BW_NOT) {
202+
fci.param_count = 1;
203+
zval params[1] = {*op1};
204+
fci.params = params;
205+
} else { /* op handlers like __add are called with two operands op1, op2 */
206+
fci.param_count = 2;
207+
zval params[2] = {*op1, *op2};
208+
fci.params = params;
209+
}
210+
202211
fci.size = sizeof(fci);
203212
fci.retval = result;
204-
fci.param_count = 2;
205-
fci.params = params;
206213
fci.no_separation = 1;
207214
//ZVAL_UNDEF(&fci.function_name); /* Unused */
208215

@@ -261,6 +268,10 @@ static int zend_std_call_op_handler(zend_uchar opcode, zval *result, zval *op1,
261268
fcic.function_handler = ce->__bitwiseXor;
262269
ZVAL_STRING(&fci.function_name, "__bitwiseXor");
263270
break;
271+
case ZEND_BW_NOT:
272+
fcic.function_handler = ce->__bitwiseNot;
273+
ZVAL_STRING(&fci.function_name, "__bitwiseNot");
274+
break;
264275
default:
265276
return FAILURE;
266277
break;
@@ -286,17 +297,25 @@ static int zend_std_call_op_handler(zend_uchar opcode, zval *result, zval *op1,
286297

287298

288299
/* Check if the given types are supported by the given handler signature */
289-
290-
zval* arr[2] = {op1, op2};
291-
if (!zend_check_arg_types(fcic.function_handler, 2, arr))
292-
{
293-
if (zobj == Z_OBJ_P(op1) && Z_TYPE_P(op2) == IS_OBJECT) {
294-
goto retry;
295-
} else {
296-
zend_type_error("The operand handlers do not support the given operand types!");
300+
if(opcode != ZEND_BW_NOT) {
301+
zval* arr[2] = {op1, op2};
302+
if (!zend_check_arg_types(fcic.function_handler, 2, arr))
303+
{
304+
if (zobj == Z_OBJ_P(op1) && Z_TYPE_P(op2) == IS_OBJECT) {
305+
goto retry;
306+
} else {
307+
zend_type_error("The operand handlers do not support the given operand types!");
308+
}
309+
}
310+
} else {
311+
zval* arr[1] = {op1};
312+
if (!zend_check_arg_types(fcic.function_handler, 1, arr))
313+
{
314+
zend_type_error("The operand handlers do not support the given operand types!");
297315
}
298316
}
299317

318+
300319
fcic.called_scope = ce;
301320
fcic.object = zobj;
302321
fcic.function_handler->type = ZEND_USER_FUNCTION;
@@ -305,7 +324,7 @@ static int zend_std_call_op_handler(zend_uchar opcode, zval *result, zval *op1,
305324

306325
/** The operand handler can either return PHP_OPERAND_NOT_SUPPORTED */
307326
if (Z_TYPE_P(result) == IS_NULL) {
308-
if(zobj == Z_OBJ_P(op1) && Z_TYPE_P(op2) == IS_OBJECT) {
327+
if(zobj == Z_OBJ_P(op1) && op2 != NULL && Z_TYPE_P(op2) == IS_OBJECT) {
309328
goto retry;
310329
} else {
311330
zend_type_error("The operand handlers do not support the given operand types!");

0 commit comments

Comments
 (0)