1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: George Peter Banyard <girgias@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17 #include "object_handlers.h"
18 #include "zend_API.h"
19 #include "object_handlers_arginfo.h"
20
21 /* donc refers to DoOperationNoCast */
22 static zend_class_entry *donc_ce;
23 static zend_object_handlers donc_object_handlers;
24
donc_object_create_ex(zend_class_entry * ce,zend_long l)25 static zend_object* donc_object_create_ex(zend_class_entry* ce, zend_long l) {
26 zend_object *obj = zend_objects_new(ce);
27 object_properties_init(obj, ce);
28 obj->handlers = &donc_object_handlers;
29 ZVAL_LONG(OBJ_PROP_NUM(obj, 0), l);
30 return obj;
31 }
donc_object_create(zend_class_entry * ce)32 static zend_object *donc_object_create(zend_class_entry *ce) /* {{{ */
33 {
34 return donc_object_create_ex(ce, 0);
35 }
36 /* }}} */
37
donc_create(zval * target,zend_long l)38 static inline void donc_create(zval *target, zend_long l) /* {{{ */
39 {
40 ZVAL_OBJ(target, donc_object_create_ex(donc_ce, l));
41 }
42
43 #define IS_DONC(zval) \
44 (Z_TYPE_P(zval) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zval), donc_ce))
45
donc_add(zval * result,zval * op1,zval * op2)46 static void donc_add(zval *result, zval *op1, zval *op2)
47 {
48 zend_long val_1;
49 zend_long val_2;
50 if (IS_DONC(op1)) {
51 val_1 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op1), 0));
52 } else {
53 val_1 = zval_get_long(op1);
54 }
55 if (IS_DONC(op2)) {
56 val_2 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op2), 0));
57 } else {
58 val_2 = zval_get_long(op2);
59 }
60
61 donc_create(result, val_1 + val_2);
62 }
donc_mul(zval * result,zval * op1,zval * op2)63 static void donc_mul(zval *result, zval *op1, zval *op2)
64 {
65 zend_long val_1;
66 zend_long val_2;
67 if (IS_DONC(op1)) {
68 val_1 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op1), 0));
69 } else {
70 val_1 = zval_get_long(op1);
71 }
72 if (IS_DONC(op2)) {
73 val_2 = Z_LVAL_P(OBJ_PROP_NUM(Z_OBJ_P(op2), 0));
74 } else {
75 val_2 = zval_get_long(op2);
76 }
77
78 donc_create(result, val_1 * val_2);
79 }
80
donc_do_operation(zend_uchar opcode,zval * result,zval * op1,zval * op2)81 static zend_result donc_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2)
82 {
83 zval op1_copy;
84 zend_result status;
85
86 if (result == op1) {
87 ZVAL_COPY_VALUE(&op1_copy, op1);
88 op1 = &op1_copy;
89 }
90
91 switch (opcode) {
92 case ZEND_ADD:
93 donc_add(result, op1, op2);
94 if (UNEXPECTED(EG(exception))) { status = FAILURE; }
95 status = SUCCESS;
96 break;
97 case ZEND_MUL:
98 donc_mul(result, op1, op2);
99 if (UNEXPECTED(EG(exception))) { status = FAILURE; }
100 status = SUCCESS;
101 break;
102 default:
103 status = FAILURE;
104 break;
105 }
106
107 if (status == SUCCESS && op1 == &op1_copy) {
108 zval_ptr_dtor(op1);
109 }
110
111 return status;
112 }
113
ZEND_METHOD(DoOperationNoCast,__construct)114 ZEND_METHOD(DoOperationNoCast, __construct)
115 {
116 zend_long l;
117
118 ZEND_PARSE_PARAMETERS_START(1, 1)
119 Z_PARAM_LONG(l)
120 ZEND_PARSE_PARAMETERS_END();
121
122 ZVAL_LONG(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), l);
123 }
124
125 static zend_class_entry *long_castable_no_operation_ce;
126 static zend_object_handlers long_castable_no_operation_object_handlers;
127
long_castable_no_operation_object_create_ex(zend_class_entry * ce,zend_long l)128 static zend_object* long_castable_no_operation_object_create_ex(zend_class_entry* ce, zend_long l) {
129 zend_object *obj = zend_objects_new(ce);
130 object_properties_init(obj, ce);
131 obj->handlers = &long_castable_no_operation_object_handlers;
132 ZVAL_LONG(OBJ_PROP_NUM(obj, 0), l);
133 return obj;
134 }
135
long_castable_no_operation_object_create(zend_class_entry * ce)136 static zend_object *long_castable_no_operation_object_create(zend_class_entry *ce)
137 {
138 return long_castable_no_operation_object_create_ex(ce, 0);
139 }
140
long_castable_no_operation_cast_object(zend_object * obj,zval * result,int type)141 static zend_result long_castable_no_operation_cast_object(zend_object *obj, zval *result, int type)
142 {
143 if (type == IS_LONG) {
144 ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0));
145 return SUCCESS;
146 }
147 return FAILURE;
148 }
149
ZEND_METHOD(LongCastableNoOperations,__construct)150 ZEND_METHOD(LongCastableNoOperations, __construct)
151 {
152 zend_long l;
153
154 ZEND_PARSE_PARAMETERS_START(1, 1)
155 Z_PARAM_LONG(l)
156 ZEND_PARSE_PARAMETERS_END();
157
158 ZVAL_LONG(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), l);
159 }
160
161 static zend_class_entry *float_castable_no_operation_ce;
162 static zend_object_handlers float_castable_no_operation_object_handlers;
163
float_castable_no_operation_object_create_ex(zend_class_entry * ce,double d)164 static zend_object* float_castable_no_operation_object_create_ex(zend_class_entry* ce, double d) {
165 zend_object *obj = zend_objects_new(ce);
166 object_properties_init(obj, ce);
167 obj->handlers = &float_castable_no_operation_object_handlers;
168 ZVAL_DOUBLE(OBJ_PROP_NUM(obj, 0), d);
169 return obj;
170 }
171
float_castable_no_operation_object_create(zend_class_entry * ce)172 static zend_object *float_castable_no_operation_object_create(zend_class_entry *ce)
173 {
174 return float_castable_no_operation_object_create_ex(ce, 0.0);
175 }
176
float_castable_no_operation_cast_object(zend_object * obj,zval * result,int type)177 static zend_result float_castable_no_operation_cast_object(zend_object *obj, zval *result, int type)
178 {
179 if (type == IS_DOUBLE) {
180 ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0));
181 return SUCCESS;
182 }
183 return FAILURE;
184 }
185
ZEND_METHOD(FloatCastableNoOperations,__construct)186 ZEND_METHOD(FloatCastableNoOperations, __construct)
187 {
188 double d;
189
190 ZEND_PARSE_PARAMETERS_START(1, 1)
191 Z_PARAM_DOUBLE(d)
192 ZEND_PARSE_PARAMETERS_END();
193
194 ZVAL_DOUBLE(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), d);
195 }
196
197 static zend_class_entry *numeric_castable_no_operation_ce;
198 static zend_object_handlers numeric_castable_no_operation_object_handlers;
199
numeric_castable_no_operation_object_create_ex(zend_class_entry * ce,const zval * n)200 static zend_object* numeric_castable_no_operation_object_create_ex(zend_class_entry* ce, const zval *n) {
201 zend_object *obj = zend_objects_new(ce);
202 object_properties_init(obj, ce);
203 obj->handlers = &numeric_castable_no_operation_object_handlers;
204 ZVAL_COPY(OBJ_PROP_NUM(obj, 0), n);
205 return obj;
206 }
207
numeric_castable_no_operation_object_create(zend_class_entry * ce)208 static zend_object *numeric_castable_no_operation_object_create(zend_class_entry *ce)
209 {
210 zval tmp;
211 ZVAL_LONG(&tmp, 0);
212 return numeric_castable_no_operation_object_create_ex(ce, &tmp);
213 }
214
numeric_castable_no_operation_cast_object(zend_object * obj,zval * result,int type)215 static zend_result numeric_castable_no_operation_cast_object(zend_object *obj, zval *result, int type)
216 {
217 if (type == _IS_NUMBER) {
218 ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0));
219 return SUCCESS;
220 }
221 return FAILURE;
222 }
223
ZEND_METHOD(NumericCastableNoOperations,__construct)224 ZEND_METHOD(NumericCastableNoOperations, __construct)
225 {
226 zval *n;
227
228 ZEND_PARSE_PARAMETERS_START(1, 1)
229 Z_PARAM_NUMBER(n)
230 ZEND_PARSE_PARAMETERS_END();
231
232 ZVAL_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), n);
233 }
234
235 static zend_class_entry *dimension_handlers_no_ArrayAccess_ce;
236 static zend_object_handlers dimension_handlers_no_ArrayAccess_object_handlers;
237
dimension_handlers_no_ArrayAccess_object_create(zend_class_entry * ce)238 static zend_object* dimension_handlers_no_ArrayAccess_object_create(zend_class_entry* ce) {
239 zend_object *object = zend_objects_new(ce);
240 object_properties_init(object, ce);
241 object->handlers = &dimension_handlers_no_ArrayAccess_object_handlers;
242 return object;
243 }
244
dimension_common_helper(zend_object * object,zval * offset,int prop_access_type)245 static void dimension_common_helper(zend_object *object, zval *offset, int prop_access_type) {
246 ZVAL_BOOL(OBJ_PROP_NUM(object, prop_access_type), true);
247 /* hasOffset */
248 ZVAL_BOOL(OBJ_PROP_NUM(object, 5), offset != NULL);
249 if (offset) {
250 ZVAL_COPY(OBJ_PROP_NUM(object, 7), offset);
251 }
252 }
253
dimension_handlers_no_ArrayAccess_read_dimension(zend_object * object,zval * offset,int type,zval * rv)254 static zval* dimension_handlers_no_ArrayAccess_read_dimension(zend_object *object, zval *offset, int type, zval *rv) {
255 dimension_common_helper(object, offset, 0);
256 /* ReadType */
257 ZVAL_LONG(OBJ_PROP_NUM(object, 4), type);
258
259 /* Normal logic */
260 ZVAL_BOOL(rv, true);
261 return rv;
262 }
263
dimension_handlers_no_ArrayAccess_write_dimension(zend_object * object,zval * offset,zval * value)264 static void dimension_handlers_no_ArrayAccess_write_dimension(zend_object *object, zval *offset, zval *value) {
265 dimension_common_helper(object, offset, 1);
266 }
267
dimension_handlers_no_ArrayAccess_has_dimension(zend_object * object,zval * offset,int check_empty)268 static int dimension_handlers_no_ArrayAccess_has_dimension(zend_object *object, zval *offset, int check_empty) {
269 /* checkEmpty */
270 ZVAL_LONG(OBJ_PROP_NUM(object, 6), check_empty);
271 dimension_common_helper(object, offset, 2);
272
273 /* Normal logic */
274 return 1;
275 }
276
dimension_handlers_no_ArrayAccess_unset_dimension(zend_object * object,zval * offset)277 static void dimension_handlers_no_ArrayAccess_unset_dimension(zend_object *object, zval *offset) {
278 dimension_common_helper(object, offset, 3);
279 }
280
zend_test_object_handlers_init(void)281 void zend_test_object_handlers_init(void)
282 {
283 /* DoOperationNoCast class */
284 donc_ce = register_class_DoOperationNoCast();
285 donc_ce->create_object = donc_object_create;
286 memcpy(&donc_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
287 donc_object_handlers.do_operation = donc_do_operation;
288
289 /* CastableNoOperation classes */
290 long_castable_no_operation_ce = register_class_LongCastableNoOperations();
291 long_castable_no_operation_ce->create_object = long_castable_no_operation_object_create;
292 memcpy(&long_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
293 long_castable_no_operation_object_handlers.cast_object = long_castable_no_operation_cast_object;
294
295 float_castable_no_operation_ce = register_class_FloatCastableNoOperations();
296 float_castable_no_operation_ce->create_object = float_castable_no_operation_object_create;
297 memcpy(&float_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
298 float_castable_no_operation_object_handlers.cast_object = float_castable_no_operation_cast_object;
299
300 numeric_castable_no_operation_ce = register_class_NumericCastableNoOperations();
301 numeric_castable_no_operation_ce->create_object = numeric_castable_no_operation_object_create;
302 memcpy(&numeric_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
303 numeric_castable_no_operation_object_handlers.cast_object = numeric_castable_no_operation_cast_object;
304
305 dimension_handlers_no_ArrayAccess_ce = register_class_DimensionHandlersNoArrayAccess();
306 dimension_handlers_no_ArrayAccess_ce->create_object = dimension_handlers_no_ArrayAccess_object_create;
307 memcpy(&dimension_handlers_no_ArrayAccess_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
308 dimension_handlers_no_ArrayAccess_object_handlers.read_dimension = dimension_handlers_no_ArrayAccess_read_dimension;
309 dimension_handlers_no_ArrayAccess_object_handlers.write_dimension = dimension_handlers_no_ArrayAccess_write_dimension;
310 dimension_handlers_no_ArrayAccess_object_handlers.has_dimension = dimension_handlers_no_ArrayAccess_has_dimension;
311 dimension_handlers_no_ArrayAccess_object_handlers.unset_dimension = dimension_handlers_no_ArrayAccess_unset_dimension;
312 }
313