This source file includes following definitions.
- overriden_ptr_dtor
- zend_duplicate_property_info
- zend_duplicate_property_info_internal
- zend_duplicate_function
- do_inherit_parent_constructor
- zend_visibility_string
- zend_do_perform_type_hint_check
- zend_do_perform_implementation_check
- zend_append_type_hint
- zend_get_function_declaration
- do_inheritance_check_on_method
- do_inherit_method
- do_inherit_property
- do_implement_interface
- zend_do_inherit_interfaces
- do_inherit_class_constant
- zend_do_inheritance
- do_inherit_constant_check
- do_inherit_iface_constant
- zend_do_implement_interface
- zend_do_implement_trait
- zend_traits_method_compatibility_check
- zend_add_magic_methods
- zend_add_trait_method
- zend_fixup_trait_method
- zend_traits_copy_functions
- zend_check_trait_usage
- zend_traits_init_trait_structures
- zend_traits_compile_exclude_table
- zend_do_traits_method_binding
- find_first_definition
- zend_do_traits_property_binding
- zend_do_check_for_inconsistent_traits_aliasing
- zend_do_bind_traits
- zend_has_deprecated_constructor
- zend_check_deprecated_constructor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include "zend.h"
21 #include "zend_API.h"
22 #include "zend_compile.h"
23 #include "zend_execute.h"
24 #include "zend_inheritance.h"
25 #include "zend_smart_str.h"
26 #include "zend_inheritance.h"
27
28 static void overriden_ptr_dtor(zval *zv)
29 {
30 efree_size(Z_PTR_P(zv), sizeof(zend_function));
31 }
32
33
34 static zend_property_info *zend_duplicate_property_info(zend_property_info *property_info)
35 {
36 zend_property_info* new_property_info;
37
38 new_property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
39 memcpy(new_property_info, property_info, sizeof(zend_property_info));
40 zend_string_addref(new_property_info->name);
41 if (new_property_info->doc_comment) {
42 zend_string_addref(new_property_info->doc_comment);
43 }
44 return new_property_info;
45 }
46
47
48 static zend_property_info *zend_duplicate_property_info_internal(zend_property_info *property_info)
49 {
50 zend_property_info* new_property_info = pemalloc(sizeof(zend_property_info), 1);
51 memcpy(new_property_info, property_info, sizeof(zend_property_info));
52 zend_string_addref(new_property_info->name);
53 return new_property_info;
54 }
55
56
57 static zend_function *zend_duplicate_function(zend_function *func, zend_class_entry *ce)
58 {
59 zend_function *new_function;
60
61 if (UNEXPECTED(func->type == ZEND_INTERNAL_FUNCTION)) {
62 if (UNEXPECTED(ce->type & ZEND_INTERNAL_CLASS)) {
63 new_function = pemalloc(sizeof(zend_internal_function), 1);
64 memcpy(new_function, func, sizeof(zend_internal_function));
65 } else {
66 new_function = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function));
67 memcpy(new_function, func, sizeof(zend_internal_function));
68 new_function->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED;
69 }
70 if (EXPECTED(new_function->common.function_name)) {
71 zend_string_addref(new_function->common.function_name);
72 }
73 } else {
74 if (func->op_array.refcount) {
75 (*func->op_array.refcount)++;
76 }
77 if (EXPECTED(!func->op_array.static_variables)) {
78
79 return func;
80 }
81 if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
82 GC_REFCOUNT(func->op_array.static_variables)++;
83 }
84 new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
85 memcpy(new_function, func, sizeof(zend_op_array));
86 }
87 return new_function;
88 }
89
90
91 static void do_inherit_parent_constructor(zend_class_entry *ce)
92 {
93 ZEND_ASSERT(ce->parent != NULL);
94
95
96 ce->create_object = ce->parent->create_object;
97
98
99 if (EXPECTED(!ce->get_iterator)) {
100 ce->get_iterator = ce->parent->get_iterator;
101 }
102 if (EXPECTED(!ce->iterator_funcs.funcs)) {
103 ce->iterator_funcs.funcs = ce->parent->iterator_funcs.funcs;
104 }
105 if (EXPECTED(!ce->__get)) {
106 ce->__get = ce->parent->__get;
107 }
108 if (EXPECTED(!ce->__set)) {
109 ce->__set = ce->parent->__set;
110 }
111 if (EXPECTED(!ce->__unset)) {
112 ce->__unset = ce->parent->__unset;
113 }
114 if (EXPECTED(!ce->__isset)) {
115 ce->__isset = ce->parent->__isset;
116 }
117 if (EXPECTED(!ce->__call)) {
118 ce->__call = ce->parent->__call;
119 }
120 if (EXPECTED(!ce->__callstatic)) {
121 ce->__callstatic = ce->parent->__callstatic;
122 }
123 if (EXPECTED(!ce->__tostring)) {
124 ce->__tostring = ce->parent->__tostring;
125 }
126 if (EXPECTED(!ce->clone)) {
127 ce->clone = ce->parent->clone;
128 }
129 if (EXPECTED(!ce->serialize)) {
130 ce->serialize = ce->parent->serialize;
131 }
132 if (EXPECTED(!ce->unserialize)) {
133 ce->unserialize = ce->parent->unserialize;
134 }
135 if (!ce->destructor) {
136 ce->destructor = ce->parent->destructor;
137 }
138 if (EXPECTED(!ce->__debugInfo)) {
139 ce->__debugInfo = ce->parent->__debugInfo;
140 }
141
142 if (ce->constructor) {
143 if (ce->parent->constructor && UNEXPECTED(ce->parent->constructor->common.fn_flags & ZEND_ACC_FINAL)) {
144 zend_error_noreturn(E_ERROR, "Cannot override final %s::%s() with %s::%s()",
145 ZSTR_VAL(ce->parent->name), ZSTR_VAL(ce->parent->constructor->common.function_name),
146 ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
147 }
148 return;
149 }
150
151 ce->constructor = ce->parent->constructor;
152 }
153
154
155 char *zend_visibility_string(uint32_t fn_flags)
156 {
157 if (fn_flags & ZEND_ACC_PRIVATE) {
158 return "private";
159 }
160 if (fn_flags & ZEND_ACC_PROTECTED) {
161 return "protected";
162 }
163 if (fn_flags & ZEND_ACC_PUBLIC) {
164 return "public";
165 }
166 return "";
167 }
168
169
170 static int zend_do_perform_type_hint_check(const zend_function *fe, zend_arg_info *fe_arg_info, const zend_function *proto, zend_arg_info *proto_arg_info)
171 {
172 if (ZEND_LOG_XOR(fe_arg_info->class_name, proto_arg_info->class_name)) {
173
174 return 0;
175 }
176
177 if (fe_arg_info->class_name) {
178 zend_string *fe_class_name, *proto_class_name;
179 const char *class_name;
180
181 if (fe->type == ZEND_INTERNAL_FUNCTION) {
182 fe_class_name = NULL;
183 class_name = ((zend_internal_arg_info*)fe_arg_info)->class_name;
184 } else {
185 fe_class_name = fe_arg_info->class_name;
186 class_name = ZSTR_VAL(fe_arg_info->class_name);
187 }
188 if (!strcasecmp(class_name, "parent") && proto->common.scope) {
189 fe_class_name = zend_string_copy(proto->common.scope->name);
190 } else if (!strcasecmp(class_name, "self") && fe->common.scope) {
191 fe_class_name = zend_string_copy(fe->common.scope->name);
192 } else if (fe_class_name) {
193 zend_string_addref(fe_class_name);
194 } else {
195 fe_class_name = zend_string_init(class_name, strlen(class_name), 0);
196 }
197
198 if (proto->type == ZEND_INTERNAL_FUNCTION) {
199 proto_class_name = NULL;
200 class_name = ((zend_internal_arg_info*)proto_arg_info)->class_name;
201 } else {
202 proto_class_name = proto_arg_info->class_name;
203 class_name = ZSTR_VAL(proto_arg_info->class_name);
204 }
205 if (!strcasecmp(class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
206 proto_class_name = zend_string_copy(proto->common.scope->parent->name);
207 } else if (!strcasecmp(class_name, "self") && proto->common.scope) {
208 proto_class_name = zend_string_copy(proto->common.scope->name);
209 } else if (proto_class_name) {
210 zend_string_addref(proto_class_name);
211 } else {
212 proto_class_name = zend_string_init(class_name, strlen(class_name), 0);
213 }
214
215 if (strcasecmp(ZSTR_VAL(fe_class_name), ZSTR_VAL(proto_class_name)) != 0) {
216 if (fe->common.type != ZEND_USER_FUNCTION) {
217 zend_string_release(proto_class_name);
218 zend_string_release(fe_class_name);
219 return 0;
220 } else {
221 zend_class_entry *fe_ce, *proto_ce;
222
223 fe_ce = zend_lookup_class(fe_class_name);
224 proto_ce = zend_lookup_class(proto_class_name);
225
226
227 if (!fe_ce || !proto_ce ||
228 fe_ce->type == ZEND_INTERNAL_CLASS ||
229 proto_ce->type == ZEND_INTERNAL_CLASS ||
230 fe_ce != proto_ce) {
231 zend_string_release(proto_class_name);
232 zend_string_release(fe_class_name);
233 return 0;
234 }
235 }
236 }
237 zend_string_release(proto_class_name);
238 zend_string_release(fe_class_name);
239 }
240
241 if (fe_arg_info->type_hint != proto_arg_info->type_hint) {
242
243 return 0;
244 }
245
246 return 1;
247 }
248
249
250 static zend_bool zend_do_perform_implementation_check(const zend_function *fe, const zend_function *proto)
251 {
252 uint32_t i, num_args;
253
254
255
256
257
258 if (!proto || (!proto->common.arg_info && proto->common.type != ZEND_USER_FUNCTION)) {
259 return 1;
260 }
261
262
263
264
265 if ((fe->common.fn_flags & ZEND_ACC_CTOR)
266 && ((proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
267 && (proto->common.fn_flags & ZEND_ACC_ABSTRACT) == 0)) {
268 return 1;
269 }
270
271
272 if ((fe->common.fn_flags & ZEND_ACC_PRIVATE) && (proto->common.fn_flags & ZEND_ACC_PRIVATE)) {
273 return 1;
274 }
275
276
277 if (proto->common.required_num_args < fe->common.required_num_args
278 || proto->common.num_args > fe->common.num_args) {
279 return 0;
280 }
281
282
283 if ((proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
284 && !(fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
285 return 0;
286 }
287
288 if ((proto->common.fn_flags & ZEND_ACC_VARIADIC)
289 && !(fe->common.fn_flags & ZEND_ACC_VARIADIC)) {
290 return 0;
291 }
292
293
294
295
296
297 num_args = proto->common.num_args;
298 if (proto->common.fn_flags & ZEND_ACC_VARIADIC) {
299 num_args++;
300 if (fe->common.num_args >= proto->common.num_args) {
301 num_args = fe->common.num_args;
302 if (fe->common.fn_flags & ZEND_ACC_VARIADIC) {
303 num_args++;
304 }
305 }
306 }
307
308 for (i = 0; i < num_args; i++) {
309 zend_arg_info *fe_arg_info = &fe->common.arg_info[i];
310
311 zend_arg_info *proto_arg_info;
312 if (i < proto->common.num_args) {
313 proto_arg_info = &proto->common.arg_info[i];
314 } else {
315 proto_arg_info = &proto->common.arg_info[proto->common.num_args];
316 }
317
318 if (!zend_do_perform_type_hint_check(fe, fe_arg_info, proto, proto_arg_info)) {
319 return 0;
320 }
321
322
323 if (fe_arg_info->pass_by_reference != proto_arg_info->pass_by_reference) {
324 return 0;
325 }
326 }
327
328
329
330 if (proto->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
331
332 if (!(fe->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
333 return 0;
334 }
335
336 if (!zend_do_perform_type_hint_check(fe, fe->common.arg_info - 1, proto, proto->common.arg_info - 1)) {
337 return 0;
338 }
339 }
340 return 1;
341 }
342
343
344 static ZEND_COLD void zend_append_type_hint(smart_str *str, const zend_function *fptr, zend_arg_info *arg_info, int return_hint)
345 {
346 if (arg_info->class_name) {
347 const char *class_name;
348 size_t class_name_len;
349
350 if (fptr->type == ZEND_INTERNAL_FUNCTION) {
351 class_name = ((zend_internal_arg_info*)arg_info)->class_name;
352 class_name_len = strlen(class_name);
353 } else {
354 class_name = ZSTR_VAL(arg_info->class_name);
355 class_name_len = ZSTR_LEN(arg_info->class_name);
356 }
357
358 if (!strcasecmp(class_name, "self") && fptr->common.scope) {
359 class_name = ZSTR_VAL(fptr->common.scope->name);
360 class_name_len = ZSTR_LEN(fptr->common.scope->name);
361 } else if (!strcasecmp(class_name, "parent") && fptr->common.scope && fptr->common.scope->parent) {
362 class_name = ZSTR_VAL(fptr->common.scope->parent->name);
363 class_name_len = ZSTR_LEN(fptr->common.scope->parent->name);
364 }
365
366 smart_str_appendl(str, class_name, class_name_len);
367 if (!return_hint) {
368 smart_str_appendc(str, ' ');
369 }
370 } else if (arg_info->type_hint) {
371 if (arg_info->type_hint == IS_LONG) {
372 smart_str_appendl(str, "int", 3);
373 } else if (arg_info->type_hint == _IS_BOOL) {
374 smart_str_appendl(str, "bool", 4);
375 } else {
376 const char *type_name = zend_get_type_by_const(arg_info->type_hint);
377 smart_str_appends(str, type_name);
378 }
379 if (!return_hint) {
380 smart_str_appendc(str, ' ');
381 }
382 }
383 }
384
385
386 static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function *fptr)
387 {
388 smart_str str = {0};
389
390 if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
391 smart_str_appends(&str, "& ");
392 }
393
394 if (fptr->common.scope) {
395
396 smart_str_appendl(&str, ZSTR_VAL(fptr->common.scope->name), strlen(ZSTR_VAL(fptr->common.scope->name)));
397 smart_str_appends(&str, "::");
398 }
399
400 smart_str_append(&str, fptr->common.function_name);
401 smart_str_appendc(&str, '(');
402
403 if (fptr->common.arg_info) {
404 uint32_t i, num_args, required;
405 zend_arg_info *arg_info = fptr->common.arg_info;
406
407 required = fptr->common.required_num_args;
408 num_args = fptr->common.num_args;
409 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
410 num_args++;
411 }
412 for (i = 0; i < num_args;) {
413 zend_append_type_hint(&str, fptr, arg_info, 0);
414
415 if (arg_info->pass_by_reference) {
416 smart_str_appendc(&str, '&');
417 }
418
419 if (arg_info->is_variadic) {
420 smart_str_appends(&str, "...");
421 }
422
423 smart_str_appendc(&str, '$');
424
425 if (arg_info->name) {
426 if (fptr->type == ZEND_INTERNAL_FUNCTION) {
427 smart_str_appends(&str, ((zend_internal_arg_info*)arg_info)->name);
428 } else {
429 smart_str_appendl(&str, ZSTR_VAL(arg_info->name), ZSTR_LEN(arg_info->name));
430 }
431 } else {
432 smart_str_appends(&str, "param");
433 smart_str_append_unsigned(&str, i);
434 }
435
436 if (i >= required && !arg_info->is_variadic) {
437 smart_str_appends(&str, " = ");
438 if (fptr->type == ZEND_USER_FUNCTION) {
439 zend_op *precv = NULL;
440 {
441 uint32_t idx = i;
442 zend_op *op = fptr->op_array.opcodes;
443 zend_op *end = op + fptr->op_array.last;
444
445 ++idx;
446 while (op < end) {
447 if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
448 && op->op1.num == (zend_ulong)idx)
449 {
450 precv = op;
451 }
452 ++op;
453 }
454 }
455 if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
456 zval *zv = RT_CONSTANT(&fptr->op_array, precv->op2);
457
458 if (Z_TYPE_P(zv) == IS_CONSTANT) {
459 smart_str_append(&str, Z_STR_P(zv));
460 } else if (Z_TYPE_P(zv) == IS_FALSE) {
461 smart_str_appends(&str, "false");
462 } else if (Z_TYPE_P(zv) == IS_TRUE) {
463 smart_str_appends(&str, "true");
464 } else if (Z_TYPE_P(zv) == IS_NULL) {
465 smart_str_appends(&str, "NULL");
466 } else if (Z_TYPE_P(zv) == IS_STRING) {
467 smart_str_appendc(&str, '\'');
468 smart_str_appendl(&str, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 10));
469 if (Z_STRLEN_P(zv) > 10) {
470 smart_str_appends(&str, "...");
471 }
472 smart_str_appendc(&str, '\'');
473 } else if (Z_TYPE_P(zv) == IS_ARRAY) {
474 smart_str_appends(&str, "Array");
475 } else if (Z_TYPE_P(zv) == IS_CONSTANT_AST) {
476 smart_str_appends(&str, "<expression>");
477 } else {
478 zend_string *zv_str = zval_get_string(zv);
479 smart_str_append(&str, zv_str);
480 zend_string_release(zv_str);
481 }
482 }
483 } else {
484 smart_str_appends(&str, "NULL");
485 }
486 }
487
488 if (++i < num_args) {
489 smart_str_appends(&str, ", ");
490 }
491 arg_info++;
492 }
493 }
494
495 smart_str_appendc(&str, ')');
496
497 if (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
498 smart_str_appends(&str, ": ");
499 zend_append_type_hint(&str, fptr, fptr->common.arg_info - 1, 1);
500 }
501 smart_str_0(&str);
502
503 return str.s;
504 }
505
506
507 static void do_inheritance_check_on_method(zend_function *child, zend_function *parent)
508 {
509 uint32_t child_flags;
510 uint32_t parent_flags = parent->common.fn_flags;
511
512 if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
513 && parent->common.fn_flags & ZEND_ACC_ABSTRACT
514 && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
515 && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
516 zend_error_noreturn(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)",
517 ZSTR_VAL(parent->common.scope->name),
518 ZSTR_VAL(child->common.function_name),
519 child->common.prototype ? ZSTR_VAL(child->common.prototype->common.scope->name) : ZSTR_VAL(child->common.scope->name));
520 }
521
522 if (UNEXPECTED(parent_flags & ZEND_ACC_FINAL)) {
523 zend_error_noreturn(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name));
524 }
525
526 child_flags = child->common.fn_flags;
527
528
529 if (UNEXPECTED((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC))) {
530 if (child->common.fn_flags & ZEND_ACC_STATIC) {
531 zend_error_noreturn(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
532 } else {
533 zend_error_noreturn(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
534 }
535 }
536
537
538 if (UNEXPECTED((child_flags & ZEND_ACC_ABSTRACT) > (parent_flags & ZEND_ACC_ABSTRACT))) {
539 zend_error_noreturn(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
540 }
541
542 if (parent_flags & ZEND_ACC_CHANGED) {
543 child->common.fn_flags |= ZEND_ACC_CHANGED;
544 } else {
545
546
547 if (UNEXPECTED((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK))) {
548 zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), ZSTR_VAL(child->common.function_name), zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
549 } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
550 && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
551 child->common.fn_flags |= ZEND_ACC_CHANGED;
552 }
553 }
554
555 if (parent_flags & ZEND_ACC_PRIVATE) {
556 child->common.prototype = NULL;
557 } else if (parent_flags & ZEND_ACC_ABSTRACT) {
558 child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
559 child->common.prototype = parent;
560 } else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
561
562 child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
563 }
564
565 if (child->common.prototype && (
566 child->common.prototype->common.fn_flags & (ZEND_ACC_ABSTRACT | ZEND_ACC_HAS_RETURN_TYPE)
567 )) {
568 if (UNEXPECTED(!zend_do_perform_implementation_check(child, child->common.prototype))) {
569 zend_string *method_prototype = zend_get_function_declaration(child->common.prototype);
570 zend_string *child_prototype = zend_get_function_declaration(child);
571 zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype));
572 }
573 } else if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) {
574 zend_string *method_prototype = zend_get_function_declaration(parent);
575 zend_string *child_prototype = zend_get_function_declaration(child);
576 zend_error(E_WARNING, "Declaration of %s should be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype));
577 zend_string_free(child_prototype);
578 zend_string_free(method_prototype);
579 }
580 }
581
582
583 static zend_function *do_inherit_method(zend_string *key, zend_function *parent, zend_class_entry *ce)
584 {
585 zval *child = zend_hash_find(&ce->function_table, key);
586
587 if (child) {
588 zend_function *func = (zend_function*)Z_PTR_P(child);
589 zend_function *orig_prototype = func->common.prototype;
590
591 do_inheritance_check_on_method(func, parent);
592 if (func->common.prototype != orig_prototype &&
593 func->type == ZEND_USER_FUNCTION &&
594 func->common.scope != ce &&
595 !func->op_array.static_variables) {
596
597 zend_function *new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
598 memcpy(new_function, func, sizeof(zend_op_array));
599 Z_PTR_P(child) = new_function;
600 func->common.prototype = orig_prototype;
601 }
602 return NULL;
603 }
604
605 if (parent->common.fn_flags & (ZEND_ACC_ABSTRACT)) {
606 ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
607 }
608
609 return zend_duplicate_function(parent, ce);
610 }
611
612
613 static void do_inherit_property(zend_property_info *parent_info, zend_string *key, zend_class_entry *ce)
614 {
615 zval *child = zend_hash_find(&ce->properties_info, key);
616 zend_property_info *child_info;
617
618 if (UNEXPECTED(child)) {
619 child_info = Z_PTR_P(child);
620 if (UNEXPECTED(parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW))) {
621 child_info->flags |= ZEND_ACC_CHANGED;
622 } else {
623 if (UNEXPECTED((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC))) {
624 zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
625 (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ZSTR_VAL(ce->parent->name), ZSTR_VAL(key),
626 (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ZSTR_VAL(ce->name), ZSTR_VAL(key));
627 }
628
629 if (parent_info->flags & ZEND_ACC_CHANGED) {
630 child_info->flags |= ZEND_ACC_CHANGED;
631 }
632
633 if (UNEXPECTED((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK))) {
634 zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ZSTR_VAL(ce->name), ZSTR_VAL(key), zend_visibility_string(parent_info->flags), ZSTR_VAL(ce->parent->name), (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
635 } else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
636 int parent_num = OBJ_PROP_TO_NUM(parent_info->offset);
637 int child_num = OBJ_PROP_TO_NUM(child_info->offset);
638
639 zval_ptr_dtor(&(ce->default_properties_table[parent_num]));
640 ce->default_properties_table[parent_num] = ce->default_properties_table[child_num];
641 ZVAL_UNDEF(&ce->default_properties_table[child_num]);
642 child_info->offset = parent_info->offset;
643 }
644 }
645 } else {
646 if (UNEXPECTED(parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW))) {
647 if (UNEXPECTED(ce->type & ZEND_INTERNAL_CLASS)) {
648 child_info = zend_duplicate_property_info_internal(parent_info);
649 } else {
650 child_info = zend_duplicate_property_info(parent_info);
651 }
652 child_info->flags &= ~ZEND_ACC_PRIVATE;
653 child_info->flags |= ZEND_ACC_SHADOW;
654 } else {
655 if (UNEXPECTED(ce->type & ZEND_INTERNAL_CLASS)) {
656 child_info = zend_duplicate_property_info_internal(parent_info);
657 } else {
658 child_info = parent_info;
659 }
660 }
661 _zend_hash_append_ptr(&ce->properties_info, key, child_info);
662 }
663 }
664
665
666 static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface)
667 {
668 if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce) == FAILURE) {
669 zend_error_noreturn(E_CORE_ERROR, "Class %s could not implement interface %s", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
670 }
671 if (UNEXPECTED(ce == iface)) {
672 zend_error_noreturn(E_ERROR, "Interface %s cannot implement itself", ZSTR_VAL(ce->name));
673 }
674 }
675
676
677 ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface)
678 {
679
680 uint32_t i, ce_num, if_num = iface->num_interfaces;
681 zend_class_entry *entry;
682
683 if (if_num==0) {
684 return;
685 }
686 ce_num = ce->num_interfaces;
687
688 if (ce->type == ZEND_INTERNAL_CLASS) {
689 ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
690 } else {
691 ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
692 }
693
694
695 while (if_num--) {
696 entry = iface->interfaces[if_num];
697 for (i = 0; i < ce_num; i++) {
698 if (ce->interfaces[i] == entry) {
699 break;
700 }
701 }
702 if (i == ce_num) {
703 ce->interfaces[ce->num_interfaces++] = entry;
704 }
705 }
706
707
708 while (ce_num < ce->num_interfaces) {
709 do_implement_interface(ce, ce->interfaces[ce_num++]);
710 }
711 }
712
713
714 static void do_inherit_class_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *parent_ce)
715 {
716 if (!zend_hash_exists(&ce->constants_table, name)) {
717 if (!Z_ISREF_P(zv)) {
718 if (parent_ce->type == ZEND_INTERNAL_CLASS) {
719 ZVAL_NEW_PERSISTENT_REF(zv, zv);
720 } else {
721 ZVAL_NEW_REF(zv, zv);
722 }
723 }
724 if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
725 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
726 }
727 Z_ADDREF_P(zv);
728 _zend_hash_append(&ce->constants_table, name, zv);
729 }
730 }
731
732
733 ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce)
734 {
735 zend_property_info *property_info;
736 zend_function *func;
737 zend_string *key;
738 zval *zv;
739
740 if (UNEXPECTED(ce->ce_flags & ZEND_ACC_INTERFACE)) {
741
742 if (UNEXPECTED(!(parent_ce->ce_flags & ZEND_ACC_INTERFACE))) {
743 zend_error_noreturn(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ZSTR_VAL(ce->name), ZSTR_VAL(parent_ce->name));
744 }
745 } else if (UNEXPECTED(parent_ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_FINAL))) {
746
747 if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
748 zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ZSTR_VAL(ce->name), ZSTR_VAL(parent_ce->name));
749 } else if (parent_ce->ce_flags & ZEND_ACC_TRAIT) {
750 zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend from trait %s", ZSTR_VAL(ce->name), ZSTR_VAL(parent_ce->name));
751 }
752
753
754 if (parent_ce->ce_flags & ZEND_ACC_FINAL) {
755 zend_error_noreturn(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ZSTR_VAL(ce->name), ZSTR_VAL(parent_ce->name));
756 }
757 }
758
759 ce->parent = parent_ce;
760
761
762 zend_do_inherit_interfaces(ce, parent_ce);
763
764
765 if (parent_ce->default_properties_count) {
766 zval *src, *dst, *end;
767
768 if (ce->default_properties_count) {
769 zval *table = pemalloc(sizeof(zval) * (ce->default_properties_count + parent_ce->default_properties_count), ce->type == ZEND_INTERNAL_CLASS);
770 src = ce->default_properties_table + ce->default_properties_count;
771 end = table + parent_ce->default_properties_count;
772 dst = end + ce->default_properties_count;
773 ce->default_properties_table = table;
774 do {
775 dst--;
776 src--;
777 ZVAL_COPY_VALUE(dst, src);
778 } while (dst != end);
779 pefree(src, ce->type == ZEND_INTERNAL_CLASS);
780 end = ce->default_properties_table;
781 } else {
782 end = pemalloc(sizeof(zval) * parent_ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
783 dst = end + parent_ce->default_properties_count;
784 ce->default_properties_table = end;
785 }
786 src = parent_ce->default_properties_table + parent_ce->default_properties_count;
787 do {
788 dst--;
789 src--;
790 #ifdef ZTS
791 if (parent_ce->type != ce->type) {
792 ZVAL_DUP(dst, src);
793 if (Z_OPT_CONSTANT_P(dst)) {
794 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
795 }
796 continue;
797 }
798 #endif
799
800 ZVAL_COPY(dst, src);
801 if (Z_OPT_CONSTANT_P(dst)) {
802 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
803 }
804 } while (dst != end);
805 ce->default_properties_count += parent_ce->default_properties_count;
806 }
807
808 if (parent_ce->default_static_members_count) {
809 zval *src, *dst, *end;
810
811 if (ce->default_static_members_count) {
812 zval *table = pemalloc(sizeof(zval) * (ce->default_static_members_count + parent_ce->default_static_members_count), ce->type == ZEND_INTERNAL_CLASS);
813 src = ce->default_static_members_table + ce->default_static_members_count;
814 end = table + parent_ce->default_static_members_count;
815 dst = end + ce->default_static_members_count;
816 ce->default_static_members_table = table;
817 do {
818 dst--;
819 src--;
820 ZVAL_COPY_VALUE(dst, src);
821 } while (dst != end);
822 pefree(src, ce->type == ZEND_INTERNAL_CLASS);
823 end = ce->default_static_members_table;
824 } else {
825 end = pemalloc(sizeof(zval) * parent_ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
826 dst = end + parent_ce->default_static_members_count;
827 ce->default_static_members_table = end;
828 }
829 src = parent_ce->default_static_members_table + parent_ce->default_static_members_count;
830 do {
831 dst--;
832 src--;
833 if (parent_ce->type == ZEND_INTERNAL_CLASS) {
834 if (!Z_ISREF_P(src)) {
835 ZVAL_NEW_PERSISTENT_REF(src, src);
836 }
837 } else {
838 ZVAL_MAKE_REF(src);
839 }
840 ZVAL_COPY_VALUE(dst, src);
841 Z_ADDREF_P(dst);
842 if (Z_CONSTANT_P(Z_REFVAL_P(dst))) {
843 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
844 }
845 } while (dst != end);
846 ce->default_static_members_count += parent_ce->default_static_members_count;
847 if (ce->type == ZEND_USER_CLASS) {
848 ce->static_members_table = ce->default_static_members_table;
849 } else {
850 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
851 }
852 }
853
854 ZEND_HASH_FOREACH_PTR(&ce->properties_info, property_info) {
855 if (property_info->ce == ce) {
856 if (property_info->flags & ZEND_ACC_STATIC) {
857 property_info->offset += parent_ce->default_static_members_count;
858 } else {
859 property_info->offset += parent_ce->default_properties_count * sizeof(zval);
860 }
861 }
862 } ZEND_HASH_FOREACH_END();
863
864 if (zend_hash_num_elements(&parent_ce->properties_info)) {
865 zend_hash_extend(&ce->properties_info,
866 zend_hash_num_elements(&ce->properties_info) +
867 zend_hash_num_elements(&parent_ce->properties_info), 0);
868
869 ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, property_info) {
870 do_inherit_property(property_info, key, ce);
871 } ZEND_HASH_FOREACH_END();
872 }
873
874 if (zend_hash_num_elements(&parent_ce->constants_table)) {
875 zend_hash_extend(&ce->constants_table,
876 zend_hash_num_elements(&ce->constants_table) +
877 zend_hash_num_elements(&parent_ce->constants_table), 0);
878
879 ZEND_HASH_FOREACH_STR_KEY_VAL(&parent_ce->constants_table, key, zv) {
880 do_inherit_class_constant(key, zv, ce, parent_ce);
881 } ZEND_HASH_FOREACH_END();
882 }
883
884 if (zend_hash_num_elements(&parent_ce->function_table)) {
885 zend_hash_extend(&ce->function_table,
886 zend_hash_num_elements(&ce->function_table) +
887 zend_hash_num_elements(&parent_ce->function_table), 0);
888
889 ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) {
890 zend_function *new_func = do_inherit_method(key, func, ce);
891
892 if (new_func) {
893 _zend_hash_append_ptr(&ce->function_table, key, new_func);
894 }
895 } ZEND_HASH_FOREACH_END();
896 }
897
898 do_inherit_parent_constructor(ce);
899
900 if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
901 ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
902 } else if (!(ce->ce_flags & (ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
903
904 zend_verify_abstract_class(ce);
905 }
906 ce->ce_flags |= parent_ce->ce_flags & (ZEND_HAS_STATIC_IN_METHODS | ZEND_ACC_USE_GUARDS);
907 }
908
909
910 static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zval *parent_constant, zend_string *name, const zend_class_entry *iface)
911 {
912 zval *old_constant;
913
914 if ((old_constant = zend_hash_find(child_constants_table, name)) != NULL) {
915 if (!Z_ISREF_P(old_constant) ||
916 !Z_ISREF_P(parent_constant) ||
917 Z_REFVAL_P(old_constant) != Z_REFVAL_P(parent_constant)) {
918 zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", ZSTR_VAL(name), ZSTR_VAL(iface->name));
919 }
920 return 0;
921 }
922 return 1;
923 }
924
925
926 static void do_inherit_iface_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *iface)
927 {
928 if (do_inherit_constant_check(&ce->constants_table, zv, name, iface)) {
929 if (!Z_ISREF_P(zv)) {
930 if (iface->type == ZEND_INTERNAL_CLASS) {
931 ZVAL_NEW_PERSISTENT_REF(zv, zv);
932 } else {
933 ZVAL_NEW_REF(zv, zv);
934 }
935 }
936 Z_ADDREF_P(zv);
937 if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
938 ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
939 }
940 zend_hash_update(&ce->constants_table, name, zv);
941 }
942 }
943
944
945 ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface)
946 {
947 uint32_t i, ignore = 0;
948 uint32_t current_iface_num = ce->num_interfaces;
949 uint32_t parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0;
950 zend_function *func;
951 zend_string *key;
952 zval *zv;
953
954 for (i = 0; i < ce->num_interfaces; i++) {
955 if (ce->interfaces[i] == NULL) {
956 memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
957 i--;
958 } else if (ce->interfaces[i] == iface) {
959 if (EXPECTED(i < parent_iface_num)) {
960 ignore = 1;
961 } else {
962 zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
963 }
964 }
965 }
966 if (ignore) {
967
968 ZEND_HASH_FOREACH_STR_KEY_VAL(&ce->constants_table, key, zv) {
969 do_inherit_constant_check(&iface->constants_table, zv, key, iface);
970 } ZEND_HASH_FOREACH_END();
971 } else {
972 if (ce->num_interfaces >= current_iface_num) {
973 if (ce->type == ZEND_INTERNAL_CLASS) {
974 ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
975 } else {
976 ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
977 }
978 }
979 ce->interfaces[ce->num_interfaces++] = iface;
980
981 ZEND_HASH_FOREACH_STR_KEY_VAL(&iface->constants_table, key, zv) {
982 do_inherit_iface_constant(key, zv, ce, iface);
983 } ZEND_HASH_FOREACH_END();
984
985 ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) {
986 zend_function *new_func = do_inherit_method(key, func, ce);
987
988 if (new_func) {
989 zend_hash_add_new_ptr(&ce->function_table, key, new_func);
990 }
991 } ZEND_HASH_FOREACH_END();
992
993 do_implement_interface(ce, iface);
994 zend_do_inherit_interfaces(ce, iface);
995 }
996 }
997
998
999 ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait)
1000 {
1001 uint32_t i, ignore = 0;
1002 uint32_t current_trait_num = ce->num_traits;
1003 uint32_t parent_trait_num = ce->parent ? ce->parent->num_traits : 0;
1004
1005 for (i = 0; i < ce->num_traits; i++) {
1006 if (ce->traits[i] == NULL) {
1007 memmove(ce->traits + i, ce->traits + i + 1, sizeof(zend_class_entry*) * (--ce->num_traits - i));
1008 i--;
1009 } else if (ce->traits[i] == trait) {
1010 if (i < parent_trait_num) {
1011 ignore = 1;
1012 }
1013 }
1014 }
1015 if (!ignore) {
1016 if (ce->num_traits >= current_trait_num) {
1017 if (ce->type == ZEND_INTERNAL_CLASS) {
1018 ce->traits = (zend_class_entry **) realloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
1019 } else {
1020 ce->traits = (zend_class_entry **) erealloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
1021 }
1022 }
1023 ce->traits[ce->num_traits++] = trait;
1024 }
1025 }
1026
1027
1028 static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_function *other_fn)
1029 {
1030 uint32_t fn_flags = fn->common.scope->ce_flags;
1031 uint32_t other_flags = other_fn->common.scope->ce_flags;
1032
1033 return zend_do_perform_implementation_check(fn, other_fn)
1034 && ((other_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) || zend_do_perform_implementation_check(other_fn, fn))
1035 && ((fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC)) ==
1036 (other_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC)));
1037 }
1038
1039
1040 static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zend_function* fe)
1041 {
1042 if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) {
1043 ce->clone = fe; fe->common.fn_flags |= ZEND_ACC_CLONE;
1044 } else if (zend_string_equals_literal(mname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
1045 if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
1046 zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name));
1047 }
1048 ce->constructor = fe; fe->common.fn_flags |= ZEND_ACC_CTOR;
1049 } else if (zend_string_equals_literal(mname, ZEND_DESTRUCTOR_FUNC_NAME)) {
1050 ce->destructor = fe; fe->common.fn_flags |= ZEND_ACC_DTOR;
1051 } else if (zend_string_equals_literal(mname, ZEND_GET_FUNC_NAME)) {
1052 ce->__get = fe;
1053 ce->ce_flags |= ZEND_ACC_USE_GUARDS;
1054 } else if (zend_string_equals_literal(mname, ZEND_SET_FUNC_NAME)) {
1055 ce->__set = fe;
1056 ce->ce_flags |= ZEND_ACC_USE_GUARDS;
1057 } else if (zend_string_equals_literal(mname, ZEND_CALL_FUNC_NAME)) {
1058 ce->__call = fe;
1059 } else if (zend_string_equals_literal(mname, ZEND_UNSET_FUNC_NAME)) {
1060 ce->__unset = fe;
1061 ce->ce_flags |= ZEND_ACC_USE_GUARDS;
1062 } else if (zend_string_equals_literal(mname, ZEND_ISSET_FUNC_NAME)) {
1063 ce->__isset = fe;
1064 ce->ce_flags |= ZEND_ACC_USE_GUARDS;
1065 } else if (zend_string_equals_literal(mname, ZEND_CALLSTATIC_FUNC_NAME)) {
1066 ce->__callstatic = fe;
1067 } else if (zend_string_equals_literal(mname, ZEND_TOSTRING_FUNC_NAME)) {
1068 ce->__tostring = fe;
1069 } else if (zend_string_equals_literal(mname, ZEND_DEBUGINFO_FUNC_NAME)) {
1070 ce->__debugInfo = fe;
1071 } else if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) {
1072 zend_string *lowercase_name = zend_string_tolower(ce->name);
1073 lowercase_name = zend_new_interned_string(lowercase_name);
1074 if (!memcmp(ZSTR_VAL(mname), ZSTR_VAL(lowercase_name), ZSTR_LEN(mname))) {
1075 if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
1076 zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name));
1077 }
1078 ce->constructor = fe;
1079 fe->common.fn_flags |= ZEND_ACC_CTOR;
1080 }
1081 zend_string_release(lowercase_name);
1082 }
1083 }
1084
1085
1086 static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_string *key, zend_function *fn, HashTable **overriden)
1087 {
1088 zend_function *existing_fn = NULL;
1089 zend_function *new_fn;
1090
1091 if ((existing_fn = zend_hash_find_ptr(&ce->function_table, key)) != NULL) {
1092 if (existing_fn->common.scope == ce) {
1093
1094
1095 if (*overriden) {
1096 if ((existing_fn = zend_hash_find_ptr(*overriden, key)) != NULL) {
1097 if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1098
1099 if (UNEXPECTED(!zend_traits_method_compatibility_check(fn, existing_fn))) {
1100 zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
1101 ZSTR_VAL(zend_get_function_declaration(fn)),
1102 ZSTR_VAL(zend_get_function_declaration(existing_fn)));
1103 }
1104 } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1105
1106 if (UNEXPECTED(!zend_traits_method_compatibility_check(existing_fn, fn))) {
1107 zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
1108 ZSTR_VAL(zend_get_function_declaration(fn)),
1109 ZSTR_VAL(zend_get_function_declaration(existing_fn)));
1110 }
1111 return;
1112 }
1113 }
1114 } else {
1115 ALLOC_HASHTABLE(*overriden);
1116 zend_hash_init_ex(*overriden, 8, NULL, overriden_ptr_dtor, 0, 0);
1117 }
1118 zend_hash_update_mem(*overriden, key, fn, sizeof(zend_function));
1119 return;
1120 } else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT &&
1121 (existing_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0) {
1122
1123 if (UNEXPECTED(!zend_traits_method_compatibility_check(fn, existing_fn))) {
1124 zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
1125 ZSTR_VAL(zend_get_function_declaration(fn)),
1126 ZSTR_VAL(zend_get_function_declaration(existing_fn)));
1127 }
1128 } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1129
1130 if (UNEXPECTED(!zend_traits_method_compatibility_check(existing_fn, fn))) {
1131 zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
1132 ZSTR_VAL(zend_get_function_declaration(fn)),
1133 ZSTR_VAL(zend_get_function_declaration(existing_fn)));
1134 }
1135 return;
1136 } else if (UNEXPECTED(existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT)) {
1137
1138 #if 1
1139 zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s has not been applied, because there are collisions with other trait methods on %s",
1140 name, ZSTR_VAL(ce->name));
1141 #else
1142 zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s::%s has not been applied as %s::%s, because of collision with %s::%s",
1143 ZSTR_VAL(fn->common.scope->name), ZSTR_VAL(fn->common.function_name),
1144 ZSTR_VAL(ce->name), name,
1145 ZSTR_VAL(existing_fn->common.scope->name), ZSTR_VAL(existing_fn->common.function_name));
1146 #endif
1147 } else {
1148
1149
1150 do_inheritance_check_on_method(fn, existing_fn);
1151 fn->common.prototype = NULL;
1152 }
1153 }
1154
1155 function_add_ref(fn);
1156 new_fn = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
1157 memcpy(new_fn, fn, sizeof(zend_op_array));
1158 fn = zend_hash_update_ptr(&ce->function_table, key, new_fn);
1159 zend_add_magic_methods(ce, key, fn);
1160 }
1161
1162
1163 static void zend_fixup_trait_method(zend_function *fn, zend_class_entry *ce)
1164 {
1165 if ((fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
1166
1167 fn->common.scope = ce;
1168
1169 if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1170 ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
1171 }
1172 if (fn->type == ZEND_USER_FUNCTION && fn->op_array.static_variables) {
1173 ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
1174 }
1175 }
1176 }
1177
1178
1179 static int zend_traits_copy_functions(zend_string *fnname, zend_function *fn, zend_class_entry *ce, HashTable **overriden, HashTable *exclude_table)
1180 {
1181 zend_trait_alias *alias, **alias_ptr;
1182 zend_string *lcname;
1183 zend_function fn_copy;
1184
1185
1186 if (ce->trait_aliases) {
1187 alias_ptr = ce->trait_aliases;
1188 alias = *alias_ptr;
1189 while (alias) {
1190
1191 if (alias->alias != NULL
1192 && (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
1193 && ZSTR_LEN(alias->trait_method->method_name) == ZSTR_LEN(fnname)
1194 && (zend_binary_strcasecmp(ZSTR_VAL(alias->trait_method->method_name), ZSTR_LEN(alias->trait_method->method_name), ZSTR_VAL(fnname), ZSTR_LEN(fnname)) == 0)) {
1195 fn_copy = *fn;
1196
1197
1198 if (alias->modifiers) {
1199 fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
1200 }
1201
1202 lcname = zend_string_tolower(alias->alias);
1203 zend_add_trait_method(ce, ZSTR_VAL(alias->alias), lcname, &fn_copy, overriden);
1204 zend_string_release(lcname);
1205
1206
1207 if (!alias->trait_method->ce) {
1208 alias->trait_method->ce = fn->common.scope;
1209 }
1210 }
1211 alias_ptr++;
1212 alias = *alias_ptr;
1213 }
1214 }
1215
1216 if (exclude_table == NULL || zend_hash_find(exclude_table, fnname) == NULL) {
1217
1218
1219 memcpy(&fn_copy, fn, fn->type == ZEND_USER_FUNCTION? sizeof(zend_op_array) : sizeof(zend_internal_function));
1220
1221
1222 if (ce->trait_aliases) {
1223 alias_ptr = ce->trait_aliases;
1224 alias = *alias_ptr;
1225 while (alias) {
1226
1227 if (alias->alias == NULL && alias->modifiers != 0
1228 && (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
1229 && (ZSTR_LEN(alias->trait_method->method_name) == ZSTR_LEN(fnname))
1230 && (zend_binary_strcasecmp(ZSTR_VAL(alias->trait_method->method_name), ZSTR_LEN(alias->trait_method->method_name), ZSTR_VAL(fnname), ZSTR_LEN(fnname)) == 0)) {
1231
1232 fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
1233
1234
1235 if (!alias->trait_method->ce) {
1236 alias->trait_method->ce = fn->common.scope;
1237 }
1238 }
1239 alias_ptr++;
1240 alias = *alias_ptr;
1241 }
1242 }
1243
1244 zend_add_trait_method(ce, ZSTR_VAL(fn->common.function_name), fnname, &fn_copy, overriden);
1245 }
1246
1247 return ZEND_HASH_APPLY_KEEP;
1248 }
1249
1250
1251 static void zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait)
1252 {
1253 uint32_t i;
1254
1255 if (UNEXPECTED((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT)) {
1256 zend_error_noreturn(E_COMPILE_ERROR, "Class %s is not a trait, Only traits may be used in 'as' and 'insteadof' statements", ZSTR_VAL(trait->name));
1257 }
1258
1259 for (i = 0; i < ce->num_traits; i++) {
1260 if (ce->traits[i] == trait) {
1261 return;
1262 }
1263 }
1264 zend_error_noreturn(E_COMPILE_ERROR, "Required Trait %s wasn't added to %s", ZSTR_VAL(trait->name), ZSTR_VAL(ce->name));
1265 }
1266
1267
1268 static void zend_traits_init_trait_structures(zend_class_entry *ce)
1269 {
1270 size_t i, j = 0;
1271 zend_trait_precedence **precedences;
1272 zend_trait_precedence *cur_precedence;
1273 zend_trait_method_reference *cur_method_ref;
1274 zend_string *lcname;
1275 zend_bool method_exists;
1276
1277
1278 if (ce->trait_precedences) {
1279 i = 0;
1280 precedences = ce->trait_precedences;
1281 ce->trait_precedences = NULL;
1282 while ((cur_precedence = precedences[i])) {
1283
1284 if (cur_precedence->exclude_from_classes) {
1285 cur_method_ref = cur_precedence->trait_method;
1286 if (!(cur_precedence->trait_method->ce = zend_fetch_class(cur_method_ref->class_name,
1287 ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD))) {
1288 zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name));
1289 }
1290 zend_check_trait_usage(ce, cur_precedence->trait_method->ce);
1291
1292
1293 lcname = zend_string_tolower(cur_method_ref->method_name);
1294 method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
1295 lcname);
1296 zend_string_release(lcname);
1297 if (!method_exists) {
1298 zend_error_noreturn(E_COMPILE_ERROR,
1299 "A precedence rule was defined for %s::%s but this method does not exist",
1300 ZSTR_VAL(cur_method_ref->ce->name),
1301 ZSTR_VAL(cur_method_ref->method_name));
1302 }
1303
1304
1305
1306
1307
1308
1309
1310 j = 0;
1311 while (cur_precedence->exclude_from_classes[j].class_name) {
1312 zend_string* class_name = cur_precedence->exclude_from_classes[j].class_name;
1313
1314 if (!(cur_precedence->exclude_from_classes[j].ce = zend_fetch_class(class_name, ZEND_FETCH_CLASS_TRAIT |ZEND_FETCH_CLASS_NO_AUTOLOAD))) {
1315 zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(class_name));
1316 }
1317 zend_check_trait_usage(ce, cur_precedence->exclude_from_classes[j].ce);
1318
1319
1320
1321 if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[j].ce) {
1322 zend_error_noreturn(E_COMPILE_ERROR,
1323 "Inconsistent insteadof definition. "
1324 "The method %s is to be used from %s, but %s is also on the exclude list",
1325 ZSTR_VAL(cur_method_ref->method_name),
1326 ZSTR_VAL(cur_precedence->trait_method->ce->name),
1327 ZSTR_VAL(cur_precedence->trait_method->ce->name));
1328 }
1329
1330 zend_string_release(class_name);
1331 j++;
1332 }
1333 }
1334 i++;
1335 }
1336 ce->trait_precedences = precedences;
1337 }
1338
1339 if (ce->trait_aliases) {
1340 i = 0;
1341 while (ce->trait_aliases[i]) {
1342
1343 if (ce->trait_aliases[i]->trait_method->class_name) {
1344 cur_method_ref = ce->trait_aliases[i]->trait_method;
1345 if (!(cur_method_ref->ce = zend_fetch_class(cur_method_ref->class_name, ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD))) {
1346 zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name));
1347 }
1348 zend_check_trait_usage(ce, cur_method_ref->ce);
1349
1350
1351 lcname = zend_string_tolower(cur_method_ref->method_name);
1352 method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
1353 lcname);
1354 zend_string_release(lcname);
1355
1356 if (!method_exists) {
1357 zend_error_noreturn(E_COMPILE_ERROR, "An alias was defined for %s::%s but this method does not exist", ZSTR_VAL(cur_method_ref->ce->name), ZSTR_VAL(cur_method_ref->method_name));
1358 }
1359 }
1360 i++;
1361 }
1362 }
1363 }
1364
1365
1366 static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_trait_precedence **precedences, zend_class_entry *trait)
1367 {
1368 size_t i = 0, j;
1369
1370 if (!precedences) {
1371 return;
1372 }
1373 while (precedences[i]) {
1374 if (precedences[i]->exclude_from_classes) {
1375 j = 0;
1376 while (precedences[i]->exclude_from_classes[j].ce) {
1377 if (precedences[i]->exclude_from_classes[j].ce == trait) {
1378 zend_string *lcname =
1379 zend_string_tolower(precedences[i]->trait_method->method_name);
1380 if (zend_hash_add_empty_element(exclude_table, lcname) == NULL) {
1381 zend_string_release(lcname);
1382 zend_error_noreturn(E_COMPILE_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times", ZSTR_VAL(precedences[i]->trait_method->method_name), ZSTR_VAL(trait->name));
1383 }
1384 zend_string_release(lcname);
1385 }
1386 ++j;
1387 }
1388 }
1389 ++i;
1390 }
1391 }
1392
1393
1394 static void zend_do_traits_method_binding(zend_class_entry *ce)
1395 {
1396 uint32_t i;
1397 HashTable *overriden = NULL;
1398 zend_string *key;
1399 zend_function *fn;
1400
1401 for (i = 0; i < ce->num_traits; i++) {
1402 if (ce->trait_precedences) {
1403 HashTable exclude_table;
1404 zend_trait_precedence **precedences;
1405
1406
1407 zend_hash_init_ex(&exclude_table, 8, NULL, NULL, 0, 0);
1408
1409 precedences = ce->trait_precedences;
1410 ce->trait_precedences = NULL;
1411 zend_traits_compile_exclude_table(&exclude_table, precedences, ce->traits[i]);
1412
1413
1414 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->traits[i]->function_table, key, fn) {
1415 zend_traits_copy_functions(key, fn, ce, &overriden, &exclude_table);
1416 } ZEND_HASH_FOREACH_END();
1417
1418 zend_hash_destroy(&exclude_table);
1419 ce->trait_precedences = precedences;
1420 } else {
1421 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->traits[i]->function_table, key, fn) {
1422 zend_traits_copy_functions(key, fn, ce, &overriden, NULL);
1423 } ZEND_HASH_FOREACH_END();
1424 }
1425 }
1426
1427 ZEND_HASH_FOREACH_PTR(&ce->function_table, fn) {
1428 zend_fixup_trait_method(fn, ce);
1429 } ZEND_HASH_FOREACH_END();
1430
1431 if (ce->trait_precedences) {
1432 i = 0;
1433 while (ce->trait_precedences[i]) {
1434 if (ce->trait_precedences[i]->exclude_from_classes) {
1435 efree(ce->trait_precedences[i]->exclude_from_classes);
1436 ce->trait_precedences[i]->exclude_from_classes = NULL;
1437 }
1438 i++;
1439 }
1440 }
1441
1442 if (overriden) {
1443 zend_hash_destroy(overriden);
1444 FREE_HASHTABLE(overriden);
1445 }
1446 }
1447
1448
1449 static zend_class_entry* find_first_definition(zend_class_entry *ce, size_t current_trait, zend_string *prop_name, zend_class_entry *coliding_ce)
1450 {
1451 size_t i;
1452
1453 if (coliding_ce == ce) {
1454 for (i = 0; i < current_trait; i++) {
1455 if (zend_hash_exists(&ce->traits[i]->properties_info, prop_name)) {
1456 return ce->traits[i];
1457 }
1458 }
1459 }
1460
1461 return coliding_ce;
1462 }
1463
1464
1465 static void zend_do_traits_property_binding(zend_class_entry *ce)
1466 {
1467 size_t i;
1468 zend_property_info *property_info;
1469 zend_property_info *coliding_prop;
1470 zval compare_result;
1471 zend_string* prop_name;
1472 const char* class_name_unused;
1473 zend_bool not_compatible;
1474 zval* prop_value;
1475 uint32_t flags;
1476 zend_string *doc_comment;
1477
1478
1479
1480
1481
1482
1483 for (i = 0; i < ce->num_traits; i++) {
1484 ZEND_HASH_FOREACH_PTR(&ce->traits[i]->properties_info, property_info) {
1485
1486
1487
1488 flags = property_info->flags;
1489 if (flags & ZEND_ACC_PUBLIC) {
1490 prop_name = zend_string_copy(property_info->name);
1491 } else {
1492 const char *pname;
1493 size_t pname_len;
1494
1495
1496 zend_unmangle_property_name_ex(property_info->name,
1497 &class_name_unused, &pname, &pname_len);
1498 prop_name = zend_string_init(pname, pname_len, 0);
1499 }
1500
1501
1502 if ((coliding_prop = zend_hash_find_ptr(&ce->properties_info, prop_name)) != NULL) {
1503 if (coliding_prop->flags & ZEND_ACC_SHADOW) {
1504 zend_string_release(coliding_prop->name);
1505 if (coliding_prop->doc_comment) {
1506 zend_string_release(coliding_prop->doc_comment);
1507 }
1508 zend_hash_del(&ce->properties_info, prop_name);
1509 flags |= ZEND_ACC_CHANGED;
1510 } else {
1511 if ((coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
1512 == (flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
1513
1514 if (flags & ZEND_ACC_STATIC) {
1515 not_compatible = (FAILURE == compare_function(&compare_result,
1516 &ce->default_static_members_table[coliding_prop->offset],
1517 &ce->traits[i]->default_static_members_table[property_info->offset]))
1518 || (Z_LVAL(compare_result) != 0);
1519 } else {
1520 not_compatible = (FAILURE == compare_function(&compare_result,
1521 &ce->default_properties_table[OBJ_PROP_TO_NUM(coliding_prop->offset)],
1522 &ce->traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]))
1523 || (Z_LVAL(compare_result) != 0);
1524 }
1525 } else {
1526
1527 not_compatible = 1;
1528 }
1529
1530 if (not_compatible) {
1531 zend_error_noreturn(E_COMPILE_ERROR,
1532 "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
1533 ZSTR_VAL(find_first_definition(ce, i, prop_name, coliding_prop->ce)->name),
1534 ZSTR_VAL(property_info->ce->name),
1535 ZSTR_VAL(prop_name),
1536 ZSTR_VAL(ce->name));
1537 }
1538
1539 zend_string_release(prop_name);
1540 continue;
1541 }
1542 }
1543
1544
1545 if (flags & ZEND_ACC_STATIC) {
1546 prop_value = &ce->traits[i]->default_static_members_table[property_info->offset];
1547 } else {
1548 prop_value = &ce->traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)];
1549 }
1550 if (Z_REFCOUNTED_P(prop_value)) Z_ADDREF_P(prop_value);
1551
1552 doc_comment = property_info->doc_comment ? zend_string_copy(property_info->doc_comment) : NULL;
1553 zend_declare_property_ex(ce, prop_name,
1554 prop_value, flags,
1555 doc_comment);
1556 zend_string_release(prop_name);
1557 } ZEND_HASH_FOREACH_END();
1558 }
1559 }
1560
1561
1562 static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce)
1563 {
1564 int i = 0;
1565 zend_trait_alias* cur_alias;
1566 zend_string* lc_method_name;
1567
1568 if (ce->trait_aliases) {
1569 while (ce->trait_aliases[i]) {
1570 cur_alias = ce->trait_aliases[i];
1571
1572
1573 if (!cur_alias->trait_method->ce) {
1574 if (cur_alias->alias) {
1575
1576 zend_error_noreturn(E_COMPILE_ERROR,
1577 "An alias (%s) was defined for method %s(), but this method does not exist",
1578 ZSTR_VAL(cur_alias->alias),
1579 ZSTR_VAL(cur_alias->trait_method->method_name));
1580 } else {
1581
1582
1583
1584
1585
1586
1587
1588
1589 lc_method_name = zend_string_tolower(
1590 cur_alias->trait_method->method_name);
1591 if (zend_hash_exists(&ce->function_table,
1592 lc_method_name)) {
1593 zend_string_release(lc_method_name);
1594 zend_error_noreturn(E_COMPILE_ERROR,
1595 "The modifiers for the trait alias %s() need to be changed in the same statement in which the alias is defined. Error",
1596 ZSTR_VAL(cur_alias->trait_method->method_name));
1597 } else {
1598 zend_string_release(lc_method_name);
1599 zend_error_noreturn(E_COMPILE_ERROR,
1600 "The modifiers of the trait method %s() are changed, but this method does not exist. Error",
1601 ZSTR_VAL(cur_alias->trait_method->method_name));
1602
1603 }
1604 }
1605 }
1606 i++;
1607 }
1608 }
1609 }
1610
1611
1612 ZEND_API void zend_do_bind_traits(zend_class_entry *ce)
1613 {
1614
1615 if (ce->num_traits <= 0) {
1616 return;
1617 }
1618
1619
1620 zend_traits_init_trait_structures(ce);
1621
1622
1623 zend_do_traits_method_binding(ce);
1624
1625
1626 zend_do_check_for_inconsistent_traits_aliasing(ce);
1627
1628
1629 zend_do_traits_property_binding(ce);
1630
1631
1632 zend_verify_abstract_class(ce);
1633
1634
1635 zend_check_deprecated_constructor(ce);
1636
1637
1638 if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
1639 ce->ce_flags -= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
1640 }
1641 }
1642
1643
1644
1645 static zend_bool zend_has_deprecated_constructor(const zend_class_entry *ce)
1646 {
1647 const zend_string *constructor_name;
1648 if (!ce->constructor) {
1649 return 0;
1650 }
1651 constructor_name = ce->constructor->common.function_name;
1652 return !zend_binary_strcasecmp(
1653 ZSTR_VAL(ce->name), ZSTR_LEN(ce->name),
1654 ZSTR_VAL(constructor_name), ZSTR_LEN(constructor_name)
1655 );
1656 }
1657
1658
1659 void zend_check_deprecated_constructor(const zend_class_entry *ce)
1660 {
1661 if (zend_has_deprecated_constructor(ce)) {
1662 zend_error(E_DEPRECATED, "Methods with the same name as their class will not be constructors in a future version of PHP; %s has a deprecated constructor", ZSTR_VAL(ce->name));
1663 }
1664 }
1665
1666
1667
1668
1669
1670
1671
1672
1673