/* +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: George Peter Banyard | +----------------------------------------------------------------------+ */ #include "object_handlers.h" #include "zend_API.h" #include "object_handlers_arginfo.h" /* donc refers to DoOperationNoCast */ static zend_class_entry *donc_ce; static zend_object_handlers donc_object_handlers; static zend_object* donc_object_create_ex(zend_class_entry* ce, zend_long l) { zend_object *obj = zend_objects_new(ce); object_properties_init(obj, ce); obj->handlers = &donc_object_handlers; ZVAL_LONG(OBJ_PROP_NUM(obj, 0), l); return obj; } static zend_object *donc_object_create(zend_class_entry *ce) /* {{{ */ { return donc_object_create_ex(ce, 0); } /* }}} */ static inline void donc_create(zval *target, zend_long l) /* {{{ */ { ZVAL_OBJ(target, donc_object_create_ex(donc_ce, l)); } #define IS_DONC(zval) \ (Z_TYPE_P(zval) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zval), donc_ce)) static void donc_add(zval *result, zval *op1, zval *op2) { zend_long val_1; zend_long val_2; if (IS_DONC(op1)) { val_1 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op1), 0)); } else { val_1 = zval_get_long(op1); } if (IS_DONC(op2)) { val_2 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op2), 0)); } else { val_2 = zval_get_long(op2); } donc_create(result, val_1 + val_2); } static void donc_mul(zval *result, zval *op1, zval *op2) { zend_long val_1; zend_long val_2; if (IS_DONC(op1)) { val_1 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op1), 0)); } else { val_1 = zval_get_long(op1); } if (IS_DONC(op2)) { val_2 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op2), 0)); } else { val_2 = zval_get_long(op2); } donc_create(result, val_1 * val_2); } static zend_result donc_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2) { zval op1_copy; zend_result status; if (result == op1) { ZVAL_COPY_VALUE(&op1_copy, op1); op1 = &op1_copy; } switch (opcode) { case ZEND_ADD: donc_add(result, op1, op2); if (UNEXPECTED(EG(exception))) { status = FAILURE; } status = SUCCESS; break; case ZEND_MUL: donc_mul(result, op1, op2); if (UNEXPECTED(EG(exception))) { status = FAILURE; } status = SUCCESS; break; default: status = FAILURE; break; } if (status == SUCCESS && op1 == &op1_copy) { zval_ptr_dtor(op1); } return status; } ZEND_METHOD(DoOperationNoCast, __construct) { zend_long l; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_LONG(l) ZEND_PARSE_PARAMETERS_END(); ZVAL_LONG(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), l); } static zend_class_entry *long_castable_no_operation_ce; static zend_object_handlers long_castable_no_operation_object_handlers; static zend_object* long_castable_no_operation_object_create_ex(zend_class_entry* ce, zend_long l) { zend_object *obj = zend_objects_new(ce); object_properties_init(obj, ce); obj->handlers = &long_castable_no_operation_object_handlers; ZVAL_LONG(OBJ_PROP_NUM(obj, 0), l); return obj; } static zend_object *long_castable_no_operation_object_create(zend_class_entry *ce) { return long_castable_no_operation_object_create_ex(ce, 0); } static zend_result long_castable_no_operation_cast_object(zend_object *obj, zval *result, int type) { if (type == IS_LONG) { ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0)); return SUCCESS; } return FAILURE; } ZEND_METHOD(LongCastableNoOperations, __construct) { zend_long l; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_LONG(l) ZEND_PARSE_PARAMETERS_END(); ZVAL_LONG(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), l); } static zend_class_entry *float_castable_no_operation_ce; static zend_object_handlers float_castable_no_operation_object_handlers; static zend_object* float_castable_no_operation_object_create_ex(zend_class_entry* ce, double d) { zend_object *obj = zend_objects_new(ce); object_properties_init(obj, ce); obj->handlers = &float_castable_no_operation_object_handlers; ZVAL_DOUBLE(OBJ_PROP_NUM(obj, 0), d); return obj; } static zend_object *float_castable_no_operation_object_create(zend_class_entry *ce) { return float_castable_no_operation_object_create_ex(ce, 0.0); } static zend_result float_castable_no_operation_cast_object(zend_object *obj, zval *result, int type) { if (type == IS_DOUBLE) { ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0)); return SUCCESS; } return FAILURE; } ZEND_METHOD(FloatCastableNoOperations, __construct) { double d; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_DOUBLE(d) ZEND_PARSE_PARAMETERS_END(); ZVAL_DOUBLE(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), d); } static zend_class_entry *numeric_castable_no_operation_ce; static zend_object_handlers numeric_castable_no_operation_object_handlers; static zend_object* numeric_castable_no_operation_object_create_ex(zend_class_entry* ce, const zval *n) { zend_object *obj = zend_objects_new(ce); object_properties_init(obj, ce); obj->handlers = &numeric_castable_no_operation_object_handlers; ZVAL_COPY(OBJ_PROP_NUM(obj, 0), n); return obj; } static zend_object *numeric_castable_no_operation_object_create(zend_class_entry *ce) { zval tmp; ZVAL_LONG(&tmp, 0); return numeric_castable_no_operation_object_create_ex(ce, &tmp); } static zend_result numeric_castable_no_operation_cast_object(zend_object *obj, zval *result, int type) { if (type == _IS_NUMBER) { ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0)); return SUCCESS; } return FAILURE; } ZEND_METHOD(NumericCastableNoOperations, __construct) { zval *n; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_NUMBER(n) ZEND_PARSE_PARAMETERS_END(); ZVAL_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), n); } void zend_test_object_handlers_init(void) { /* DoOperationNoCast class */ donc_ce = register_class_DoOperationNoCast(); donc_ce->create_object = donc_object_create; memcpy(&donc_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); donc_object_handlers.do_operation = donc_do_operation; /* CastableNoOperation classes */ long_castable_no_operation_ce = register_class_LongCastableNoOperations(); long_castable_no_operation_ce->create_object = long_castable_no_operation_object_create; memcpy(&long_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); long_castable_no_operation_object_handlers.cast_object = long_castable_no_operation_cast_object; float_castable_no_operation_ce = register_class_FloatCastableNoOperations(); float_castable_no_operation_ce->create_object = float_castable_no_operation_object_create; memcpy(&float_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); float_castable_no_operation_object_handlers.cast_object = float_castable_no_operation_cast_object; numeric_castable_no_operation_ce = register_class_NumericCastableNoOperations(); numeric_castable_no_operation_ce->create_object = numeric_castable_no_operation_object_create; memcpy(&numeric_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); numeric_castable_no_operation_object_handlers.cast_object = numeric_castable_no_operation_cast_object; }