xref: /PHP-8.2/Zend/zend_inheritance.c (revision 86b93bc4)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend license,     |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Andi Gutmans <andi@php.net>                                 |
16    |          Zeev Suraski <zeev@php.net>                                 |
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_interfaces.h"
26 #include "zend_smart_str.h"
27 #include "zend_operators.h"
28 #include "zend_exceptions.h"
29 #include "zend_enum.h"
30 #include "zend_attributes.h"
31 #include "zend_constants.h"
32 #include "zend_observer.h"
33 
34 ZEND_API zend_class_entry* (*zend_inheritance_cache_get)(zend_class_entry *ce, zend_class_entry *parent, zend_class_entry **traits_and_interfaces) = NULL;
35 ZEND_API zend_class_entry* (*zend_inheritance_cache_add)(zend_class_entry *ce, zend_class_entry *proto, zend_class_entry *parent, zend_class_entry **traits_and_interfaces, HashTable *dependencies) = NULL;
36 
37 /* Unresolved means that class declarations that are currently not available are needed to
38  * determine whether the inheritance is valid or not. At runtime UNRESOLVED should be treated
39  * as an ERROR. */
40 typedef enum {
41 	INHERITANCE_UNRESOLVED = -1,
42 	INHERITANCE_ERROR = 0,
43 	INHERITANCE_WARNING = 1,
44 	INHERITANCE_SUCCESS = 2,
45 } inheritance_status;
46 
47 static void add_dependency_obligation(zend_class_entry *ce, zend_class_entry *dependency_ce);
48 static void add_compatibility_obligation(
49 		zend_class_entry *ce, const zend_function *child_fn, zend_class_entry *child_scope,
50 		const zend_function *parent_fn, zend_class_entry *parent_scope);
51 static void add_property_compatibility_obligation(
52 		zend_class_entry *ce, const zend_property_info *child_prop,
53 		const zend_property_info *parent_prop);
54 
55 static void ZEND_COLD emit_incompatible_method_error(
56 		const zend_function *child, zend_class_entry *child_scope,
57 		const zend_function *parent, zend_class_entry *parent_scope,
58 		inheritance_status status);
59 
60 static void zend_type_copy_ctor(zend_type *const type, bool use_arena, bool persistent);
61 
zend_type_list_copy_ctor(zend_type * const parent_type,bool use_arena,bool persistent)62 static void zend_type_list_copy_ctor(
63 	zend_type *const parent_type,
64 	bool use_arena,
65 	bool persistent
66 ) {
67 	const zend_type_list *const old_list = ZEND_TYPE_LIST(*parent_type);
68 	size_t size = ZEND_TYPE_LIST_SIZE(old_list->num_types);
69 	zend_type_list *new_list = use_arena
70 		? zend_arena_alloc(&CG(arena), size) : pemalloc(size, persistent);
71 
72 	memcpy(new_list, old_list, size);
73 	ZEND_TYPE_SET_LIST(*parent_type, new_list);
74 	if (use_arena) {
75 		ZEND_TYPE_FULL_MASK(*parent_type) |= _ZEND_TYPE_ARENA_BIT;
76 	}
77 
78 	zend_type *list_type;
79 	ZEND_TYPE_LIST_FOREACH(new_list, list_type) {
80 		zend_type_copy_ctor(list_type, use_arena, persistent);
81 	} ZEND_TYPE_LIST_FOREACH_END();
82 }
83 
zend_type_copy_ctor(zend_type * const type,bool use_arena,bool persistent)84 static void zend_type_copy_ctor(zend_type *const type, bool use_arena, bool persistent) {
85 	if (ZEND_TYPE_HAS_LIST(*type)) {
86 		zend_type_list_copy_ctor(type, use_arena, persistent);
87 	} else if (ZEND_TYPE_HAS_NAME(*type)) {
88 		zend_string_addref(ZEND_TYPE_NAME(*type));
89 	}
90 }
91 
zend_duplicate_internal_function(zend_function * func,zend_class_entry * ce)92 static zend_function *zend_duplicate_internal_function(zend_function *func, zend_class_entry *ce) /* {{{ */
93 {
94 	zend_function *new_function;
95 
96 	if (UNEXPECTED(ce->type & ZEND_INTERNAL_CLASS)) {
97 		new_function = pemalloc(sizeof(zend_internal_function), 1);
98 		memcpy(new_function, func, sizeof(zend_internal_function));
99 	} else {
100 		new_function = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function));
101 		memcpy(new_function, func, sizeof(zend_internal_function));
102 		new_function->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED;
103 	}
104 	if (EXPECTED(new_function->common.function_name)) {
105 		zend_string_addref(new_function->common.function_name);
106 	}
107 	return new_function;
108 }
109 /* }}} */
110 
zend_duplicate_function(zend_function * func,zend_class_entry * ce)111 static zend_always_inline zend_function *zend_duplicate_function(zend_function *func, zend_class_entry *ce) /* {{{ */
112 {
113 	if (UNEXPECTED(func->type == ZEND_INTERNAL_FUNCTION)) {
114 		return zend_duplicate_internal_function(func, ce);
115 	} else {
116 		if (func->op_array.refcount) {
117 			(*func->op_array.refcount)++;
118 		}
119 		if (EXPECTED(func->op_array.function_name)) {
120 			zend_string_addref(func->op_array.function_name);
121 		}
122 		return func;
123 	}
124 }
125 /* }}} */
126 
do_inherit_parent_constructor(zend_class_entry * ce)127 static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
128 {
129 	zend_class_entry *parent = ce->parent;
130 
131 	ZEND_ASSERT(parent != NULL);
132 
133 	/* You cannot change create_object */
134 	ce->create_object = parent->create_object;
135 
136 	/* Inherit special functions if needed */
137 	if (EXPECTED(!ce->get_iterator)) {
138 		ce->get_iterator = parent->get_iterator;
139 	}
140 	if (EXPECTED(!ce->__get)) {
141 		ce->__get = parent->__get;
142 	}
143 	if (EXPECTED(!ce->__set)) {
144 		ce->__set = parent->__set;
145 	}
146 	if (EXPECTED(!ce->__unset)) {
147 		ce->__unset = parent->__unset;
148 	}
149 	if (EXPECTED(!ce->__isset)) {
150 		ce->__isset = parent->__isset;
151 	}
152 	if (EXPECTED(!ce->__call)) {
153 		ce->__call = parent->__call;
154 	}
155 	if (EXPECTED(!ce->__callstatic)) {
156 		ce->__callstatic = parent->__callstatic;
157 	}
158 	if (EXPECTED(!ce->__tostring)) {
159 		ce->__tostring = parent->__tostring;
160 	}
161 	if (EXPECTED(!ce->clone)) {
162 		ce->clone = parent->clone;
163 	}
164 	if (EXPECTED(!ce->__serialize)) {
165 		ce->__serialize = parent->__serialize;
166 	}
167 	if (EXPECTED(!ce->__unserialize)) {
168 		ce->__unserialize = parent->__unserialize;
169 	}
170 	if (EXPECTED(!ce->serialize)) {
171 		ce->serialize = parent->serialize;
172 	}
173 	if (EXPECTED(!ce->unserialize)) {
174 		ce->unserialize = parent->unserialize;
175 	}
176 	if (!ce->destructor) {
177 		ce->destructor = parent->destructor;
178 	}
179 	if (EXPECTED(!ce->__debugInfo)) {
180 		ce->__debugInfo = parent->__debugInfo;
181 	}
182 
183 	if (ce->constructor) {
184 		if (parent->constructor && UNEXPECTED(parent->constructor->common.fn_flags & ZEND_ACC_FINAL)) {
185 			zend_error_noreturn(E_ERROR, "Cannot override final %s::%s() with %s::%s()",
186 				ZSTR_VAL(parent->name), ZSTR_VAL(parent->constructor->common.function_name),
187 				ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
188 		}
189 		return;
190 	}
191 
192 	ce->constructor = parent->constructor;
193 }
194 /* }}} */
195 
zend_visibility_string(uint32_t fn_flags)196 char *zend_visibility_string(uint32_t fn_flags) /* {{{ */
197 {
198 	if (fn_flags & ZEND_ACC_PUBLIC) {
199 		return "public";
200 	} else if (fn_flags & ZEND_ACC_PRIVATE) {
201 		return "private";
202 	} else {
203 		ZEND_ASSERT(fn_flags & ZEND_ACC_PROTECTED);
204 		return "protected";
205 	}
206 }
207 /* }}} */
208 
resolve_class_name(zend_class_entry * scope,zend_string * name)209 static zend_string *resolve_class_name(zend_class_entry *scope, zend_string *name) {
210 	ZEND_ASSERT(scope);
211 	if (zend_string_equals_literal_ci(name, "parent") && scope->parent) {
212 		if (scope->ce_flags & ZEND_ACC_RESOLVED_PARENT) {
213 			return scope->parent->name;
214 		} else {
215 			return scope->parent_name;
216 		}
217 	} else if (zend_string_equals_literal_ci(name, "self")) {
218 		return scope->name;
219 	} else {
220 		return name;
221 	}
222 }
223 
class_visible(zend_class_entry * ce)224 static bool class_visible(zend_class_entry *ce) {
225 	if (ce->type == ZEND_INTERNAL_CLASS) {
226 		return !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES);
227 	} else {
228 		ZEND_ASSERT(ce->type == ZEND_USER_CLASS);
229 		return !(CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES)
230 			|| ce->info.user.filename == CG(compiled_filename);
231 	}
232 }
233 
register_unresolved_class(zend_string * name)234 static zend_always_inline void register_unresolved_class(zend_string *name) {
235 	/* We'll autoload this class and process delayed variance obligations later. */
236 	if (!CG(delayed_autoloads)) {
237 		ALLOC_HASHTABLE(CG(delayed_autoloads));
238 		zend_hash_init(CG(delayed_autoloads), 0, NULL, NULL, 0);
239 	}
240 	zend_hash_add_empty_element(CG(delayed_autoloads), name);
241 }
242 
lookup_class_ex(zend_class_entry * scope,zend_string * name,bool register_unresolved)243 static zend_class_entry *lookup_class_ex(
244 		zend_class_entry *scope, zend_string *name, bool register_unresolved) {
245 	zend_class_entry *ce;
246 	bool in_preload = CG(compiler_options) & ZEND_COMPILE_PRELOAD;
247 
248 	if (UNEXPECTED(!EG(active) && !in_preload)) {
249 		zend_string *lc_name = zend_string_tolower(name);
250 
251 		ce = zend_hash_find_ptr(CG(class_table), lc_name);
252 
253 		zend_string_release(lc_name);
254 
255 		if (register_unresolved && !ce) {
256 			zend_error_noreturn(
257 				E_COMPILE_ERROR, "%s must be registered before %s",
258 				ZSTR_VAL(name), ZSTR_VAL(scope->name));
259 	    }
260 
261 		return ce;
262 	}
263 
264 	ce = zend_lookup_class_ex(
265 	    name, NULL, ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD);
266 
267 	if (!CG(in_compilation) || in_preload) {
268 		if (ce) {
269 			return ce;
270 		}
271 
272 		if (register_unresolved) {
273 			register_unresolved_class(name);
274 		}
275 	} else {
276 		if (ce && class_visible(ce)) {
277 			return ce;
278 		}
279 
280 		/* The current class may not be registered yet, so check for it explicitly. */
281 		if (zend_string_equals_ci(scope->name, name)) {
282 			return scope;
283 		}
284 	}
285 
286 	return NULL;
287 }
288 
lookup_class(zend_class_entry * scope,zend_string * name)289 static zend_class_entry *lookup_class(zend_class_entry *scope, zend_string *name) {
290 	return lookup_class_ex(scope, name, /* register_unresolved */ false);
291 }
292 
293 /* Instanceof that's safe to use on unlinked classes. */
unlinked_instanceof(zend_class_entry * ce1,zend_class_entry * ce2)294 static bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce2) {
295 	if (ce1 == ce2) {
296 		return 1;
297 	}
298 
299 	if (ce1->ce_flags & ZEND_ACC_LINKED) {
300 		return instanceof_function(ce1, ce2);
301 	}
302 
303 	if (ce1->parent) {
304 		zend_class_entry *parent_ce;
305 		if (ce1->ce_flags & ZEND_ACC_RESOLVED_PARENT) {
306 			parent_ce = ce1->parent;
307 		} else {
308 			parent_ce = zend_lookup_class_ex(ce1->parent_name, NULL,
309 				ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD);
310 		}
311 
312 		/* It's not sufficient to only check the parent chain itself, as need to do a full
313 		 * recursive instanceof in case the parent interfaces haven't been copied yet. */
314 		if (parent_ce && unlinked_instanceof(parent_ce, ce2)) {
315 			return 1;
316 		}
317 	}
318 
319 	if (ce1->num_interfaces) {
320 		uint32_t i;
321 		if (ce1->ce_flags & ZEND_ACC_RESOLVED_INTERFACES) {
322 			/* Unlike the normal instanceof_function(), we have to perform a recursive
323 			 * check here, as the parent interfaces might not have been fully copied yet. */
324 			for (i = 0; i < ce1->num_interfaces; i++) {
325 				if (unlinked_instanceof(ce1->interfaces[i], ce2)) {
326 					return 1;
327 				}
328 			}
329 		} else {
330 			for (i = 0; i < ce1->num_interfaces; i++) {
331 				zend_class_entry *ce = zend_lookup_class_ex(
332 					ce1->interface_names[i].name, ce1->interface_names[i].lc_name,
333 					ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD);
334 				/* Avoid recursing if class implements itself. */
335 				if (ce && ce != ce1 && unlinked_instanceof(ce, ce2)) {
336 					return 1;
337 				}
338 			}
339 		}
340 	}
341 
342 	return 0;
343 }
344 
zend_type_permits_self(zend_type type,zend_class_entry * scope,zend_class_entry * self)345 static bool zend_type_permits_self(
346 		zend_type type, zend_class_entry *scope, zend_class_entry *self) {
347 	if (ZEND_TYPE_FULL_MASK(type) & MAY_BE_OBJECT) {
348 		return 1;
349 	}
350 
351 	/* Any types that may satisfy self must have already been loaded at this point
352 	 * (as a parent or interface), so we never need to register delayed variance obligations
353 	 * for this case. */
354 	zend_type *single_type;
355 	ZEND_TYPE_FOREACH(type, single_type) {
356 		if (ZEND_TYPE_HAS_NAME(*single_type)) {
357 			zend_string *name = resolve_class_name(scope, ZEND_TYPE_NAME(*single_type));
358 			zend_class_entry *ce = lookup_class(self, name);
359 			if (ce && unlinked_instanceof(self, ce)) {
360 				return 1;
361 			}
362 		}
363 	} ZEND_TYPE_FOREACH_END();
364 	return 0;
365 }
366 
track_class_dependency(zend_class_entry * ce,zend_string * class_name)367 static void track_class_dependency(zend_class_entry *ce, zend_string *class_name)
368 {
369 	HashTable *ht;
370 
371 	ZEND_ASSERT(class_name);
372 	if (!CG(current_linking_class) || ce == CG(current_linking_class)) {
373 		return;
374 	} else if (zend_string_equals_literal_ci(class_name, "self")
375 	        || zend_string_equals_literal_ci(class_name, "parent")) {
376 		return;
377 	}
378 
379 #ifndef ZEND_WIN32
380 	/* On non-Windows systems, internal classes are always the same,
381 	 * so there is no need to explicitly track them. */
382 	if (ce->type == ZEND_INTERNAL_CLASS) {
383 		return;
384 	}
385 #endif
386 
387 	ht = (HashTable*)CG(current_linking_class)->inheritance_cache;
388 
389 	if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
390 		// TODO: dependency on not-immutable class ???
391 		if (ht) {
392 			zend_hash_destroy(ht);
393 			FREE_HASHTABLE(ht);
394 			CG(current_linking_class)->inheritance_cache = NULL;
395 		}
396 		CG(current_linking_class)->ce_flags &= ~ZEND_ACC_CACHEABLE;
397 		CG(current_linking_class) = NULL;
398 		return;
399 	}
400 
401 	/* Record dependency */
402 	if (!ht) {
403 		ALLOC_HASHTABLE(ht);
404 		zend_hash_init(ht, 0, NULL, NULL, 0);
405 		CG(current_linking_class)->inheritance_cache = (zend_inheritance_cache_entry*)ht;
406 	}
407 	zend_hash_add_ptr(ht, class_name, ce);
408 }
409 
410 /* Check whether any type in the fe_type intersection type is a subtype of the proto class. */
zend_is_intersection_subtype_of_class(zend_class_entry * fe_scope,zend_type fe_type,zend_class_entry * proto_scope,zend_string * proto_class_name,zend_class_entry * proto_ce)411 static inheritance_status zend_is_intersection_subtype_of_class(
412 		zend_class_entry *fe_scope, zend_type fe_type,
413 		zend_class_entry *proto_scope, zend_string *proto_class_name, zend_class_entry *proto_ce)
414 {
415 	ZEND_ASSERT(ZEND_TYPE_IS_INTERSECTION(fe_type));
416 	bool have_unresolved = false;
417 	zend_type *single_type;
418 
419 	/* Traverse the list of child types and check that at least one is
420 	 * a subtype of the parent type being checked */
421 	ZEND_TYPE_FOREACH(fe_type, single_type) {
422 		zend_class_entry *fe_ce;
423 		zend_string *fe_class_name = NULL;
424 		if (ZEND_TYPE_HAS_NAME(*single_type)) {
425 			fe_class_name =
426 				resolve_class_name(fe_scope, ZEND_TYPE_NAME(*single_type));
427 			if (zend_string_equals_ci(fe_class_name, proto_class_name)) {
428 				return INHERITANCE_SUCCESS;
429 			}
430 
431 			if (!proto_ce) proto_ce = lookup_class(proto_scope, proto_class_name);
432 			fe_ce = lookup_class(fe_scope, fe_class_name);
433 		} else {
434 			/* standard type in an intersection type is impossible,
435 			 * because it would be a fatal compile error */
436 			ZEND_UNREACHABLE();
437 			continue;
438 		}
439 
440 		if (!fe_ce || !proto_ce) {
441 			have_unresolved = true;
442 			continue;
443 		}
444 		if (unlinked_instanceof(fe_ce, proto_ce)) {
445 			track_class_dependency(fe_ce, fe_class_name);
446 			track_class_dependency(proto_ce, proto_class_name);
447 			return INHERITANCE_SUCCESS;
448 		}
449 	} ZEND_TYPE_FOREACH_END();
450 
451 	return have_unresolved ? INHERITANCE_UNRESOLVED : INHERITANCE_ERROR;
452 }
453 
454 /* Check whether a single class proto type is a subtype of a potentially complex fe_type. */
zend_is_class_subtype_of_type(zend_class_entry * fe_scope,zend_string * fe_class_name,zend_class_entry * proto_scope,zend_type proto_type)455 static inheritance_status zend_is_class_subtype_of_type(
456 		zend_class_entry *fe_scope, zend_string *fe_class_name,
457 		zend_class_entry *proto_scope, zend_type proto_type) {
458 	zend_class_entry *fe_ce = NULL;
459 	bool have_unresolved = 0;
460 
461 	/* If the parent has 'object' as a return type, any class satisfies the co-variant check */
462 	if (ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_OBJECT) {
463 		/* Currently, any class name would be allowed here. We still perform a class lookup
464 		 * for forward-compatibility reasons, as we may have named types in the future that
465 		 * are not classes (such as typedefs). */
466 		if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name);
467 		if (!fe_ce) {
468 			have_unresolved = 1;
469 		} else {
470 			track_class_dependency(fe_ce, fe_class_name);
471 			return INHERITANCE_SUCCESS;
472 		}
473 	}
474 
475 	zend_type *single_type;
476 
477 	/* Traverse the list of parent types and check if the current child (FE)
478 	 * class is the subtype of at least one of them (union) or all of them (intersection). */
479 	bool is_intersection = ZEND_TYPE_IS_INTERSECTION(proto_type);
480 	ZEND_TYPE_FOREACH(proto_type, single_type) {
481 		if (ZEND_TYPE_IS_INTERSECTION(*single_type)) {
482 			inheritance_status subtype_status = zend_is_class_subtype_of_type(
483 				fe_scope, fe_class_name, proto_scope, *single_type);
484 
485 			switch (subtype_status) {
486 				case INHERITANCE_ERROR:
487 					if (is_intersection) {
488 						return INHERITANCE_ERROR;
489 					}
490 					continue;
491 				case INHERITANCE_UNRESOLVED:
492 					have_unresolved = 1;
493 					continue;
494 				case INHERITANCE_SUCCESS:
495 					if (!is_intersection) {
496 						return INHERITANCE_SUCCESS;
497 					}
498 					continue;
499 				EMPTY_SWITCH_DEFAULT_CASE();
500 			}
501 		}
502 
503 		zend_class_entry *proto_ce;
504 		zend_string *proto_class_name = NULL;
505 		if (ZEND_TYPE_HAS_NAME(*single_type)) {
506 			proto_class_name =
507 				resolve_class_name(proto_scope, ZEND_TYPE_NAME(*single_type));
508 			if (zend_string_equals_ci(fe_class_name, proto_class_name)) {
509 				if (!is_intersection) {
510 					return INHERITANCE_SUCCESS;
511 				}
512 				continue;
513 			}
514 
515 			if (!fe_ce) fe_ce = lookup_class(fe_scope, fe_class_name);
516 			proto_ce = lookup_class(proto_scope, proto_class_name);
517 		} else {
518 			/* standard type */
519 			ZEND_ASSERT(!is_intersection);
520 			continue;
521 		}
522 
523 		if (!fe_ce || !proto_ce) {
524 			have_unresolved = 1;
525 			continue;
526 		}
527 		if (unlinked_instanceof(fe_ce, proto_ce)) {
528 			track_class_dependency(fe_ce, fe_class_name);
529 			track_class_dependency(proto_ce, proto_class_name);
530 			if (!is_intersection) {
531 				return INHERITANCE_SUCCESS;
532 			}
533 		} else {
534 			if (is_intersection) {
535 				return INHERITANCE_ERROR;
536 			}
537 		}
538 	} ZEND_TYPE_FOREACH_END();
539 
540 	if (have_unresolved) {
541 		return INHERITANCE_UNRESOLVED;
542 	}
543 	return is_intersection ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
544 }
545 
get_class_from_type(zend_class_entry * scope,zend_type single_type)546 static zend_string *get_class_from_type(zend_class_entry *scope, zend_type single_type) {
547 	if (ZEND_TYPE_HAS_NAME(single_type)) {
548 		return resolve_class_name(scope, ZEND_TYPE_NAME(single_type));
549 	}
550 	return NULL;
551 }
552 
register_unresolved_classes(zend_class_entry * scope,zend_type type)553 static void register_unresolved_classes(zend_class_entry *scope, zend_type type) {
554 	zend_type *single_type;
555 	ZEND_TYPE_FOREACH(type, single_type) {
556 		if (ZEND_TYPE_HAS_LIST(*single_type)) {
557 			register_unresolved_classes(scope, *single_type);
558 			continue;
559 		}
560 		if (ZEND_TYPE_HAS_NAME(*single_type)) {
561 			zend_string *class_name = resolve_class_name(scope, ZEND_TYPE_NAME(*single_type));
562 			lookup_class_ex(scope, class_name, /* register_unresolved */ true);
563 		}
564 	} ZEND_TYPE_FOREACH_END();
565 }
566 
zend_is_intersection_subtype_of_type(zend_class_entry * fe_scope,zend_type fe_type,zend_class_entry * proto_scope,zend_type proto_type)567 static inheritance_status zend_is_intersection_subtype_of_type(
568 	zend_class_entry *fe_scope, zend_type fe_type,
569 	zend_class_entry *proto_scope, zend_type proto_type)
570 {
571 	bool have_unresolved = false;
572 	zend_type *single_type;
573 	uint32_t proto_type_mask = ZEND_TYPE_PURE_MASK(proto_type);
574 
575 	/* Currently, for object type any class name would be allowed here.
576 	 * We still perform a class lookup for forward-compatibility reasons,
577 	 * as we may have named types in the future that are not classes
578 	 * (such as typedefs). */
579 	if (proto_type_mask & MAY_BE_OBJECT) {
580 		ZEND_TYPE_FOREACH(fe_type, single_type) {
581 			zend_string *fe_class_name = get_class_from_type(fe_scope, *single_type);
582 			if (!fe_class_name) {
583 				continue;
584 			}
585 			zend_class_entry *fe_ce = lookup_class(fe_scope, fe_class_name);
586 			if (fe_ce) {
587 				track_class_dependency(fe_ce, fe_class_name);
588 				return INHERITANCE_SUCCESS;
589 			} else {
590 				have_unresolved = true;
591 			}
592 		} ZEND_TYPE_FOREACH_END();
593 	}
594 
595 	/* U_1&...&U_n < V_1&...&V_m if forall V_j. exists U_i. U_i < V_j.
596 	 * U_1&...&U_n < V_1|...|V_m if exists V_j. exists U_i. U_i < V_j.
597 	 * As such, we need to iterate over proto_type (V_j) first and use a different
598 	 * quantifier depending on whether fe_type is a union or an intersection. */
599 	inheritance_status early_exit_status =
600 		ZEND_TYPE_IS_INTERSECTION(proto_type) ? INHERITANCE_ERROR : INHERITANCE_SUCCESS;
601 	ZEND_TYPE_FOREACH(proto_type, single_type) {
602 		inheritance_status status;
603 
604 		if (ZEND_TYPE_IS_INTERSECTION(*single_type)) {
605 			status = zend_is_intersection_subtype_of_type(
606 				fe_scope, fe_type, proto_scope, *single_type);
607 		} else {
608 			zend_string *proto_class_name = get_class_from_type(proto_scope, *single_type);
609 			if (!proto_class_name) {
610 				continue;
611 			}
612 
613 			zend_class_entry *proto_ce = NULL;
614 			status = zend_is_intersection_subtype_of_class(
615 				fe_scope, fe_type, proto_scope, proto_class_name, proto_ce);
616 		}
617 
618 		if (status == early_exit_status) {
619 			return status;
620 		}
621 		if (status == INHERITANCE_UNRESOLVED) {
622 			have_unresolved = true;
623 		}
624 	} ZEND_TYPE_FOREACH_END();
625 
626 	if (have_unresolved) {
627 		return INHERITANCE_UNRESOLVED;
628 	}
629 
630 	return early_exit_status == INHERITANCE_ERROR ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
631 }
632 
zend_perform_covariant_type_check(zend_class_entry * fe_scope,zend_type fe_type,zend_class_entry * proto_scope,zend_type proto_type)633 static inheritance_status zend_perform_covariant_type_check(
634 		zend_class_entry *fe_scope, zend_type fe_type,
635 		zend_class_entry *proto_scope, zend_type proto_type)
636 {
637 	ZEND_ASSERT(ZEND_TYPE_IS_SET(fe_type) && ZEND_TYPE_IS_SET(proto_type));
638 
639 	/* Apart from void, everything is trivially covariant to the mixed type.
640 	 * Handle this case separately to ensure it never requires class loading. */
641 	if (ZEND_TYPE_PURE_MASK(proto_type) == MAY_BE_ANY &&
642 			!ZEND_TYPE_CONTAINS_CODE(fe_type, IS_VOID)) {
643 		return INHERITANCE_SUCCESS;
644 	}
645 
646 	/* Builtin types may be removed, but not added */
647 	uint32_t fe_type_mask = ZEND_TYPE_PURE_MASK(fe_type);
648 	uint32_t proto_type_mask = ZEND_TYPE_PURE_MASK(proto_type);
649 	uint32_t added_types = fe_type_mask & ~proto_type_mask;
650 	if (added_types) {
651 		if ((added_types & MAY_BE_STATIC)
652 				&& zend_type_permits_self(proto_type, proto_scope, fe_scope)) {
653 			/* Replacing type that accepts self with static is okay */
654 			added_types &= ~MAY_BE_STATIC;
655 		}
656 
657 		if (added_types == MAY_BE_NEVER) {
658 			/* never is the bottom type */
659 			return INHERITANCE_SUCCESS;
660 		}
661 
662 		if (added_types) {
663 			/* Otherwise adding new types is illegal */
664 			return INHERITANCE_ERROR;
665 		}
666 	}
667 
668 	zend_type *single_type;
669 	inheritance_status early_exit_status;
670 	bool have_unresolved = false;
671 
672 	if (ZEND_TYPE_IS_INTERSECTION(fe_type)) {
673 		early_exit_status =
674 			ZEND_TYPE_IS_INTERSECTION(proto_type) ? INHERITANCE_ERROR : INHERITANCE_SUCCESS;
675 		inheritance_status status = zend_is_intersection_subtype_of_type(
676 			fe_scope, fe_type, proto_scope, proto_type);
677 
678 		if (status == early_exit_status) {
679 			return status;
680 		}
681 		if (status == INHERITANCE_UNRESOLVED) {
682 			have_unresolved = true;
683 		}
684 	} else {
685 		/* U_1|...|U_n < V_1|...|V_m if forall U_i. exists V_j. U_i < V_j.
686 		 * U_1|...|U_n < V_1&...&V_m if forall U_i. forall V_j. U_i < V_j.
687 		 * We need to iterate over fe_type (U_i) first and the logic is independent of
688 		 * whether proto_type is a union or intersection (only the inner check differs). */
689 		early_exit_status = INHERITANCE_ERROR;
690 		ZEND_TYPE_FOREACH(fe_type, single_type) {
691 			inheritance_status status;
692 			/* Union has an intersection type as it's member */
693 			if (ZEND_TYPE_IS_INTERSECTION(*single_type)) {
694 				status = zend_is_intersection_subtype_of_type(
695 					fe_scope, *single_type, proto_scope, proto_type);
696 			} else {
697 				zend_string *fe_class_name = get_class_from_type(fe_scope, *single_type);
698 				if (!fe_class_name) {
699 					continue;
700 				}
701 
702 				status = zend_is_class_subtype_of_type(
703 					fe_scope, fe_class_name, proto_scope, proto_type);
704 			}
705 
706 			if (status == early_exit_status) {
707 				return status;
708 			}
709 			if (status == INHERITANCE_UNRESOLVED) {
710 				have_unresolved = true;
711 			}
712 		} ZEND_TYPE_FOREACH_END();
713 	}
714 
715 	if (!have_unresolved) {
716 		return early_exit_status == INHERITANCE_ERROR ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
717 	}
718 
719 	register_unresolved_classes(fe_scope, fe_type);
720 	register_unresolved_classes(proto_scope, proto_type);
721 	return INHERITANCE_UNRESOLVED;
722 }
723 
zend_do_perform_arg_type_hint_check(zend_class_entry * fe_scope,zend_arg_info * fe_arg_info,zend_class_entry * proto_scope,zend_arg_info * proto_arg_info)724 static inheritance_status zend_do_perform_arg_type_hint_check(
725 		zend_class_entry *fe_scope, zend_arg_info *fe_arg_info,
726 		zend_class_entry *proto_scope, zend_arg_info *proto_arg_info) /* {{{ */
727 {
728 	if (!ZEND_TYPE_IS_SET(fe_arg_info->type) || ZEND_TYPE_PURE_MASK(fe_arg_info->type) == MAY_BE_ANY) {
729 		/* Child with no type or mixed type is always compatible */
730 		return INHERITANCE_SUCCESS;
731 	}
732 
733 	if (!ZEND_TYPE_IS_SET(proto_arg_info->type)) {
734 		/* Child defines a type, but parent doesn't, violates LSP */
735 		return INHERITANCE_ERROR;
736 	}
737 
738 	/* Contravariant type check is performed as a covariant type check with swapped
739 	 * argument order. */
740 	return zend_perform_covariant_type_check(
741 		proto_scope, proto_arg_info->type, fe_scope, fe_arg_info->type);
742 }
743 /* }}} */
744 
745 /* For trait methods, fe_scope/proto_scope may differ from fe/proto->common.scope,
746  * as self will refer to the self of the class the trait is used in, not the trait
747  * the method was declared in. */
zend_do_perform_implementation_check(const zend_function * fe,zend_class_entry * fe_scope,const zend_function * proto,zend_class_entry * proto_scope)748 static inheritance_status zend_do_perform_implementation_check(
749 		const zend_function *fe, zend_class_entry *fe_scope,
750 		const zend_function *proto, zend_class_entry *proto_scope) /* {{{ */
751 {
752 	uint32_t i, num_args, proto_num_args, fe_num_args;
753 	inheritance_status status, local_status;
754 	bool proto_is_variadic, fe_is_variadic;
755 
756 	/* Checks for constructors only if they are declared in an interface,
757 	 * or explicitly marked as abstract
758 	 */
759 	ZEND_ASSERT(!((fe->common.fn_flags & ZEND_ACC_CTOR)
760 		&& ((proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
761 			&& (proto->common.fn_flags & ZEND_ACC_ABSTRACT) == 0)));
762 
763 	/* If the prototype method is private and not abstract, we do not enforce a signature.
764 	 * private abstract methods can only occur in traits. */
765 	ZEND_ASSERT(!(proto->common.fn_flags & ZEND_ACC_PRIVATE)
766 			|| (proto->common.fn_flags & ZEND_ACC_ABSTRACT));
767 
768 	/* The number of required arguments cannot increase. */
769 	if (proto->common.required_num_args < fe->common.required_num_args) {
770 		return INHERITANCE_ERROR;
771 	}
772 
773 	/* by-ref constraints on return values are covariant */
774 	if ((proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
775 		&& !(fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
776 		return INHERITANCE_ERROR;
777 	}
778 
779 	proto_is_variadic = (proto->common.fn_flags & ZEND_ACC_VARIADIC) != 0;
780 	fe_is_variadic = (fe->common.fn_flags & ZEND_ACC_VARIADIC) != 0;
781 
782 	/* A variadic function cannot become non-variadic */
783 	if (proto_is_variadic && !fe_is_variadic) {
784 		return INHERITANCE_ERROR;
785 	}
786 
787 	/* The variadic argument is not included in the stored argument count. */
788 	proto_num_args = proto->common.num_args + proto_is_variadic;
789 	fe_num_args = fe->common.num_args + fe_is_variadic;
790 	num_args = MAX(proto_num_args, fe_num_args);
791 
792 	status = INHERITANCE_SUCCESS;
793 	for (i = 0; i < num_args; i++) {
794 		zend_arg_info *proto_arg_info =
795 			i < proto_num_args ? &proto->common.arg_info[i] :
796 			proto_is_variadic ? &proto->common.arg_info[proto_num_args - 1] : NULL;
797 		zend_arg_info *fe_arg_info =
798 			i < fe_num_args ? &fe->common.arg_info[i] :
799 			fe_is_variadic ? &fe->common.arg_info[fe_num_args - 1] : NULL;
800 		if (!proto_arg_info) {
801 			/* A new (optional) argument has been added, which is fine. */
802 			continue;
803 		}
804 		if (!fe_arg_info) {
805 			/* An argument has been removed. This is considered illegal, because arity checks
806 			 * work based on a model where passing more than the declared number of parameters
807 			 * to a function is an error. */
808 			return INHERITANCE_ERROR;
809 		}
810 
811 		local_status = zend_do_perform_arg_type_hint_check(
812 			fe_scope, fe_arg_info, proto_scope, proto_arg_info);
813 
814 		if (UNEXPECTED(local_status != INHERITANCE_SUCCESS)) {
815 			if (UNEXPECTED(local_status == INHERITANCE_ERROR)) {
816 				return INHERITANCE_ERROR;
817 			}
818 			ZEND_ASSERT(local_status == INHERITANCE_UNRESOLVED);
819 			status = INHERITANCE_UNRESOLVED;
820 		}
821 
822 		/* by-ref constraints on arguments are invariant */
823 		if (ZEND_ARG_SEND_MODE(fe_arg_info) != ZEND_ARG_SEND_MODE(proto_arg_info)) {
824 			return INHERITANCE_ERROR;
825 		}
826 	}
827 
828 	/* Check return type compatibility, but only if the prototype already specifies
829 	 * a return type. Adding a new return type is always valid. */
830 	if (proto->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
831 		/* Removing a return type is not valid, unless the parent return type is tentative. */
832 		if (!(fe->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
833 			if (!ZEND_ARG_TYPE_IS_TENTATIVE(&proto->common.arg_info[-1])) {
834 				return INHERITANCE_ERROR;
835 			}
836 			if (status == INHERITANCE_SUCCESS) {
837 				return INHERITANCE_WARNING;
838 			}
839 			return status;
840 		}
841 
842 		local_status = zend_perform_covariant_type_check(
843 			fe_scope, fe->common.arg_info[-1].type, proto_scope, proto->common.arg_info[-1].type);
844 
845 		if (UNEXPECTED(local_status != INHERITANCE_SUCCESS)) {
846 			if (local_status == INHERITANCE_ERROR
847 					&& ZEND_ARG_TYPE_IS_TENTATIVE(&proto->common.arg_info[-1])) {
848 				local_status = INHERITANCE_WARNING;
849 			}
850 			return local_status;
851 		}
852 	}
853 
854 	return status;
855 }
856 /* }}} */
857 
zend_append_type_hint(smart_str * str,zend_class_entry * scope,zend_arg_info * arg_info,bool return_hint)858 static ZEND_COLD void zend_append_type_hint(
859 		smart_str *str, zend_class_entry *scope, zend_arg_info *arg_info, bool return_hint) /* {{{ */
860 {
861 	if (ZEND_TYPE_IS_SET(arg_info->type)) {
862 		zend_string *type_str = zend_type_to_string_resolved(arg_info->type, scope);
863 		smart_str_append(str, type_str);
864 		zend_string_release(type_str);
865 		if (!return_hint) {
866 			smart_str_appendc(str, ' ');
867 		}
868 	}
869 }
870 /* }}} */
871 
zend_get_function_declaration(const zend_function * fptr,zend_class_entry * scope)872 static ZEND_COLD zend_string *zend_get_function_declaration(
873 		const zend_function *fptr, zend_class_entry *scope) /* {{{ */
874 {
875 	smart_str str = {0};
876 
877 	if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
878 		smart_str_appends(&str, "& ");
879 	}
880 
881 	if (fptr->common.scope) {
882 		if (fptr->common.scope->ce_flags & ZEND_ACC_ANON_CLASS) {
883 			/* cut off on NULL byte ... class@anonymous */
884 			smart_str_appends(&str, ZSTR_VAL(fptr->common.scope->name));
885 		} else {
886 			smart_str_appendl(&str, ZSTR_VAL(fptr->common.scope->name), ZSTR_LEN(fptr->common.scope->name));
887 		}
888 		smart_str_appends(&str, "::");
889 	}
890 
891 	smart_str_append(&str, fptr->common.function_name);
892 	smart_str_appendc(&str, '(');
893 
894 	if (fptr->common.arg_info) {
895 		uint32_t i, num_args, required;
896 		zend_arg_info *arg_info = fptr->common.arg_info;
897 
898 		required = fptr->common.required_num_args;
899 		num_args = fptr->common.num_args;
900 		if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
901 			num_args++;
902 		}
903 		for (i = 0; i < num_args;) {
904 			zend_append_type_hint(&str, scope, arg_info, 0);
905 
906 			if (ZEND_ARG_SEND_MODE(arg_info)) {
907 				smart_str_appendc(&str, '&');
908 			}
909 
910 			if (ZEND_ARG_IS_VARIADIC(arg_info)) {
911 				smart_str_appends(&str, "...");
912 			}
913 
914 			smart_str_appendc(&str, '$');
915 			if (fptr->type == ZEND_INTERNAL_FUNCTION) {
916 				smart_str_appends(&str, ((zend_internal_arg_info*)arg_info)->name);
917 			} else {
918 				smart_str_appendl(&str, ZSTR_VAL(arg_info->name), ZSTR_LEN(arg_info->name));
919 			}
920 
921 			if (i >= required && !ZEND_ARG_IS_VARIADIC(arg_info)) {
922 				smart_str_appends(&str, " = ");
923 
924 				if (fptr->type == ZEND_INTERNAL_FUNCTION) {
925 					if (((zend_internal_arg_info*)arg_info)->default_value) {
926 						smart_str_appends(&str, ((zend_internal_arg_info*)arg_info)->default_value);
927 					} else {
928 						smart_str_appends(&str, "<default>");
929 					}
930 				} else {
931 					zend_op *precv = NULL;
932 					{
933 						uint32_t idx  = i;
934 						zend_op *op = fptr->op_array.opcodes;
935 						zend_op *end = op + fptr->op_array.last;
936 
937 						++idx;
938 						while (op < end) {
939 							if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
940 									&& op->op1.num == (zend_ulong)idx)
941 							{
942 								precv = op;
943 							}
944 							++op;
945 						}
946 					}
947 					if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
948 						zval *zv = RT_CONSTANT(precv, precv->op2);
949 
950 						if (Z_TYPE_P(zv) == IS_FALSE) {
951 							smart_str_appends(&str, "false");
952 						} else if (Z_TYPE_P(zv) == IS_TRUE) {
953 							smart_str_appends(&str, "true");
954 						} else if (Z_TYPE_P(zv) == IS_NULL) {
955 							smart_str_appends(&str, "null");
956 						} else if (Z_TYPE_P(zv) == IS_STRING) {
957 							smart_str_appendc(&str, '\'');
958 							smart_str_appendl(&str, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 10));
959 							if (Z_STRLEN_P(zv) > 10) {
960 								smart_str_appends(&str, "...");
961 							}
962 							smart_str_appendc(&str, '\'');
963 						} else if (Z_TYPE_P(zv) == IS_ARRAY) {
964 							if (zend_hash_num_elements(Z_ARRVAL_P(zv)) == 0) {
965 								smart_str_appends(&str, "[]");
966 							} else {
967 								smart_str_appends(&str, "[...]");
968 							}
969 						} else if (Z_TYPE_P(zv) == IS_CONSTANT_AST) {
970 							zend_ast *ast = Z_ASTVAL_P(zv);
971 							if (ast->kind == ZEND_AST_CONSTANT) {
972 								smart_str_append(&str, zend_ast_get_constant_name(ast));
973 							} else if (ast->kind == ZEND_AST_CLASS_CONST) {
974 								smart_str_append(&str, zend_ast_get_str(ast->child[0]));
975 								smart_str_appends(&str, "::");
976 								smart_str_append(&str, zend_ast_get_str(ast->child[1]));
977 							} else {
978 								smart_str_appends(&str, "<expression>");
979 							}
980 						} else {
981 							zend_string *tmp_zv_str;
982 							zend_string *zv_str = zval_get_tmp_string(zv, &tmp_zv_str);
983 							smart_str_append(&str, zv_str);
984 							zend_tmp_string_release(tmp_zv_str);
985 						}
986 					}
987 				}
988 			}
989 
990 			if (++i < num_args) {
991 				smart_str_appends(&str, ", ");
992 			}
993 			arg_info++;
994 		}
995 	}
996 
997 	smart_str_appendc(&str, ')');
998 
999 	if (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1000 		smart_str_appends(&str, ": ");
1001 		zend_append_type_hint(&str, scope, fptr->common.arg_info - 1, 1);
1002 	}
1003 	smart_str_0(&str);
1004 
1005 	return str.s;
1006 }
1007 /* }}} */
1008 
func_filename(const zend_function * fn)1009 static zend_always_inline zend_string *func_filename(const zend_function *fn) {
1010 	return fn->common.type == ZEND_USER_FUNCTION ? fn->op_array.filename : NULL;
1011 }
1012 
func_lineno(const zend_function * fn)1013 static zend_always_inline uint32_t func_lineno(const zend_function *fn) {
1014 	return fn->common.type == ZEND_USER_FUNCTION ? fn->op_array.line_start : 0;
1015 }
1016 
emit_incompatible_method_error(const zend_function * child,zend_class_entry * child_scope,const zend_function * parent,zend_class_entry * parent_scope,inheritance_status status)1017 static void ZEND_COLD emit_incompatible_method_error(
1018 		const zend_function *child, zend_class_entry *child_scope,
1019 		const zend_function *parent, zend_class_entry *parent_scope,
1020 		inheritance_status status) {
1021 	zend_string *parent_prototype = zend_get_function_declaration(parent, parent_scope);
1022 	zend_string *child_prototype = zend_get_function_declaration(child, child_scope);
1023 	if (status == INHERITANCE_UNRESOLVED) {
1024 		// TODO Improve error message if first unresolved class is present in child and parent?
1025 		/* Fetch the first unresolved class from registered autoloads */
1026 		zend_string *unresolved_class = NULL;
1027 		ZEND_HASH_MAP_FOREACH_STR_KEY(CG(delayed_autoloads), unresolved_class) {
1028 			break;
1029 		} ZEND_HASH_FOREACH_END();
1030 		ZEND_ASSERT(unresolved_class);
1031 
1032 		zend_error_at(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
1033 			"Could not check compatibility between %s and %s, because class %s is not available",
1034 			ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype), ZSTR_VAL(unresolved_class));
1035 	} else if (status == INHERITANCE_WARNING) {
1036 		zend_attribute *return_type_will_change_attribute = zend_get_attribute_str(
1037 			child->common.attributes,
1038 			"returntypewillchange",
1039 			sizeof("returntypewillchange")-1
1040 		);
1041 
1042 		if (!return_type_will_change_attribute) {
1043 			zend_error_at(E_DEPRECATED, func_filename(child), func_lineno(child),
1044 				"Return type of %s should either be compatible with %s, "
1045 				"or the #[\\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice",
1046 				ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype));
1047 			if (EG(exception)) {
1048 				zend_exception_uncaught_error(
1049 					"During inheritance of %s", ZSTR_VAL(parent_scope->name));
1050 			}
1051 		}
1052 	} else {
1053 		zend_error_at(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
1054 			"Declaration of %s must be compatible with %s",
1055 			ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype));
1056 	}
1057 	zend_string_efree(child_prototype);
1058 	zend_string_efree(parent_prototype);
1059 }
1060 
perform_delayable_implementation_check(zend_class_entry * ce,const zend_function * fe,zend_class_entry * fe_scope,const zend_function * proto,zend_class_entry * proto_scope)1061 static void perform_delayable_implementation_check(
1062 		zend_class_entry *ce,
1063 		const zend_function *fe, zend_class_entry *fe_scope,
1064 		const zend_function *proto, zend_class_entry *proto_scope)
1065 {
1066 	inheritance_status status =
1067 		zend_do_perform_implementation_check(fe, fe_scope, proto, proto_scope);
1068 	if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
1069 		if (EXPECTED(status == INHERITANCE_UNRESOLVED)) {
1070 			add_compatibility_obligation(ce, fe, fe_scope, proto, proto_scope);
1071 		} else {
1072 			ZEND_ASSERT(status == INHERITANCE_ERROR || status == INHERITANCE_WARNING);
1073 			emit_incompatible_method_error(fe, fe_scope, proto, proto_scope, status);
1074 		}
1075 	}
1076 }
1077 
1078 
1079 #define ZEND_INHERITANCE_LAZY_CHILD_CLONE     (1<<0)
1080 #define ZEND_INHERITANCE_CHECK_SILENT         (1<<1) /* don't throw errors */
1081 #define ZEND_INHERITANCE_CHECK_PROTO          (1<<2) /* check method prototype (it might be already checked before) */
1082 #define ZEND_INHERITANCE_CHECK_VISIBILITY     (1<<3)
1083 #define ZEND_INHERITANCE_SET_CHILD_CHANGED    (1<<4)
1084 #define ZEND_INHERITANCE_SET_CHILD_PROTO      (1<<5)
1085 
do_inheritance_check_on_method(zend_function * child,zend_class_entry * child_scope,zend_function * parent,zend_class_entry * parent_scope,zend_class_entry * ce,zval * child_zv,uint32_t flags)1086 static inheritance_status do_inheritance_check_on_method(
1087 		zend_function *child, zend_class_entry *child_scope,
1088 		zend_function *parent, zend_class_entry *parent_scope,
1089 		zend_class_entry *ce, zval *child_zv, uint32_t flags) /* {{{ */
1090 {
1091 	uint32_t child_flags;
1092 	uint32_t parent_flags = parent->common.fn_flags;
1093 	zend_function *proto;
1094 
1095 #define SEPARATE_METHOD() do { \
1096 			if ((flags & ZEND_INHERITANCE_LAZY_CHILD_CLONE) \
1097 			 && child_scope != ce && child->type == ZEND_USER_FUNCTION) { \
1098 				/* op_array wasn't duplicated yet */ \
1099 				zend_function *new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); \
1100 				memcpy(new_function, child, sizeof(zend_op_array)); \
1101 				Z_PTR_P(child_zv) = child = new_function; \
1102 				flags &= ~ZEND_INHERITANCE_LAZY_CHILD_CLONE; \
1103 			} \
1104 		} while(0)
1105 
1106 	if (UNEXPECTED((parent_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_ABSTRACT|ZEND_ACC_CTOR)) == ZEND_ACC_PRIVATE)) {
1107 		if (flags & ZEND_INHERITANCE_SET_CHILD_CHANGED) {
1108 			SEPARATE_METHOD();
1109 			child->common.fn_flags |= ZEND_ACC_CHANGED;
1110 		}
1111 		/* The parent method is private and not an abstract so we don't need to check any inheritance rules */
1112 		return INHERITANCE_SUCCESS;
1113 	}
1114 
1115 	if ((flags & ZEND_INHERITANCE_CHECK_PROTO) && UNEXPECTED(parent_flags & ZEND_ACC_FINAL)) {
1116 		if (flags & ZEND_INHERITANCE_CHECK_SILENT) {
1117 			return INHERITANCE_ERROR;
1118 		}
1119 		zend_error_at_noreturn(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
1120 			"Cannot override final method %s::%s()",
1121 			ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name));
1122 	}
1123 
1124 	child_flags	= child->common.fn_flags;
1125 	/* You cannot change from static to non static and vice versa.
1126 	 */
1127 	if ((flags & ZEND_INHERITANCE_CHECK_PROTO)
1128 	 && UNEXPECTED((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC))) {
1129 		if (flags & ZEND_INHERITANCE_CHECK_SILENT) {
1130 			return INHERITANCE_ERROR;
1131 		}
1132 		if (child_flags & ZEND_ACC_STATIC) {
1133 			zend_error_at_noreturn(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
1134 				"Cannot make non static method %s::%s() static in class %s",
1135 				ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
1136 		} else {
1137 			zend_error_at_noreturn(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
1138 				"Cannot make static method %s::%s() non static in class %s",
1139 				ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
1140 		}
1141 	}
1142 
1143 	/* Disallow making an inherited method abstract. */
1144 	if ((flags & ZEND_INHERITANCE_CHECK_PROTO)
1145 	 && UNEXPECTED((child_flags & ZEND_ACC_ABSTRACT) > (parent_flags & ZEND_ACC_ABSTRACT))) {
1146 		if (flags & ZEND_INHERITANCE_CHECK_SILENT) {
1147 			return INHERITANCE_ERROR;
1148 		}
1149 		zend_error_at_noreturn(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
1150 			"Cannot make non abstract method %s::%s() abstract in class %s",
1151 			ZEND_FN_SCOPE_NAME(parent), ZSTR_VAL(child->common.function_name), ZEND_FN_SCOPE_NAME(child));
1152 	}
1153 
1154 	if ((flags & ZEND_INHERITANCE_SET_CHILD_CHANGED)
1155 	 && (parent_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_CHANGED))) {
1156 		SEPARATE_METHOD();
1157 		child->common.fn_flags |= ZEND_ACC_CHANGED;
1158 	}
1159 
1160 	proto = parent->common.prototype ?
1161 		parent->common.prototype : parent;
1162 
1163 	if (parent_flags & ZEND_ACC_CTOR) {
1164 		/* ctors only have a prototype if is abstract (or comes from an interface) */
1165 		/* and if that is the case, we want to check inheritance against it */
1166 		if (!(proto->common.fn_flags & ZEND_ACC_ABSTRACT)) {
1167 			return INHERITANCE_SUCCESS;
1168 		}
1169 		parent = proto;
1170 	}
1171 
1172 	if ((flags & ZEND_INHERITANCE_SET_CHILD_PROTO)
1173 	 && child->common.prototype != proto) {
1174 		SEPARATE_METHOD();
1175 		child->common.prototype = proto;
1176 	}
1177 
1178 	/* Prevent derived classes from restricting access that was available in parent classes (except deriving from non-abstract ctors) */
1179 	if ((flags & ZEND_INHERITANCE_CHECK_VISIBILITY)
1180 			&& (child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
1181 		if (flags & ZEND_INHERITANCE_CHECK_SILENT) {
1182 			return INHERITANCE_ERROR;
1183 		}
1184 		zend_error_at_noreturn(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
1185 			"Access level to %s::%s() must be %s (as in class %s)%s",
1186 			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");
1187 	}
1188 
1189 	if (flags & ZEND_INHERITANCE_CHECK_PROTO) {
1190 		if (flags & ZEND_INHERITANCE_CHECK_SILENT) {
1191 			return zend_do_perform_implementation_check(child, child_scope, parent, parent_scope);
1192 		}
1193 		perform_delayable_implementation_check(ce, child, child_scope, parent, parent_scope);
1194 	}
1195 
1196 #undef SEPARATE_METHOD
1197 
1198 	return INHERITANCE_SUCCESS;
1199 }
1200 /* }}} */
1201 
do_inherit_method(zend_string * key,zend_function * parent,zend_class_entry * ce,bool is_interface,uint32_t flags)1202 static void do_inherit_method(zend_string *key, zend_function *parent, zend_class_entry *ce, bool is_interface, uint32_t flags) /* {{{ */
1203 {
1204 	zval *child = zend_hash_find_known_hash(&ce->function_table, key);
1205 
1206 	if (child) {
1207 		zend_function *func = (zend_function*)Z_PTR_P(child);
1208 
1209 		if (is_interface && UNEXPECTED(func == parent)) {
1210 			/* The same method in interface may be inherited few times */
1211 			return;
1212 		}
1213 
1214 		do_inheritance_check_on_method(
1215 			func, func->common.scope, parent, parent->common.scope, ce, child, flags);
1216 	} else {
1217 
1218 		if (is_interface || (parent->common.fn_flags & (ZEND_ACC_ABSTRACT))) {
1219 			ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
1220 		}
1221 
1222 		parent = zend_duplicate_function(parent, ce);
1223 
1224 		if (!is_interface) {
1225 			_zend_hash_append_ptr(&ce->function_table, key, parent);
1226 		} else {
1227 			zend_hash_add_new_ptr(&ce->function_table, key, parent);
1228 		}
1229 	}
1230 }
1231 /* }}} */
1232 
property_types_compatible(const zend_property_info * parent_info,const zend_property_info * child_info)1233 inheritance_status property_types_compatible(
1234 		const zend_property_info *parent_info, const zend_property_info *child_info) {
1235 	if (ZEND_TYPE_PURE_MASK(parent_info->type) == ZEND_TYPE_PURE_MASK(child_info->type)
1236 			&& ZEND_TYPE_NAME(parent_info->type) == ZEND_TYPE_NAME(child_info->type)) {
1237 		return INHERITANCE_SUCCESS;
1238 	}
1239 
1240 	if (ZEND_TYPE_IS_SET(parent_info->type) != ZEND_TYPE_IS_SET(child_info->type)) {
1241 		return INHERITANCE_ERROR;
1242 	}
1243 
1244 	/* Perform a covariant type check in both directions to determined invariance. */
1245 	inheritance_status status1 = zend_perform_covariant_type_check(
1246 		child_info->ce, child_info->type, parent_info->ce, parent_info->type);
1247 	inheritance_status status2 = zend_perform_covariant_type_check(
1248 		parent_info->ce, parent_info->type, child_info->ce, child_info->type);
1249 	if (status1 == INHERITANCE_SUCCESS && status2 == INHERITANCE_SUCCESS) {
1250 		return INHERITANCE_SUCCESS;
1251 	}
1252 	if (status1 == INHERITANCE_ERROR || status2 == INHERITANCE_ERROR) {
1253 		return INHERITANCE_ERROR;
1254 	}
1255 	ZEND_ASSERT(status1 == INHERITANCE_UNRESOLVED || status2 == INHERITANCE_UNRESOLVED);
1256 	return INHERITANCE_UNRESOLVED;
1257 }
1258 
emit_incompatible_property_error(const zend_property_info * child,const zend_property_info * parent)1259 static void emit_incompatible_property_error(
1260 		const zend_property_info *child, const zend_property_info *parent) {
1261 	zend_string *type_str = zend_type_to_string_resolved(parent->type, parent->ce);
1262 	zend_error_noreturn(E_COMPILE_ERROR,
1263 		"Type of %s::$%s must be %s (as in class %s)",
1264 		ZSTR_VAL(child->ce->name),
1265 		zend_get_unmangled_property_name(child->name),
1266 		ZSTR_VAL(type_str),
1267 		ZSTR_VAL(parent->ce->name));
1268 }
1269 
do_inherit_property(zend_property_info * parent_info,zend_string * key,zend_class_entry * ce)1270 static void do_inherit_property(zend_property_info *parent_info, zend_string *key, zend_class_entry *ce) /* {{{ */
1271 {
1272 	zval *child = zend_hash_find_known_hash(&ce->properties_info, key);
1273 	zend_property_info *child_info;
1274 
1275 	if (UNEXPECTED(child)) {
1276 		child_info = Z_PTR_P(child);
1277 		if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_CHANGED)) {
1278 			child_info->flags |= ZEND_ACC_CHANGED;
1279 		}
1280 		if (!(parent_info->flags & ZEND_ACC_PRIVATE)) {
1281 			if (UNEXPECTED((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC))) {
1282 				zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
1283 					(parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ZSTR_VAL(parent_info->ce->name), ZSTR_VAL(key),
1284 					(child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ZSTR_VAL(ce->name), ZSTR_VAL(key));
1285 			}
1286 			if (UNEXPECTED((child_info->flags & ZEND_ACC_READONLY) != (parent_info->flags & ZEND_ACC_READONLY))) {
1287 				zend_error_noreturn(E_COMPILE_ERROR,
1288 					"Cannot redeclare %s property %s::$%s as %s %s::$%s",
1289 					parent_info->flags & ZEND_ACC_READONLY ? "readonly" : "non-readonly",
1290 					ZSTR_VAL(parent_info->ce->name), ZSTR_VAL(key),
1291 					child_info->flags & ZEND_ACC_READONLY ? "readonly" : "non-readonly",
1292 					ZSTR_VAL(ce->name), ZSTR_VAL(key));
1293 			}
1294 
1295 			if (UNEXPECTED((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK))) {
1296 				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(parent_info->ce->name), (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
1297 			} else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
1298 				int parent_num = OBJ_PROP_TO_NUM(parent_info->offset);
1299 				int child_num = OBJ_PROP_TO_NUM(child_info->offset);
1300 
1301 				/* Don't keep default properties in GC (they may be freed by opcache) */
1302 				zval_ptr_dtor_nogc(&(ce->default_properties_table[parent_num]));
1303 				ce->default_properties_table[parent_num] = ce->default_properties_table[child_num];
1304 				ZVAL_UNDEF(&ce->default_properties_table[child_num]);
1305 				child_info->offset = parent_info->offset;
1306 			}
1307 
1308 			if (UNEXPECTED(ZEND_TYPE_IS_SET(parent_info->type))) {
1309 				inheritance_status status = property_types_compatible(parent_info, child_info);
1310 				if (status == INHERITANCE_ERROR) {
1311 					emit_incompatible_property_error(child_info, parent_info);
1312 				}
1313 				if (status == INHERITANCE_UNRESOLVED) {
1314 					add_property_compatibility_obligation(ce, child_info, parent_info);
1315 				}
1316 			} else if (UNEXPECTED(ZEND_TYPE_IS_SET(child_info->type) && !ZEND_TYPE_IS_SET(parent_info->type))) {
1317 				zend_error_noreturn(E_COMPILE_ERROR,
1318 						"Type of %s::$%s must not be defined (as in class %s)",
1319 						ZSTR_VAL(ce->name),
1320 						ZSTR_VAL(key),
1321 						ZSTR_VAL(parent_info->ce->name));
1322 			}
1323 		}
1324 	} else {
1325 		_zend_hash_append_ptr(&ce->properties_info, key, parent_info);
1326 	}
1327 }
1328 /* }}} */
1329 
do_implement_interface(zend_class_entry * ce,zend_class_entry * iface)1330 static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
1331 {
1332 	if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce) == FAILURE) {
1333 		zend_error_noreturn(E_CORE_ERROR, "%s %s could not implement interface %s", zend_get_object_type_uc(ce), ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
1334 	}
1335 	/* This should be prevented by the class lookup logic. */
1336 	ZEND_ASSERT(ce != iface);
1337 }
1338 /* }}} */
1339 
zend_do_inherit_interfaces(zend_class_entry * ce,const zend_class_entry * iface)1340 static void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface) /* {{{ */
1341 {
1342 	/* expects interface to be contained in ce's interface list already */
1343 	uint32_t i, ce_num, if_num = iface->num_interfaces;
1344 	zend_class_entry *entry;
1345 
1346 	ce_num = ce->num_interfaces;
1347 
1348 	if (ce->type == ZEND_INTERNAL_CLASS) {
1349 		ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
1350 	} else {
1351 		ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
1352 	}
1353 
1354 	/* Inherit the interfaces, only if they're not already inherited by the class */
1355 	while (if_num--) {
1356 		entry = iface->interfaces[if_num];
1357 		for (i = 0; i < ce_num; i++) {
1358 			if (ce->interfaces[i] == entry) {
1359 				break;
1360 			}
1361 		}
1362 		if (i == ce_num) {
1363 			ce->interfaces[ce->num_interfaces++] = entry;
1364 		}
1365 	}
1366 	ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES;
1367 
1368 	/* and now call the implementing handlers */
1369 	while (ce_num < ce->num_interfaces) {
1370 		do_implement_interface(ce, ce->interfaces[ce_num++]);
1371 	}
1372 }
1373 /* }}} */
1374 
do_inherit_class_constant(zend_string * name,zend_class_constant * parent_const,zend_class_entry * ce)1375 static void do_inherit_class_constant(zend_string *name, zend_class_constant *parent_const, zend_class_entry *ce) /* {{{ */
1376 {
1377 	zval *zv = zend_hash_find_known_hash(&ce->constants_table, name);
1378 	zend_class_constant *c;
1379 
1380 	if (zv != NULL) {
1381 		c = (zend_class_constant*)Z_PTR_P(zv);
1382 		if (UNEXPECTED((ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_PPP_MASK) > (ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PPP_MASK))) {
1383 			zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s must be %s (as in class %s)%s",
1384 				ZSTR_VAL(ce->name), ZSTR_VAL(name), zend_visibility_string(ZEND_CLASS_CONST_FLAGS(parent_const)), ZSTR_VAL(parent_const->ce->name), (ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PUBLIC) ? "" : " or weaker");
1385 		}
1386 
1387 		if (UNEXPECTED((ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_FINAL))) {
1388 			zend_error_noreturn(
1389 				E_COMPILE_ERROR, "%s::%s cannot override final constant %s::%s",
1390 				ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(parent_const->ce->name), ZSTR_VAL(name)
1391 			);
1392 		}
1393 	} else if (!(ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PRIVATE)) {
1394 		if (Z_TYPE(parent_const->value) == IS_CONSTANT_AST) {
1395 			ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
1396 			ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
1397 			if (ce->parent->ce_flags & ZEND_ACC_IMMUTABLE) {
1398 				c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
1399 				memcpy(c, parent_const, sizeof(zend_class_constant));
1400 				parent_const = c;
1401 				Z_CONSTANT_FLAGS(c->value) |= CONST_OWNED;
1402 			}
1403 		}
1404 		if (ce->type & ZEND_INTERNAL_CLASS) {
1405 			c = pemalloc(sizeof(zend_class_constant), 1);
1406 			memcpy(c, parent_const, sizeof(zend_class_constant));
1407 			parent_const = c;
1408 		}
1409 		_zend_hash_append_ptr(&ce->constants_table, name, parent_const);
1410 	}
1411 }
1412 /* }}} */
1413 
zend_build_properties_info_table(zend_class_entry * ce)1414 void zend_build_properties_info_table(zend_class_entry *ce)
1415 {
1416 	zend_property_info **table, *prop;
1417 	size_t size;
1418 	if (ce->default_properties_count == 0) {
1419 		return;
1420 	}
1421 
1422 	ZEND_ASSERT(ce->properties_info_table == NULL);
1423 	size = sizeof(zend_property_info *) * ce->default_properties_count;
1424 	if (ce->type == ZEND_USER_CLASS) {
1425 		ce->properties_info_table = table = zend_arena_alloc(&CG(arena), size);
1426 	} else {
1427 		ce->properties_info_table = table = pemalloc(size, 1);
1428 	}
1429 
1430 	/* Dead slots may be left behind during inheritance. Make sure these are NULLed out. */
1431 	memset(table, 0, size);
1432 
1433 	if (ce->parent && ce->parent->default_properties_count != 0) {
1434 		zend_property_info **parent_table = ce->parent->properties_info_table;
1435 		memcpy(
1436 			table, parent_table,
1437 			sizeof(zend_property_info *) * ce->parent->default_properties_count
1438 		);
1439 
1440 		/* Child did not add any new properties, we are done */
1441 		if (ce->default_properties_count == ce->parent->default_properties_count) {
1442 			return;
1443 		}
1444 	}
1445 
1446 	ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) {
1447 		if (prop->ce == ce && (prop->flags & ZEND_ACC_STATIC) == 0) {
1448 			table[OBJ_PROP_TO_NUM(prop->offset)] = prop;
1449 		}
1450 	} ZEND_HASH_FOREACH_END();
1451 }
1452 
zend_do_inheritance_ex(zend_class_entry * ce,zend_class_entry * parent_ce,bool checked)1453 ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *parent_ce, bool checked) /* {{{ */
1454 {
1455 	zend_property_info *property_info;
1456 	zend_function *func;
1457 	zend_string *key;
1458 
1459 	if (UNEXPECTED(ce->ce_flags & ZEND_ACC_INTERFACE)) {
1460 		/* Interface can only inherit other interfaces */
1461 		if (UNEXPECTED(!(parent_ce->ce_flags & ZEND_ACC_INTERFACE))) {
1462 			zend_error_noreturn(E_COMPILE_ERROR, "Interface %s cannot extend class %s", ZSTR_VAL(ce->name), ZSTR_VAL(parent_ce->name));
1463 		}
1464 	} else if (UNEXPECTED(parent_ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_FINAL))) {
1465 		/* Class must not extend a final class */
1466 		if (parent_ce->ce_flags & ZEND_ACC_FINAL) {
1467 			zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend final class %s", ZSTR_VAL(ce->name), ZSTR_VAL(parent_ce->name));
1468 		}
1469 
1470 		/* Class declaration must not extend traits or interfaces */
1471 		if ((parent_ce->ce_flags & ZEND_ACC_INTERFACE) || (parent_ce->ce_flags & ZEND_ACC_TRAIT)) {
1472 			zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend %s %s",
1473 				ZSTR_VAL(ce->name), parent_ce->ce_flags & ZEND_ACC_INTERFACE ? "interface" : "trait", ZSTR_VAL(parent_ce->name)
1474 			);
1475 		}
1476 	}
1477 
1478 	if (UNEXPECTED((ce->ce_flags & ZEND_ACC_READONLY_CLASS) != (parent_ce->ce_flags & ZEND_ACC_READONLY_CLASS))) {
1479 		zend_error_noreturn(E_COMPILE_ERROR, "%s class %s cannot extend %s class %s",
1480 			ce->ce_flags & ZEND_ACC_READONLY_CLASS ? "Readonly" : "Non-readonly", ZSTR_VAL(ce->name),
1481 			parent_ce->ce_flags & ZEND_ACC_READONLY_CLASS ? "readonly" : "non-readonly", ZSTR_VAL(parent_ce->name)
1482 		);
1483 	}
1484 
1485 	if (ce->parent_name) {
1486 		zend_string_release_ex(ce->parent_name, 0);
1487 	}
1488 	ce->parent = parent_ce;
1489 	ce->ce_flags |= ZEND_ACC_RESOLVED_PARENT;
1490 
1491 	/* Inherit properties */
1492 	if (parent_ce->default_properties_count) {
1493 		zval *src, *dst, *end;
1494 
1495 		if (ce->default_properties_count) {
1496 			zval *table = pemalloc(sizeof(zval) * (ce->default_properties_count + parent_ce->default_properties_count), ce->type == ZEND_INTERNAL_CLASS);
1497 			src = ce->default_properties_table + ce->default_properties_count;
1498 			end = table + parent_ce->default_properties_count;
1499 			dst = end + ce->default_properties_count;
1500 			ce->default_properties_table = table;
1501 			do {
1502 				dst--;
1503 				src--;
1504 				ZVAL_COPY_VALUE_PROP(dst, src);
1505 			} while (dst != end);
1506 			pefree(src, ce->type == ZEND_INTERNAL_CLASS);
1507 			end = ce->default_properties_table;
1508 		} else {
1509 			end = pemalloc(sizeof(zval) * parent_ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
1510 			dst = end + parent_ce->default_properties_count;
1511 			ce->default_properties_table = end;
1512 		}
1513 		src = parent_ce->default_properties_table + parent_ce->default_properties_count;
1514 		if (UNEXPECTED(parent_ce->type != ce->type)) {
1515 			/* User class extends internal */
1516 			do {
1517 				dst--;
1518 				src--;
1519 				ZVAL_COPY_OR_DUP_PROP(dst, src);
1520 				if (Z_OPT_TYPE_P(dst) == IS_CONSTANT_AST) {
1521 					ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
1522 					ce->ce_flags |= ZEND_ACC_HAS_AST_PROPERTIES;
1523 				}
1524 				continue;
1525 			} while (dst != end);
1526 		} else {
1527 			do {
1528 				dst--;
1529 				src--;
1530 				ZVAL_COPY_PROP(dst, src);
1531 				if (Z_OPT_TYPE_P(dst) == IS_CONSTANT_AST) {
1532 					ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
1533 					ce->ce_flags |= ZEND_ACC_HAS_AST_PROPERTIES;
1534 				}
1535 				continue;
1536 			} while (dst != end);
1537 		}
1538 		ce->default_properties_count += parent_ce->default_properties_count;
1539 	}
1540 
1541 	if (parent_ce->default_static_members_count) {
1542 		zval *src, *dst, *end;
1543 
1544 		if (ce->default_static_members_count) {
1545 			zval *table = pemalloc(sizeof(zval) * (ce->default_static_members_count + parent_ce->default_static_members_count), ce->type == ZEND_INTERNAL_CLASS);
1546 			src = ce->default_static_members_table + ce->default_static_members_count;
1547 			end = table + parent_ce->default_static_members_count;
1548 			dst = end + ce->default_static_members_count;
1549 			ce->default_static_members_table = table;
1550 			do {
1551 				dst--;
1552 				src--;
1553 				ZVAL_COPY_VALUE(dst, src);
1554 			} while (dst != end);
1555 			pefree(src, ce->type == ZEND_INTERNAL_CLASS);
1556 			end = ce->default_static_members_table;
1557 		} else {
1558 			end = pemalloc(sizeof(zval) * parent_ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
1559 			dst = end + parent_ce->default_static_members_count;
1560 			ce->default_static_members_table = end;
1561 		}
1562 		src = parent_ce->default_static_members_table + parent_ce->default_static_members_count;
1563 		do {
1564 			dst--;
1565 			src--;
1566 			if (Z_TYPE_P(src) == IS_INDIRECT) {
1567 				ZVAL_INDIRECT(dst, Z_INDIRECT_P(src));
1568 			} else {
1569 				ZVAL_INDIRECT(dst, src);
1570 			}
1571 			if (Z_TYPE_P(Z_INDIRECT_P(dst)) == IS_CONSTANT_AST) {
1572 				ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
1573 				ce->ce_flags |= ZEND_ACC_HAS_AST_STATICS;
1574 			}
1575 		} while (dst != end);
1576 		ce->default_static_members_count += parent_ce->default_static_members_count;
1577 		if (!ZEND_MAP_PTR(ce->static_members_table)) {
1578 			if (ce->type == ZEND_INTERNAL_CLASS &&
1579 					ce->info.internal.module->type == MODULE_PERSISTENT) {
1580 				ZEND_MAP_PTR_NEW(ce->static_members_table);
1581 			}
1582 		}
1583 	}
1584 
1585 	ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, property_info) {
1586 		if (property_info->ce == ce) {
1587 			if (property_info->flags & ZEND_ACC_STATIC) {
1588 				property_info->offset += parent_ce->default_static_members_count;
1589 			} else {
1590 				property_info->offset += parent_ce->default_properties_count * sizeof(zval);
1591 			}
1592 		}
1593 	} ZEND_HASH_FOREACH_END();
1594 
1595 	if (zend_hash_num_elements(&parent_ce->properties_info)) {
1596 		zend_hash_extend(&ce->properties_info,
1597 			zend_hash_num_elements(&ce->properties_info) +
1598 			zend_hash_num_elements(&parent_ce->properties_info), 0);
1599 
1600 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, property_info) {
1601 			do_inherit_property(property_info, key, ce);
1602 		} ZEND_HASH_FOREACH_END();
1603 	}
1604 
1605 	if (zend_hash_num_elements(&parent_ce->constants_table)) {
1606 		zend_class_constant *c;
1607 
1608 		zend_hash_extend(&ce->constants_table,
1609 			zend_hash_num_elements(&ce->constants_table) +
1610 			zend_hash_num_elements(&parent_ce->constants_table), 0);
1611 
1612 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->constants_table, key, c) {
1613 			do_inherit_class_constant(key, c, ce);
1614 		} ZEND_HASH_FOREACH_END();
1615 	}
1616 
1617 	if (zend_hash_num_elements(&parent_ce->function_table)) {
1618 		zend_hash_extend(&ce->function_table,
1619 			zend_hash_num_elements(&ce->function_table) +
1620 			zend_hash_num_elements(&parent_ce->function_table), 0);
1621 		uint32_t flags =
1622 			ZEND_INHERITANCE_LAZY_CHILD_CLONE | ZEND_INHERITANCE_SET_CHILD_CHANGED | ZEND_INHERITANCE_SET_CHILD_PROTO;
1623 
1624 		if (!checked) {
1625 			flags |= ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY;
1626 		}
1627 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) {
1628 			do_inherit_method(key, func, ce, 0, flags);
1629 		} ZEND_HASH_FOREACH_END();
1630 	}
1631 
1632 	do_inherit_parent_constructor(ce);
1633 
1634 	if (ce->type == ZEND_INTERNAL_CLASS) {
1635 		if (parent_ce->num_interfaces) {
1636 			zend_do_inherit_interfaces(ce, parent_ce);
1637 		}
1638 
1639 		if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
1640 			ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
1641 		}
1642 	}
1643 	ce->ce_flags |= parent_ce->ce_flags & (ZEND_HAS_STATIC_IN_METHODS | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_USE_GUARDS | ZEND_ACC_NOT_SERIALIZABLE | ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES);
1644 }
1645 /* }}} */
1646 
check_trait_property_or_constant_value_compatibility(zend_class_entry * ce,zval * op1,zval * op2)1647 static zend_always_inline bool check_trait_property_or_constant_value_compatibility(zend_class_entry *ce, zval *op1, zval *op2) /* {{{ */
1648 {
1649 	bool is_compatible;
1650 	zval op1_tmp, op2_tmp;
1651 
1652 	/* if any of the values is a constant, we try to resolve it */
1653 	if (UNEXPECTED(Z_TYPE_P(op1) == IS_CONSTANT_AST)) {
1654 		ZVAL_COPY_OR_DUP(&op1_tmp, op1);
1655 		zval_update_constant_ex(&op1_tmp, ce);
1656 		op1 = &op1_tmp;
1657 	}
1658 	if (UNEXPECTED(Z_TYPE_P(op2) == IS_CONSTANT_AST)) {
1659 		ZVAL_COPY_OR_DUP(&op2_tmp, op2);
1660 		zval_update_constant_ex(&op2_tmp, ce);
1661 		op2 = &op2_tmp;
1662 	}
1663 
1664 	is_compatible = fast_is_identical_function(op1, op2);
1665 
1666 	if (op1 == &op1_tmp) {
1667 		zval_ptr_dtor_nogc(&op1_tmp);
1668 	}
1669 	if (op2 == &op2_tmp) {
1670 		zval_ptr_dtor_nogc(&op2_tmp);
1671 	}
1672 
1673 	return is_compatible;
1674 }
1675 /* }}} */
1676 
do_inherit_constant_check(zend_class_entry * ce,zend_class_constant * parent_constant,zend_string * name)1677 static bool do_inherit_constant_check(
1678 	zend_class_entry *ce, zend_class_constant *parent_constant, zend_string *name
1679 ) {
1680 	zval *zv = zend_hash_find_known_hash(&ce->constants_table, name);
1681 	if (zv == NULL) {
1682 		return true;
1683 	}
1684 
1685 	zend_class_constant *old_constant = Z_PTR_P(zv);
1686 	if (parent_constant->ce != old_constant->ce && (ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_FINAL)) {
1687 		zend_error_noreturn(E_COMPILE_ERROR, "%s::%s cannot override final constant %s::%s",
1688 			ZSTR_VAL(old_constant->ce->name), ZSTR_VAL(name),
1689 			ZSTR_VAL(parent_constant->ce->name), ZSTR_VAL(name)
1690 		);
1691 	}
1692 
1693 	if (old_constant->ce != parent_constant->ce && old_constant->ce != ce) {
1694 		zend_error_noreturn(E_COMPILE_ERROR,
1695 			"%s %s inherits both %s::%s and %s::%s, which is ambiguous",
1696 			zend_get_object_type_uc(ce),
1697 			ZSTR_VAL(ce->name),
1698 			ZSTR_VAL(old_constant->ce->name), ZSTR_VAL(name),
1699 			ZSTR_VAL(parent_constant->ce->name), ZSTR_VAL(name));
1700 	}
1701 
1702 	return false;
1703 }
1704 /* }}} */
1705 
do_inherit_iface_constant(zend_string * name,zend_class_constant * c,zend_class_entry * ce,zend_class_entry * iface)1706 static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
1707 {
1708 	if (do_inherit_constant_check(ce, c, name)) {
1709 		zend_class_constant *ct;
1710 		if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1711 			ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
1712 			ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
1713 			if (iface->ce_flags & ZEND_ACC_IMMUTABLE) {
1714 				ct = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
1715 				memcpy(ct, c, sizeof(zend_class_constant));
1716 				c = ct;
1717 				Z_CONSTANT_FLAGS(c->value) |= CONST_OWNED;
1718 			}
1719 		}
1720 		if (ce->type & ZEND_INTERNAL_CLASS) {
1721 			ct = pemalloc(sizeof(zend_class_constant), 1);
1722 			memcpy(ct, c, sizeof(zend_class_constant));
1723 			c = ct;
1724 		}
1725 		zend_hash_update_ptr(&ce->constants_table, name, c);
1726 	}
1727 }
1728 /* }}} */
1729 
do_interface_implementation(zend_class_entry * ce,zend_class_entry * iface)1730 static void do_interface_implementation(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
1731 {
1732 	zend_function *func;
1733 	zend_string *key;
1734 	zend_class_constant *c;
1735 	uint32_t flags = ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY;
1736 
1737 	if (!(ce->ce_flags & ZEND_ACC_INTERFACE)) {
1738 		/* We are not setting the prototype of overridden interface methods because of abstract
1739 		 * constructors. See Zend/tests/interface_constructor_prototype_001.phpt. */
1740 		flags |= ZEND_INHERITANCE_LAZY_CHILD_CLONE | ZEND_INHERITANCE_SET_CHILD_PROTO;
1741 	}
1742 
1743 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) {
1744 		do_inherit_iface_constant(key, c, ce, iface);
1745 	} ZEND_HASH_FOREACH_END();
1746 
1747 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) {
1748 		do_inherit_method(key, func, ce, 1, flags);
1749 	} ZEND_HASH_FOREACH_END();
1750 
1751 	do_implement_interface(ce, iface);
1752 	if (iface->num_interfaces) {
1753 		zend_do_inherit_interfaces(ce, iface);
1754 	}
1755 }
1756 /* }}} */
1757 
zend_do_implement_interface(zend_class_entry * ce,zend_class_entry * iface)1758 ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
1759 {
1760 	uint32_t i, ignore = 0;
1761 	uint32_t current_iface_num = ce->num_interfaces;
1762 	uint32_t parent_iface_num  = ce->parent ? ce->parent->num_interfaces : 0;
1763 	zend_string *key;
1764 	zend_class_constant *c;
1765 
1766 	ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
1767 
1768 	for (i = 0; i < ce->num_interfaces; i++) {
1769 		if (ce->interfaces[i] == NULL) {
1770 			memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
1771 			i--;
1772 		} else if (ce->interfaces[i] == iface) {
1773 			if (EXPECTED(i < parent_iface_num)) {
1774 				ignore = 1;
1775 			} else {
1776 				zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
1777 			}
1778 		}
1779 	}
1780 	if (ignore) {
1781 		/* Check for attempt to redeclare interface constants */
1782 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) {
1783 			do_inherit_constant_check(ce, c, key);
1784 		} ZEND_HASH_FOREACH_END();
1785 	} else {
1786 		if (ce->num_interfaces >= current_iface_num) {
1787 			if (ce->type == ZEND_INTERNAL_CLASS) {
1788 				ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
1789 			} else {
1790 				ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
1791 			}
1792 		}
1793 		ce->interfaces[ce->num_interfaces++] = iface;
1794 
1795 		do_interface_implementation(ce, iface);
1796 	}
1797 }
1798 /* }}} */
1799 
zend_do_implement_interfaces(zend_class_entry * ce,zend_class_entry ** interfaces)1800 static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry **interfaces) /* {{{ */
1801 {
1802 	zend_class_entry *iface;
1803 	uint32_t num_parent_interfaces = ce->parent ? ce->parent->num_interfaces : 0;
1804 	uint32_t num_interfaces = num_parent_interfaces;
1805 	zend_string *key;
1806 	zend_class_constant *c;
1807 	uint32_t i, j;
1808 
1809 	for (i = 0; i < ce->num_interfaces; i++) {
1810 		iface = interfaces[num_parent_interfaces + i];
1811 		if (!(iface->ce_flags & ZEND_ACC_LINKED)) {
1812 			add_dependency_obligation(ce, iface);
1813 		}
1814 		if (UNEXPECTED(!(iface->ce_flags & ZEND_ACC_INTERFACE))) {
1815 			efree(interfaces);
1816 			zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
1817 			return;
1818 		}
1819 		for (j = 0; j < num_interfaces; j++) {
1820 			if (interfaces[j] == iface) {
1821 				if (j >= num_parent_interfaces) {
1822 					efree(interfaces);
1823 					zend_error_noreturn(E_COMPILE_ERROR, "%s %s cannot implement previously implemented interface %s",
1824 						zend_get_object_type_uc(ce),
1825 						ZSTR_VAL(ce->name),
1826 						ZSTR_VAL(iface->name));
1827 					return;
1828 				}
1829 				/* skip duplications */
1830 				ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) {
1831 					do_inherit_constant_check(ce, c, key);
1832 				} ZEND_HASH_FOREACH_END();
1833 
1834 				iface = NULL;
1835 				break;
1836 			}
1837 		}
1838 		if (iface) {
1839 			interfaces[num_interfaces] = iface;
1840 			num_interfaces++;
1841 		}
1842 	}
1843 
1844 	if (!(ce->ce_flags & ZEND_ACC_CACHED)) {
1845 		for (i = 0; i < ce->num_interfaces; i++) {
1846 			zend_string_release_ex(ce->interface_names[i].name, 0);
1847 			zend_string_release_ex(ce->interface_names[i].lc_name, 0);
1848 		}
1849 		efree(ce->interface_names);
1850 	}
1851 
1852 	ce->num_interfaces = num_interfaces;
1853 	ce->interfaces = interfaces;
1854 	ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES;
1855 
1856 	for (i = 0; i < num_parent_interfaces; i++) {
1857 		do_implement_interface(ce, ce->interfaces[i]);
1858 	}
1859 	/* Note that new interfaces can be added during this loop due to interface inheritance.
1860 	 * Use num_interfaces rather than ce->num_interfaces to not re-process the new ones. */
1861 	for (; i < num_interfaces; i++) {
1862 		do_interface_implementation(ce, ce->interfaces[i]);
1863 	}
1864 }
1865 /* }}} */
1866 
fixup_trait_scope(const zend_function * fn,zend_class_entry * ce)1867 static zend_class_entry *fixup_trait_scope(const zend_function *fn, zend_class_entry *ce)
1868 {
1869 	/* self in trait methods should be resolved to the using class, not the trait. */
1870 	return fn->common.scope->ce_flags & ZEND_ACC_TRAIT ? ce : fn->common.scope;
1871 }
1872 
zend_add_trait_method(zend_class_entry * ce,zend_string * name,zend_string * key,zend_function * fn)1873 static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_string *key, zend_function *fn) /* {{{ */
1874 {
1875 	zend_function *existing_fn = NULL;
1876 	zend_function *new_fn;
1877 	bool check_inheritance = false;
1878 
1879 	if ((existing_fn = zend_hash_find_ptr(&ce->function_table, key)) != NULL) {
1880 		/* if it is the same function with the same visibility and has not been assigned a class scope yet, regardless
1881 		 * of where it is coming from there is no conflict and we do not need to add it again */
1882 		if (existing_fn->op_array.opcodes == fn->op_array.opcodes &&
1883 			(existing_fn->common.fn_flags & ZEND_ACC_PPP_MASK) == (fn->common.fn_flags & ZEND_ACC_PPP_MASK) &&
1884 			(existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
1885 			return;
1886 		}
1887 
1888 		/* Abstract method signatures from the trait must be satisfied. */
1889 		if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1890 			/* "abstract private" methods in traits were not available prior to PHP 8.
1891 			 * As such, "abstract protected" was sometimes used to indicate trait requirements,
1892 			 * even though the "implementing" method was private. Do not check visibility
1893 			 * requirements to maintain backwards-compatibility with such usage.
1894 			 */
1895 			do_inheritance_check_on_method(
1896 				existing_fn, fixup_trait_scope(existing_fn, ce), fn, fixup_trait_scope(fn, ce),
1897 				ce, NULL, ZEND_INHERITANCE_CHECK_PROTO);
1898 			return;
1899 		}
1900 
1901 		if (existing_fn->common.scope == ce) {
1902 			/* members from the current class override trait methods */
1903 			return;
1904 		} else if (UNEXPECTED((existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT)
1905 				&& !(existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT))) {
1906 			/* two traits can't define the same non-abstract method */
1907 			zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s::%s has not been applied as %s::%s, because of collision with %s::%s",
1908 				ZSTR_VAL(fn->common.scope->name), ZSTR_VAL(fn->common.function_name),
1909 				ZSTR_VAL(ce->name), ZSTR_VAL(name),
1910 				ZSTR_VAL(existing_fn->common.scope->name), ZSTR_VAL(existing_fn->common.function_name));
1911 		} else {
1912 			check_inheritance = true;
1913 		}
1914 	}
1915 
1916 	if (UNEXPECTED(fn->type == ZEND_INTERNAL_FUNCTION)) {
1917 		new_fn = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function));
1918 		memcpy(new_fn, fn, sizeof(zend_internal_function));
1919 		new_fn->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED;
1920 	} else {
1921 		new_fn = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
1922 		memcpy(new_fn, fn, sizeof(zend_op_array));
1923 		new_fn->op_array.fn_flags &= ~ZEND_ACC_IMMUTABLE;
1924 	}
1925 	new_fn->common.fn_flags |= ZEND_ACC_TRAIT_CLONE;
1926 
1927 	/* Reassign method name, in case it is an alias. */
1928 	new_fn->common.function_name = name;
1929 	function_add_ref(new_fn);
1930 	fn = zend_hash_update_ptr(&ce->function_table, key, new_fn);
1931 	zend_add_magic_method(ce, fn, key);
1932 
1933 	if (check_inheritance) {
1934 		/* Inherited members are overridden by members inserted by traits.
1935 		 * Check whether the trait method fulfills the inheritance requirements. */
1936 		uint32_t flags = ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY;
1937 		if (!(existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT)) {
1938 			flags |= ZEND_INHERITANCE_SET_CHILD_CHANGED |ZEND_INHERITANCE_SET_CHILD_PROTO;
1939 		}
1940 		do_inheritance_check_on_method(
1941 			fn, fixup_trait_scope(fn, ce), existing_fn, fixup_trait_scope(existing_fn, ce),
1942 			ce, NULL, flags);
1943 	}
1944 }
1945 /* }}} */
1946 
zend_fixup_trait_method(zend_function * fn,zend_class_entry * ce)1947 static void zend_fixup_trait_method(zend_function *fn, zend_class_entry *ce) /* {{{ */
1948 {
1949 	if ((fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
1950 
1951 		fn->common.scope = ce;
1952 
1953 		if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1954 			ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
1955 		}
1956 		if (fn->type == ZEND_USER_FUNCTION && fn->op_array.static_variables) {
1957 			ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
1958 		}
1959 	}
1960 }
1961 /* }}} */
1962 
zend_traits_copy_functions(zend_string * fnname,zend_function * fn,zend_class_entry * ce,HashTable * exclude_table,zend_class_entry ** aliases)1963 static void zend_traits_copy_functions(zend_string *fnname, zend_function *fn, zend_class_entry *ce, HashTable *exclude_table, zend_class_entry **aliases) /* {{{ */
1964 {
1965 	zend_trait_alias  *alias, **alias_ptr;
1966 	zend_string       *lcname;
1967 	zend_function      fn_copy;
1968 	int                i;
1969 
1970 	/* apply aliases which are qualified with a class name, there should not be any ambiguity */
1971 	if (ce->trait_aliases) {
1972 		alias_ptr = ce->trait_aliases;
1973 		alias = *alias_ptr;
1974 		i = 0;
1975 		while (alias) {
1976 			/* Scope unset or equal to the function we compare to, and the alias applies to fn */
1977 			if (alias->alias != NULL
1978 				&& fn->common.scope == aliases[i]
1979 				&& zend_string_equals_ci(alias->trait_method.method_name, fnname)
1980 			) {
1981 				fn_copy = *fn;
1982 
1983 				/* if it is 0, no modifiers have been changed */
1984 				if (alias->modifiers) {
1985 					fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags & ~ZEND_ACC_PPP_MASK);
1986 				}
1987 
1988 				lcname = zend_string_tolower(alias->alias);
1989 				zend_add_trait_method(ce, alias->alias, lcname, &fn_copy);
1990 				zend_string_release_ex(lcname, 0);
1991 			}
1992 			alias_ptr++;
1993 			alias = *alias_ptr;
1994 			i++;
1995 		}
1996 	}
1997 
1998 	if (exclude_table == NULL || zend_hash_find(exclude_table, fnname) == NULL) {
1999 		/* is not in hashtable, thus, function is not to be excluded */
2000 		memcpy(&fn_copy, fn, fn->type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function));
2001 
2002 		/* apply aliases which have not alias name, just setting visibility */
2003 		if (ce->trait_aliases) {
2004 			alias_ptr = ce->trait_aliases;
2005 			alias = *alias_ptr;
2006 			i = 0;
2007 			while (alias) {
2008 				/* Scope unset or equal to the function we compare to, and the alias applies to fn */
2009 				if (alias->alias == NULL && alias->modifiers != 0
2010 					&& fn->common.scope == aliases[i]
2011 					&& zend_string_equals_ci(alias->trait_method.method_name, fnname)
2012 				) {
2013 					fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags & ~ZEND_ACC_PPP_MASK);
2014 				}
2015 				alias_ptr++;
2016 				alias = *alias_ptr;
2017 				i++;
2018 			}
2019 		}
2020 
2021 		zend_add_trait_method(ce, fn->common.function_name, fnname, &fn_copy);
2022 	}
2023 }
2024 /* }}} */
2025 
zend_check_trait_usage(zend_class_entry * ce,zend_class_entry * trait,zend_class_entry ** traits)2026 static uint32_t zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait, zend_class_entry **traits) /* {{{ */
2027 {
2028 	uint32_t i;
2029 
2030 	if (UNEXPECTED((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT)) {
2031 		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));
2032 		return 0;
2033 	}
2034 
2035 	for (i = 0; i < ce->num_traits; i++) {
2036 		if (traits[i] == trait) {
2037 			return i;
2038 		}
2039 	}
2040 	zend_error_noreturn(E_COMPILE_ERROR, "Required Trait %s wasn't added to %s", ZSTR_VAL(trait->name), ZSTR_VAL(ce->name));
2041 	return 0;
2042 }
2043 /* }}} */
2044 
zend_traits_init_trait_structures(zend_class_entry * ce,zend_class_entry ** traits,HashTable *** exclude_tables_ptr,zend_class_entry *** aliases_ptr)2045 static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_entry **traits, HashTable ***exclude_tables_ptr, zend_class_entry ***aliases_ptr) /* {{{ */
2046 {
2047 	size_t i, j = 0;
2048 	zend_trait_precedence **precedences;
2049 	zend_trait_precedence *cur_precedence;
2050 	zend_trait_method_reference *cur_method_ref;
2051 	zend_string *lc_trait_name;
2052 	zend_string *lcname;
2053 	HashTable **exclude_tables = NULL;
2054 	zend_class_entry **aliases = NULL;
2055 	zend_class_entry *trait;
2056 
2057 	/* resolve class references */
2058 	if (ce->trait_precedences) {
2059 		exclude_tables = ecalloc(ce->num_traits, sizeof(HashTable*));
2060 		i = 0;
2061 		precedences = ce->trait_precedences;
2062 		ce->trait_precedences = NULL;
2063 		while ((cur_precedence = precedences[i])) {
2064 			/** Resolve classes for all precedence operations. */
2065 			cur_method_ref = &cur_precedence->trait_method;
2066 			lc_trait_name = zend_string_tolower(cur_method_ref->class_name);
2067 			trait = zend_hash_find_ptr(EG(class_table), lc_trait_name);
2068 			zend_string_release_ex(lc_trait_name, 0);
2069 			if (!trait || !(trait->ce_flags & ZEND_ACC_LINKED)) {
2070 				zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name));
2071 			}
2072 			zend_check_trait_usage(ce, trait, traits);
2073 
2074 			/** Ensure that the preferred method is actually available. */
2075 			lcname = zend_string_tolower(cur_method_ref->method_name);
2076 			if (!zend_hash_exists(&trait->function_table, lcname)) {
2077 				zend_error_noreturn(E_COMPILE_ERROR,
2078 						   "A precedence rule was defined for %s::%s but this method does not exist",
2079 						   ZSTR_VAL(trait->name),
2080 						   ZSTR_VAL(cur_method_ref->method_name));
2081 			}
2082 
2083 			/** With the other traits, we are more permissive.
2084 				We do not give errors for those. This allows to be more
2085 				defensive in such definitions.
2086 				However, we want to make sure that the insteadof declaration
2087 				is consistent in itself.
2088 			 */
2089 
2090 			for (j = 0; j < cur_precedence->num_excludes; j++) {
2091 				zend_string* class_name = cur_precedence->exclude_class_names[j];
2092 				zend_class_entry *exclude_ce;
2093 				uint32_t trait_num;
2094 
2095 				lc_trait_name = zend_string_tolower(class_name);
2096 				exclude_ce = zend_hash_find_ptr(EG(class_table), lc_trait_name);
2097 				zend_string_release_ex(lc_trait_name, 0);
2098 				if (!exclude_ce || !(exclude_ce->ce_flags & ZEND_ACC_LINKED)) {
2099 					zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(class_name));
2100 				}
2101 				trait_num = zend_check_trait_usage(ce, exclude_ce, traits);
2102 				if (!exclude_tables[trait_num]) {
2103 					ALLOC_HASHTABLE(exclude_tables[trait_num]);
2104 					zend_hash_init(exclude_tables[trait_num], 0, NULL, NULL, 0);
2105 				}
2106 				if (zend_hash_add_empty_element(exclude_tables[trait_num], lcname) == NULL) {
2107 					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(exclude_ce->name));
2108 				}
2109 
2110 				/* make sure that the trait method is not from a class mentioned in
2111 				 exclude_from_classes, for consistency */
2112 				if (trait == exclude_ce) {
2113 					zend_error_noreturn(E_COMPILE_ERROR,
2114 							   "Inconsistent insteadof definition. "
2115 							   "The method %s is to be used from %s, but %s is also on the exclude list",
2116 							   ZSTR_VAL(cur_method_ref->method_name),
2117 							   ZSTR_VAL(trait->name),
2118 							   ZSTR_VAL(trait->name));
2119 				}
2120 			}
2121 			zend_string_release_ex(lcname, 0);
2122 			i++;
2123 		}
2124 		ce->trait_precedences = precedences;
2125 	}
2126 
2127 	if (ce->trait_aliases) {
2128 		i = 0;
2129 		while (ce->trait_aliases[i]) {
2130 			i++;
2131 		}
2132 		aliases = ecalloc(i, sizeof(zend_class_entry*));
2133 		i = 0;
2134 		while (ce->trait_aliases[i]) {
2135 			zend_trait_alias *cur_alias = ce->trait_aliases[i];
2136 			cur_method_ref = &ce->trait_aliases[i]->trait_method;
2137 			lcname = zend_string_tolower(cur_method_ref->method_name);
2138 			if (cur_method_ref->class_name) {
2139 				/* For all aliases with an explicit class name, resolve the class now. */
2140 				lc_trait_name = zend_string_tolower(cur_method_ref->class_name);
2141 				trait = zend_hash_find_ptr(EG(class_table), lc_trait_name);
2142 				zend_string_release_ex(lc_trait_name, 0);
2143 				if (!trait || !(trait->ce_flags & ZEND_ACC_LINKED)) {
2144 					zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name));
2145 				}
2146 				zend_check_trait_usage(ce, trait, traits);
2147 				aliases[i] = trait;
2148 
2149 				/* And, ensure that the referenced method is resolvable, too. */
2150 				if (!zend_hash_exists(&trait->function_table, lcname)) {
2151 					zend_error_noreturn(E_COMPILE_ERROR, "An alias was defined for %s::%s but this method does not exist", ZSTR_VAL(trait->name), ZSTR_VAL(cur_method_ref->method_name));
2152 				}
2153 			} else {
2154 				/* Find out which trait this method refers to. */
2155 				trait = NULL;
2156 				for (j = 0; j < ce->num_traits; j++) {
2157 					if (traits[j]) {
2158 						if (zend_hash_exists(&traits[j]->function_table, lcname)) {
2159 							if (!trait) {
2160 								trait = traits[j];
2161 								continue;
2162 							}
2163 
2164 							zend_error_noreturn(E_COMPILE_ERROR,
2165 								"An alias was defined for method %s(), which exists in both %s and %s. Use %s::%s or %s::%s to resolve the ambiguity",
2166 								ZSTR_VAL(cur_method_ref->method_name),
2167 								ZSTR_VAL(trait->name), ZSTR_VAL(traits[j]->name),
2168 								ZSTR_VAL(trait->name), ZSTR_VAL(cur_method_ref->method_name),
2169 								ZSTR_VAL(traits[j]->name), ZSTR_VAL(cur_method_ref->method_name));
2170 						}
2171 					}
2172 				}
2173 
2174 				/* Non-absolute method reference refers to method that does not exist. */
2175 				if (!trait) {
2176 					if (cur_alias->alias) {
2177 						zend_error_noreturn(E_COMPILE_ERROR,
2178 							"An alias (%s) was defined for method %s(), but this method does not exist",
2179 							ZSTR_VAL(cur_alias->alias),
2180 							ZSTR_VAL(cur_alias->trait_method.method_name));
2181 					} else {
2182 						zend_error_noreturn(E_COMPILE_ERROR,
2183 							"The modifiers of the trait method %s() are changed, but this method does not exist. Error",
2184 							ZSTR_VAL(cur_alias->trait_method.method_name));
2185 					}
2186 				}
2187 
2188 				aliases[i] = trait;
2189 			}
2190 			zend_string_release_ex(lcname, 0);
2191 			i++;
2192 		}
2193 	}
2194 
2195 	*exclude_tables_ptr = exclude_tables;
2196 	*aliases_ptr = aliases;
2197 }
2198 /* }}} */
2199 
zend_do_traits_method_binding(zend_class_entry * ce,zend_class_entry ** traits,HashTable ** exclude_tables,zend_class_entry ** aliases)2200 static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry **traits, HashTable **exclude_tables, zend_class_entry **aliases) /* {{{ */
2201 {
2202 	uint32_t i;
2203 	zend_string *key;
2204 	zend_function *fn;
2205 
2206 	if (exclude_tables) {
2207 		for (i = 0; i < ce->num_traits; i++) {
2208 			if (traits[i]) {
2209 				/* copies functions, applies defined aliasing, and excludes unused trait methods */
2210 				ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) {
2211 					zend_traits_copy_functions(key, fn, ce, exclude_tables[i], aliases);
2212 				} ZEND_HASH_FOREACH_END();
2213 
2214 				if (exclude_tables[i]) {
2215 					zend_hash_destroy(exclude_tables[i]);
2216 					FREE_HASHTABLE(exclude_tables[i]);
2217 					exclude_tables[i] = NULL;
2218 				}
2219 			}
2220 		}
2221 	} else {
2222 		for (i = 0; i < ce->num_traits; i++) {
2223 			if (traits[i]) {
2224 				ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) {
2225 					zend_traits_copy_functions(key, fn, ce, NULL, aliases);
2226 				} ZEND_HASH_FOREACH_END();
2227 			}
2228 		}
2229 	}
2230 
2231 	ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) {
2232 		zend_fixup_trait_method(fn, ce);
2233 	} ZEND_HASH_FOREACH_END();
2234 }
2235 /* }}} */
2236 
find_first_constant_definition(zend_class_entry * ce,zend_class_entry ** traits,size_t current_trait,zend_string * constant_name,zend_class_entry * colliding_ce)2237 static zend_class_entry* find_first_constant_definition(zend_class_entry *ce, zend_class_entry **traits, size_t current_trait, zend_string *constant_name, zend_class_entry *colliding_ce) /* {{{ */
2238 {
2239 	/* This function is used to show the place of the existing conflicting
2240 	 * definition in error messages when conflicts occur. Since trait constants
2241 	 * are flattened into the constants table of the composing class, and thus
2242 	 * we lose information about which constant was defined in which trait, a
2243 	 * process like this is needed to find the location of the first definition
2244 	 * of the constant from traits.
2245 	 */
2246 	size_t i;
2247 
2248 	if (colliding_ce == ce) {
2249 		for (i = 0; i < current_trait; i++) {
2250 			if (traits[i]
2251 				&& zend_hash_exists(&traits[i]->constants_table, constant_name)) {
2252 				return traits[i];
2253 			}
2254 		}
2255 	}
2256 	/* Traits don't have it, then the composing class (or trait) itself has it. */
2257 	return colliding_ce;
2258 }
2259 /* }}} */
2260 
do_trait_constant_check(zend_class_entry * ce,zend_class_constant * trait_constant,zend_string * name,zend_class_entry ** traits,size_t current_trait)2261 static bool do_trait_constant_check(zend_class_entry *ce, zend_class_constant *trait_constant, zend_string *name, zend_class_entry **traits, size_t current_trait) /* {{{ */
2262 {
2263 	uint32_t flags_mask = ZEND_ACC_PPP_MASK | ZEND_ACC_FINAL;
2264 
2265 	zval *zv = zend_hash_find_known_hash(&ce->constants_table, name);
2266 	if (zv == NULL) {
2267 		/* No existing constant of the same name, so this one can be added */
2268 		return true;
2269 	}
2270 
2271 	zend_class_constant *existing_constant = Z_PTR_P(zv);
2272 
2273 	if ((ZEND_CLASS_CONST_FLAGS(trait_constant) & flags_mask) != (ZEND_CLASS_CONST_FLAGS(existing_constant) & flags_mask) ||
2274 	    !check_trait_property_or_constant_value_compatibility(ce, &trait_constant->value, &existing_constant->value)) {
2275 		/* There is an existing constant of the same name, and it conflicts with the new one, so let's throw a fatal error */
2276 		zend_error_noreturn(E_COMPILE_ERROR,
2277 			"%s and %s define the same constant (%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
2278 			ZSTR_VAL(find_first_constant_definition(ce, traits, current_trait, name, existing_constant->ce)->name),
2279 			ZSTR_VAL(trait_constant->ce->name),
2280 			ZSTR_VAL(name),
2281 			ZSTR_VAL(ce->name));
2282 	}
2283 
2284 	/* There is an existing constant which is compatible with the new one, so no need to add it */
2285 	return false;
2286 }
2287 /* }}} */
2288 
zend_do_traits_constant_binding(zend_class_entry * ce,zend_class_entry ** traits)2289 static void zend_do_traits_constant_binding(zend_class_entry *ce, zend_class_entry **traits) /* {{{ */
2290 {
2291 	size_t i;
2292 
2293 	for (i = 0; i < ce->num_traits; i++) {
2294 		zend_string *constant_name;
2295 		zend_class_constant *constant;
2296 
2297 		if (!traits[i]) {
2298 			continue;
2299 		}
2300 
2301 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->constants_table, constant_name, constant) {
2302 			if (do_trait_constant_check(ce, constant, constant_name, traits, i)) {
2303 				zend_class_constant *ct = NULL;
2304 
2305 				ct = zend_arena_alloc(&CG(arena),sizeof(zend_class_constant));
2306 				memcpy(ct, constant, sizeof(zend_class_constant));
2307 				constant = ct;
2308 
2309 				if (Z_TYPE(constant->value) == IS_CONSTANT_AST) {
2310 					ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
2311 					ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
2312 				}
2313 
2314 				/* Unlike interface implementations and class inheritances,
2315 				 * access control of the trait constants is done by the scope
2316 				 * of the composing class. So let's replace the ce here.
2317 				 */
2318 				constant->ce = ce;
2319 
2320 				Z_TRY_ADDREF(constant->value);
2321 				constant->doc_comment = constant->doc_comment ? zend_string_copy(constant->doc_comment) : NULL;
2322 				if (constant->attributes && (!(GC_FLAGS(constant->attributes) & IS_ARRAY_IMMUTABLE))) {
2323 					GC_ADDREF(constant->attributes);
2324 				}
2325 
2326 				zend_hash_update_ptr(&ce->constants_table, constant_name, constant);
2327 			}
2328 		} ZEND_HASH_FOREACH_END();
2329 	}
2330 }
2331 /* }}} */
2332 
find_first_property_definition(zend_class_entry * ce,zend_class_entry ** traits,size_t current_trait,zend_string * prop_name,zend_class_entry * colliding_ce)2333 static zend_class_entry* find_first_property_definition(zend_class_entry *ce, zend_class_entry **traits, size_t current_trait, zend_string *prop_name, zend_class_entry *colliding_ce) /* {{{ */
2334 {
2335 	size_t i;
2336 
2337 	if (colliding_ce == ce) {
2338 		for (i = 0; i < current_trait; i++) {
2339 			if (traits[i]
2340 			 && zend_hash_exists(&traits[i]->properties_info, prop_name)) {
2341 				return traits[i];
2342 			}
2343 		}
2344 	}
2345 
2346 	return colliding_ce;
2347 }
2348 /* }}} */
2349 
zend_do_traits_property_binding(zend_class_entry * ce,zend_class_entry ** traits)2350 static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_entry **traits) /* {{{ */
2351 {
2352 	size_t i;
2353 	zend_property_info *property_info;
2354 	zend_property_info *colliding_prop;
2355 	zend_property_info *new_prop;
2356 	zend_string* prop_name;
2357 	zval* prop_value;
2358 	zend_string *doc_comment;
2359 
2360 	/* In the following steps the properties are inserted into the property table
2361 	 * for that, a very strict approach is applied:
2362 	 * - check for compatibility, if not compatible with any property in class -> fatal
2363 	 * - if compatible, then strict notice
2364 	 */
2365 	for (i = 0; i < ce->num_traits; i++) {
2366 		if (!traits[i]) {
2367 			continue;
2368 		}
2369 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->properties_info, prop_name, property_info) {
2370 			uint32_t flags = property_info->flags;
2371 
2372 			/* next: check for conflicts with current class */
2373 			if ((colliding_prop = zend_hash_find_ptr(&ce->properties_info, prop_name)) != NULL) {
2374 				if ((colliding_prop->flags & ZEND_ACC_PRIVATE) && colliding_prop->ce != ce) {
2375 					zend_hash_del(&ce->properties_info, prop_name);
2376 					flags |= ZEND_ACC_CHANGED;
2377 				} else {
2378 					bool is_compatible = false;
2379 					uint32_t flags_mask = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC | ZEND_ACC_READONLY;
2380 
2381 					if ((colliding_prop->flags & flags_mask) == (flags & flags_mask) &&
2382 						property_types_compatible(property_info, colliding_prop) == INHERITANCE_SUCCESS
2383 					) {
2384 						/* the flags are identical, thus, the properties may be compatible */
2385 						zval *op1, *op2;
2386 
2387 						if (flags & ZEND_ACC_STATIC) {
2388 							op1 = &ce->default_static_members_table[colliding_prop->offset];
2389 							op2 = &traits[i]->default_static_members_table[property_info->offset];
2390 							ZVAL_DEINDIRECT(op1);
2391 							ZVAL_DEINDIRECT(op2);
2392 						} else {
2393 							op1 = &ce->default_properties_table[OBJ_PROP_TO_NUM(colliding_prop->offset)];
2394 							op2 = &traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)];
2395 						}
2396 						is_compatible = check_trait_property_or_constant_value_compatibility(ce, op1, op2);
2397 					}
2398 
2399 					if (!is_compatible) {
2400 						zend_error_noreturn(E_COMPILE_ERROR,
2401 								"%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
2402 								ZSTR_VAL(find_first_property_definition(ce, traits, i, prop_name, colliding_prop->ce)->name),
2403 								ZSTR_VAL(property_info->ce->name),
2404 								ZSTR_VAL(prop_name),
2405 								ZSTR_VAL(ce->name));
2406 					}
2407 					continue;
2408 				}
2409 			}
2410 
2411 			if ((ce->ce_flags & ZEND_ACC_READONLY_CLASS) && !(property_info->flags & ZEND_ACC_READONLY)) {
2412 				zend_error_noreturn(E_COMPILE_ERROR,
2413 					"Readonly class %s cannot use trait with a non-readonly property %s::$%s",
2414 					ZSTR_VAL(ce->name),
2415 					ZSTR_VAL(property_info->ce->name),
2416 					ZSTR_VAL(prop_name)
2417 				);
2418 			}
2419 
2420 			/* property not found, so lets add it */
2421 			if (flags & ZEND_ACC_STATIC) {
2422 				prop_value = &traits[i]->default_static_members_table[property_info->offset];
2423 				ZEND_ASSERT(Z_TYPE_P(prop_value) != IS_INDIRECT);
2424 			} else {
2425 				prop_value = &traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)];
2426 			}
2427 
2428 			Z_TRY_ADDREF_P(prop_value);
2429 			doc_comment = property_info->doc_comment ? zend_string_copy(property_info->doc_comment) : NULL;
2430 
2431 			zend_type type = property_info->type;
2432 			/* Assumption: only userland classes can use traits, as such the type must be arena allocated */
2433 			zend_type_copy_ctor(&type, /* use arena */ true, /* persistent */ false);
2434 			new_prop = zend_declare_typed_property(ce, prop_name, prop_value, flags, doc_comment, type);
2435 
2436 			if (property_info->attributes) {
2437 				new_prop->attributes = property_info->attributes;
2438 
2439 				if (!(GC_FLAGS(new_prop->attributes) & IS_ARRAY_IMMUTABLE)) {
2440 					GC_ADDREF(new_prop->attributes);
2441 				}
2442 			}
2443 		} ZEND_HASH_FOREACH_END();
2444 	}
2445 }
2446 /* }}} */
2447 
zend_do_bind_traits(zend_class_entry * ce,zend_class_entry ** traits)2448 static void zend_do_bind_traits(zend_class_entry *ce, zend_class_entry **traits) /* {{{ */
2449 {
2450 	HashTable **exclude_tables;
2451 	zend_class_entry **aliases;
2452 
2453 	ZEND_ASSERT(ce->num_traits > 0);
2454 
2455 	/* complete initialization of trait structures in ce */
2456 	zend_traits_init_trait_structures(ce, traits, &exclude_tables, &aliases);
2457 
2458 	/* first care about all methods to be flattened into the class */
2459 	zend_do_traits_method_binding(ce, traits, exclude_tables, aliases);
2460 
2461 	if (aliases) {
2462 		efree(aliases);
2463 	}
2464 
2465 	if (exclude_tables) {
2466 		efree(exclude_tables);
2467 	}
2468 
2469 	/* then flatten the constants and properties into it, to, mostly to notify developer about problems */
2470 	zend_do_traits_constant_binding(ce, traits);
2471 	zend_do_traits_property_binding(ce, traits);
2472 }
2473 /* }}} */
2474 
2475 #define MAX_ABSTRACT_INFO_CNT 3
2476 #define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
2477 #define DISPLAY_ABSTRACT_FN(idx) \
2478 	ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
2479 	ai.afn[idx] ? "::" : "", \
2480 	ai.afn[idx] ? ZSTR_VAL(ai.afn[idx]->common.function_name) : "", \
2481 	ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
2482 
2483 typedef struct _zend_abstract_info {
2484 	zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1];
2485 	int cnt;
2486 } zend_abstract_info;
2487 
zend_verify_abstract_class_function(zend_function * fn,zend_abstract_info * ai)2488 static void zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai) /* {{{ */
2489 {
2490 	if (ai->cnt < MAX_ABSTRACT_INFO_CNT) {
2491 		ai->afn[ai->cnt] = fn;
2492 	}
2493 	ai->cnt++;
2494 }
2495 /* }}} */
2496 
zend_verify_abstract_class(zend_class_entry * ce)2497 void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */
2498 {
2499 	zend_function *func;
2500 	zend_abstract_info ai;
2501 	bool is_explicit_abstract = (ce->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) != 0;
2502 	bool can_be_abstract = (ce->ce_flags & ZEND_ACC_ENUM) == 0;
2503 	memset(&ai, 0, sizeof(ai));
2504 
2505 	ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, func) {
2506 		if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
2507 			/* If the class is explicitly abstract, we only check private abstract methods,
2508 			 * because only they must be declared in the same class. */
2509 			if (!is_explicit_abstract || (func->common.fn_flags & ZEND_ACC_PRIVATE)) {
2510 				zend_verify_abstract_class_function(func, &ai);
2511 			}
2512 		}
2513 	} ZEND_HASH_FOREACH_END();
2514 
2515 	if (ai.cnt) {
2516 		zend_error_noreturn(E_ERROR, !is_explicit_abstract && can_be_abstract
2517 			? "%s %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")"
2518 			: "%s %s must implement %d abstract private method%s (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
2519 			zend_get_object_type_uc(ce),
2520 			ZSTR_VAL(ce->name), ai.cnt,
2521 			ai.cnt > 1 ? "s" : "",
2522 			DISPLAY_ABSTRACT_FN(0),
2523 			DISPLAY_ABSTRACT_FN(1),
2524 			DISPLAY_ABSTRACT_FN(2)
2525 			);
2526 	} else {
2527 		/* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */
2528 		ce->ce_flags &= ~ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2529 	}
2530 }
2531 /* }}} */
2532 
2533 typedef struct {
2534 	enum {
2535 		OBLIGATION_DEPENDENCY,
2536 		OBLIGATION_COMPATIBILITY,
2537 		OBLIGATION_PROPERTY_COMPATIBILITY
2538 	} type;
2539 	union {
2540 		zend_class_entry *dependency_ce;
2541 		struct {
2542 			/* Traits may use temporary on-stack functions during inheritance checks,
2543 			 * so use copies of functions here as well. */
2544 			zend_function parent_fn;
2545 			zend_function child_fn;
2546 			zend_class_entry *child_scope;
2547 			zend_class_entry *parent_scope;
2548 		};
2549 		struct {
2550 			const zend_property_info *parent_prop;
2551 			const zend_property_info *child_prop;
2552 		};
2553 	};
2554 } variance_obligation;
2555 
variance_obligation_dtor(zval * zv)2556 static void variance_obligation_dtor(zval *zv) {
2557 	efree(Z_PTR_P(zv));
2558 }
2559 
variance_obligation_ht_dtor(zval * zv)2560 static void variance_obligation_ht_dtor(zval *zv) {
2561 	zend_hash_destroy(Z_PTR_P(zv));
2562 	FREE_HASHTABLE(Z_PTR_P(zv));
2563 }
2564 
get_or_init_obligations_for_class(zend_class_entry * ce)2565 static HashTable *get_or_init_obligations_for_class(zend_class_entry *ce) {
2566 	HashTable *ht;
2567 	zend_ulong key;
2568 	if (!CG(delayed_variance_obligations)) {
2569 		ALLOC_HASHTABLE(CG(delayed_variance_obligations));
2570 		zend_hash_init(CG(delayed_variance_obligations), 0, NULL, variance_obligation_ht_dtor, 0);
2571 	}
2572 
2573 	key = (zend_ulong) (uintptr_t) ce;
2574 	ht = zend_hash_index_find_ptr(CG(delayed_variance_obligations), key);
2575 	if (ht) {
2576 		return ht;
2577 	}
2578 
2579 	ALLOC_HASHTABLE(ht);
2580 	zend_hash_init(ht, 0, NULL, variance_obligation_dtor, 0);
2581 	zend_hash_index_add_new_ptr(CG(delayed_variance_obligations), key, ht);
2582 	ce->ce_flags |= ZEND_ACC_UNRESOLVED_VARIANCE;
2583 	return ht;
2584 }
2585 
add_dependency_obligation(zend_class_entry * ce,zend_class_entry * dependency_ce)2586 static void add_dependency_obligation(zend_class_entry *ce, zend_class_entry *dependency_ce) {
2587 	HashTable *obligations = get_or_init_obligations_for_class(ce);
2588 	variance_obligation *obligation = emalloc(sizeof(variance_obligation));
2589 	obligation->type = OBLIGATION_DEPENDENCY;
2590 	obligation->dependency_ce = dependency_ce;
2591 	zend_hash_next_index_insert_ptr(obligations, obligation);
2592 }
2593 
add_compatibility_obligation(zend_class_entry * ce,const zend_function * child_fn,zend_class_entry * child_scope,const zend_function * parent_fn,zend_class_entry * parent_scope)2594 static void add_compatibility_obligation(
2595 		zend_class_entry *ce,
2596 		const zend_function *child_fn, zend_class_entry *child_scope,
2597 		const zend_function *parent_fn, zend_class_entry *parent_scope) {
2598 	HashTable *obligations = get_or_init_obligations_for_class(ce);
2599 	variance_obligation *obligation = emalloc(sizeof(variance_obligation));
2600 	obligation->type = OBLIGATION_COMPATIBILITY;
2601 	/* Copy functions, because they may be stack-allocated in the case of traits. */
2602 	if (child_fn->common.type == ZEND_INTERNAL_FUNCTION) {
2603 		memcpy(&obligation->child_fn, child_fn, sizeof(zend_internal_function));
2604 	} else {
2605 		memcpy(&obligation->child_fn, child_fn, sizeof(zend_op_array));
2606 	}
2607 	if (parent_fn->common.type == ZEND_INTERNAL_FUNCTION) {
2608 		memcpy(&obligation->parent_fn, parent_fn, sizeof(zend_internal_function));
2609 	} else {
2610 		memcpy(&obligation->parent_fn, parent_fn, sizeof(zend_op_array));
2611 	}
2612 	obligation->child_scope = child_scope;
2613 	obligation->parent_scope = parent_scope;
2614 	zend_hash_next_index_insert_ptr(obligations, obligation);
2615 }
2616 
add_property_compatibility_obligation(zend_class_entry * ce,const zend_property_info * child_prop,const zend_property_info * parent_prop)2617 static void add_property_compatibility_obligation(
2618 		zend_class_entry *ce, const zend_property_info *child_prop,
2619 		const zend_property_info *parent_prop) {
2620 	HashTable *obligations = get_or_init_obligations_for_class(ce);
2621 	variance_obligation *obligation = emalloc(sizeof(variance_obligation));
2622 	obligation->type = OBLIGATION_PROPERTY_COMPATIBILITY;
2623 	obligation->child_prop = child_prop;
2624 	obligation->parent_prop = parent_prop;
2625 	zend_hash_next_index_insert_ptr(obligations, obligation);
2626 }
2627 
2628 static void resolve_delayed_variance_obligations(zend_class_entry *ce);
2629 
check_variance_obligation(variance_obligation * obligation)2630 static void check_variance_obligation(variance_obligation *obligation) {
2631 	if (obligation->type == OBLIGATION_DEPENDENCY) {
2632 		zend_class_entry *dependency_ce = obligation->dependency_ce;
2633 		if (dependency_ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE) {
2634 			zend_class_entry *orig_linking_class = CG(current_linking_class);
2635 
2636 			CG(current_linking_class) =
2637 				(dependency_ce->ce_flags & ZEND_ACC_CACHEABLE) ? dependency_ce : NULL;
2638 			resolve_delayed_variance_obligations(dependency_ce);
2639 			CG(current_linking_class) = orig_linking_class;
2640 		}
2641 	} else if (obligation->type == OBLIGATION_COMPATIBILITY) {
2642 		inheritance_status status = zend_do_perform_implementation_check(
2643 			&obligation->child_fn, obligation->child_scope,
2644 			&obligation->parent_fn, obligation->parent_scope);
2645 		if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
2646 			emit_incompatible_method_error(
2647 				&obligation->child_fn, obligation->child_scope,
2648 				&obligation->parent_fn, obligation->parent_scope, status);
2649 		}
2650 		/* Either the compatibility check was successful or only threw a warning. */
2651 	} else {
2652 		ZEND_ASSERT(obligation->type == OBLIGATION_PROPERTY_COMPATIBILITY);
2653 		inheritance_status status =
2654 			property_types_compatible(obligation->parent_prop, obligation->child_prop);
2655 		if (status != INHERITANCE_SUCCESS) {
2656 			emit_incompatible_property_error(obligation->child_prop, obligation->parent_prop);
2657 		}
2658 	}
2659 }
2660 
load_delayed_classes(zend_class_entry * ce)2661 static void load_delayed_classes(zend_class_entry *ce) {
2662 	HashTable *delayed_autoloads = CG(delayed_autoloads);
2663 	if (!delayed_autoloads) {
2664 		return;
2665 	}
2666 
2667 	/* Autoloading can trigger linking of another class, which may register new delayed autoloads.
2668 	 * For that reason, this code uses a loop that pops and loads the first element of the HT. If
2669 	 * this triggers linking, then the remaining classes may get loaded when linking the newly
2670 	 * loaded class. This is important, as otherwise necessary dependencies may not be available
2671 	 * if the new class is lower in the hierarchy than the current one. */
2672 	HashPosition pos = 0;
2673 	zend_string *name;
2674 	zend_ulong idx;
2675 	while (zend_hash_get_current_key_ex(delayed_autoloads, &name, &idx, &pos)
2676 			!= HASH_KEY_NON_EXISTENT) {
2677 		zend_string_addref(name);
2678 		zend_hash_del(delayed_autoloads, name);
2679 		zend_lookup_class(name);
2680 		zend_string_release(name);
2681 		if (EG(exception)) {
2682 			zend_exception_uncaught_error(
2683 				"During inheritance of %s, while autoloading %s",
2684 				ZSTR_VAL(ce->name), ZSTR_VAL(name));
2685 		}
2686 	}
2687 }
2688 
resolve_delayed_variance_obligations(zend_class_entry * ce)2689 static void resolve_delayed_variance_obligations(zend_class_entry *ce) {
2690 	HashTable *all_obligations = CG(delayed_variance_obligations), *obligations;
2691 	zend_ulong num_key = (zend_ulong) (uintptr_t) ce;
2692 
2693 	ZEND_ASSERT(all_obligations != NULL);
2694 	obligations = zend_hash_index_find_ptr(all_obligations, num_key);
2695 	ZEND_ASSERT(obligations != NULL);
2696 
2697 	variance_obligation *obligation;
2698 	ZEND_HASH_FOREACH_PTR(obligations, obligation) {
2699 		check_variance_obligation(obligation);
2700 	} ZEND_HASH_FOREACH_END();
2701 
2702 	ce->ce_flags &= ~ZEND_ACC_UNRESOLVED_VARIANCE;
2703 	ce->ce_flags |= ZEND_ACC_LINKED;
2704 	zend_hash_index_del(all_obligations, num_key);
2705 }
2706 
check_unrecoverable_load_failure(zend_class_entry * ce)2707 static void check_unrecoverable_load_failure(zend_class_entry *ce) {
2708 	/* If this class has been used while unlinked through a variance obligation, it is not legal
2709 	 * to remove the class from the class table and throw an exception, because there is already
2710 	 * a dependence on the inheritance hierarchy of this specific class. Instead we fall back to
2711 	 * a fatal error, as would happen if we did not allow exceptions in the first place. */
2712 	if (CG(unlinked_uses)
2713 			&& zend_hash_index_del(CG(unlinked_uses), (zend_long)(zend_uintptr_t)ce) == SUCCESS) {
2714 		zend_exception_uncaught_error(
2715 			"During inheritance of %s with variance dependencies", ZSTR_VAL(ce->name));
2716 	}
2717 }
2718 
2719 #define zend_update_inherited_handler(handler) do { \
2720 		if (ce->handler == (zend_function*)op_array) { \
2721 			ce->handler = (zend_function*)new_op_array; \
2722 		} \
2723 	} while (0)
2724 
zend_lazy_class_load(zend_class_entry * pce)2725 static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce)
2726 {
2727 	zend_class_entry *ce;
2728 	Bucket *p, *end;
2729 
2730 	ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
2731 	memcpy(ce, pce, sizeof(zend_class_entry));
2732 	ce->ce_flags &= ~ZEND_ACC_IMMUTABLE;
2733 	ce->refcount = 1;
2734 	ce->inheritance_cache = NULL;
2735 	if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
2736 		ZEND_MAP_PTR_NEW(ce->mutable_data);
2737 	} else {
2738 		ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
2739 	}
2740 
2741 	/* properties */
2742 	if (ce->default_properties_table) {
2743 		zval *dst = emalloc(sizeof(zval) * ce->default_properties_count);
2744 		zval *src = ce->default_properties_table;
2745 		zval *end = src + ce->default_properties_count;
2746 
2747 		ce->default_properties_table = dst;
2748 		for (; src != end; src++, dst++) {
2749 			ZVAL_COPY_VALUE_PROP(dst, src);
2750 		}
2751 	}
2752 
2753 	/* methods */
2754 	ce->function_table.pDestructor = ZEND_FUNCTION_DTOR;
2755 	if (!(HT_FLAGS(&ce->function_table) & HASH_FLAG_UNINITIALIZED)) {
2756 		p = emalloc(HT_SIZE(&ce->function_table));
2757 		memcpy(p, HT_GET_DATA_ADDR(&ce->function_table), HT_USED_SIZE(&ce->function_table));
2758 		HT_SET_DATA_ADDR(&ce->function_table, p);
2759 		p = ce->function_table.arData;
2760 		end = p + ce->function_table.nNumUsed;
2761 		for (; p != end; p++) {
2762 			zend_op_array *op_array, *new_op_array;
2763 
2764 			op_array = Z_PTR(p->val);
2765 			ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
2766 			ZEND_ASSERT(op_array->scope == pce);
2767 			ZEND_ASSERT(op_array->prototype == NULL);
2768 			new_op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
2769 			Z_PTR(p->val) = new_op_array;
2770 			memcpy(new_op_array, op_array, sizeof(zend_op_array));
2771 			new_op_array->fn_flags &= ~ZEND_ACC_IMMUTABLE;
2772 			new_op_array->scope = ce;
2773 			ZEND_MAP_PTR_INIT(new_op_array->run_time_cache, NULL);
2774 			ZEND_MAP_PTR_INIT(new_op_array->static_variables_ptr, NULL);
2775 
2776 			zend_update_inherited_handler(constructor);
2777 			zend_update_inherited_handler(destructor);
2778 			zend_update_inherited_handler(clone);
2779 			zend_update_inherited_handler(__get);
2780 			zend_update_inherited_handler(__set);
2781 			zend_update_inherited_handler(__call);
2782 			zend_update_inherited_handler(__isset);
2783 			zend_update_inherited_handler(__unset);
2784 			zend_update_inherited_handler(__tostring);
2785 			zend_update_inherited_handler(__callstatic);
2786 			zend_update_inherited_handler(__debugInfo);
2787 			zend_update_inherited_handler(__serialize);
2788 			zend_update_inherited_handler(__unserialize);
2789 		}
2790 	}
2791 
2792 	/* static members */
2793 	if (ce->default_static_members_table) {
2794 		zval *dst = emalloc(sizeof(zval) * ce->default_static_members_count);
2795 		zval *src = ce->default_static_members_table;
2796 		zval *end = src + ce->default_static_members_count;
2797 
2798 		ce->default_static_members_table = dst;
2799 		for (; src != end; src++, dst++) {
2800 			ZVAL_COPY_VALUE(dst, src);
2801 		}
2802 	}
2803 	ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
2804 
2805 	/* properties_info */
2806 	if (!(HT_FLAGS(&ce->properties_info) & HASH_FLAG_UNINITIALIZED)) {
2807 		p = emalloc(HT_SIZE(&ce->properties_info));
2808 		memcpy(p, HT_GET_DATA_ADDR(&ce->properties_info), HT_USED_SIZE(&ce->properties_info));
2809 		HT_SET_DATA_ADDR(&ce->properties_info, p);
2810 		p = ce->properties_info.arData;
2811 		end = p + ce->properties_info.nNumUsed;
2812 		for (; p != end; p++) {
2813 			zend_property_info *prop_info, *new_prop_info;
2814 
2815 			prop_info = Z_PTR(p->val);
2816 			ZEND_ASSERT(prop_info->ce == pce);
2817 			new_prop_info= zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
2818 			Z_PTR(p->val) = new_prop_info;
2819 			memcpy(new_prop_info, prop_info, sizeof(zend_property_info));
2820 			new_prop_info->ce = ce;
2821 			/* Deep copy the type information */
2822 			zend_type_copy_ctor(&new_prop_info->type, /* use_arena */ true, /* persistent */ false);
2823 		}
2824 	}
2825 
2826 	/* constants table */
2827 	if (!(HT_FLAGS(&ce->constants_table) & HASH_FLAG_UNINITIALIZED)) {
2828 		p = emalloc(HT_SIZE(&ce->constants_table));
2829 		memcpy(p, HT_GET_DATA_ADDR(&ce->constants_table), HT_USED_SIZE(&ce->constants_table));
2830 		HT_SET_DATA_ADDR(&ce->constants_table, p);
2831 		p = ce->constants_table.arData;
2832 		end = p + ce->constants_table.nNumUsed;
2833 		for (; p != end; p++) {
2834 			zend_class_constant *c, *new_c;
2835 
2836 			c = Z_PTR(p->val);
2837 			ZEND_ASSERT(c->ce == pce);
2838 			new_c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
2839 			Z_PTR(p->val) = new_c;
2840 			memcpy(new_c, c, sizeof(zend_class_constant));
2841 			new_c->ce = ce;
2842 		}
2843 	}
2844 
2845 	return ce;
2846 }
2847 
2848 #ifndef ZEND_WIN32
2849 # define UPDATE_IS_CACHEABLE(ce) do { \
2850 			if ((ce)->type == ZEND_USER_CLASS) { \
2851 				is_cacheable &= (ce)->ce_flags; \
2852 			} \
2853 		} while (0)
2854 #else
2855 // TODO: ASLR may cause different addresses in different workers ???
2856 # define UPDATE_IS_CACHEABLE(ce) do { \
2857 			is_cacheable &= (ce)->ce_flags; \
2858 		} while (0)
2859 #endif
2860 
zend_do_link_class(zend_class_entry * ce,zend_string * lc_parent_name,zend_string * key)2861 ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name, zend_string *key) /* {{{ */
2862 {
2863 	/* Load parent/interface dependencies first, so we can still gracefully abort linking
2864 	 * with an exception and remove the class from the class table. This is only possible
2865 	 * if no variance obligations on the current class have been added during autoloading. */
2866 	zend_class_entry *parent = NULL;
2867 	zend_class_entry **traits_and_interfaces = NULL;
2868 	zend_class_entry *proto = NULL;
2869 	zend_class_entry *orig_linking_class;
2870 	uint32_t is_cacheable = ce->ce_flags & ZEND_ACC_IMMUTABLE;
2871 	uint32_t i, j;
2872 	zval *zv;
2873 	ALLOCA_FLAG(use_heap)
2874 
2875 	SET_ALLOCA_FLAG(use_heap);
2876 	ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_LINKED));
2877 
2878 	if (ce->parent_name) {
2879 		parent = zend_fetch_class_by_name(
2880 			ce->parent_name, lc_parent_name,
2881 			ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED | ZEND_FETCH_CLASS_EXCEPTION);
2882 		if (!parent) {
2883 			check_unrecoverable_load_failure(ce);
2884 			return NULL;
2885 		}
2886 		UPDATE_IS_CACHEABLE(parent);
2887 	}
2888 
2889 	if (ce->num_traits || ce->num_interfaces) {
2890 		traits_and_interfaces = do_alloca(sizeof(zend_class_entry*) * (ce->num_traits + ce->num_interfaces), use_heap);
2891 
2892 		for (i = 0; i < ce->num_traits; i++) {
2893 			zend_class_entry *trait = zend_fetch_class_by_name(ce->trait_names[i].name,
2894 				ce->trait_names[i].lc_name, ZEND_FETCH_CLASS_TRAIT);
2895 			if (UNEXPECTED(trait == NULL)) {
2896 				free_alloca(traits_and_interfaces, use_heap);
2897 				return NULL;
2898 			}
2899 			if (UNEXPECTED(!(trait->ce_flags & ZEND_ACC_TRAIT))) {
2900 				zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ZSTR_VAL(ce->name), ZSTR_VAL(trait->name));
2901 				free_alloca(traits_and_interfaces, use_heap);
2902 				return NULL;
2903 			}
2904 			for (j = 0; j < i; j++) {
2905 				if (traits_and_interfaces[j] == trait) {
2906 					/* skip duplications */
2907 					trait = NULL;
2908 					break;
2909 				}
2910 			}
2911 			traits_and_interfaces[i] = trait;
2912 			if (trait) {
2913 				UPDATE_IS_CACHEABLE(trait);
2914 			}
2915 		}
2916 	}
2917 
2918 	if (ce->num_interfaces) {
2919 		for (i = 0; i < ce->num_interfaces; i++) {
2920 			zend_class_entry *iface = zend_fetch_class_by_name(
2921 				ce->interface_names[i].name, ce->interface_names[i].lc_name,
2922 				ZEND_FETCH_CLASS_INTERFACE |
2923 				ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED | ZEND_FETCH_CLASS_EXCEPTION);
2924 			if (!iface) {
2925 				check_unrecoverable_load_failure(ce);
2926 				free_alloca(traits_and_interfaces, use_heap);
2927 				return NULL;
2928 			}
2929 			traits_and_interfaces[ce->num_traits + i] = iface;
2930 			if (iface) {
2931 				UPDATE_IS_CACHEABLE(iface);
2932 			}
2933 		}
2934 	}
2935 
2936 #ifndef ZEND_WIN32
2937 	if (ce->ce_flags & ZEND_ACC_ENUM) {
2938 		/* We will add internal methods. */
2939 		is_cacheable = false;
2940 	}
2941 #endif
2942 
2943 	bool orig_record_errors = EG(record_errors);
2944 
2945 	if (ce->ce_flags & ZEND_ACC_IMMUTABLE && is_cacheable) {
2946 		if (zend_inheritance_cache_get && zend_inheritance_cache_add) {
2947 			zend_class_entry *ret = zend_inheritance_cache_get(ce, parent, traits_and_interfaces);
2948 			if (ret) {
2949 				if (traits_and_interfaces) {
2950 					free_alloca(traits_and_interfaces, use_heap);
2951 				}
2952 				zv = zend_hash_find_known_hash(CG(class_table), key);
2953 				Z_CE_P(zv) = ret;
2954 				return ret;
2955 			}
2956 
2957 			/* Make sure warnings (such as deprecations) thrown during inheritance
2958 			 * will be recorded in the inheritance cache. */
2959 			zend_begin_record_errors();
2960 		} else {
2961 			is_cacheable = 0;
2962 		}
2963 		proto = ce;
2964 	}
2965 
2966 	zend_try {
2967 		if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
2968 			/* Lazy class loading */
2969 			ce = zend_lazy_class_load(ce);
2970 			zv = zend_hash_find_known_hash(CG(class_table), key);
2971 			Z_CE_P(zv) = ce;
2972 		} else if (ce->ce_flags & ZEND_ACC_FILE_CACHED) {
2973 			/* Lazy class loading */
2974 			ce = zend_lazy_class_load(ce);
2975 			ce->ce_flags &= ~ZEND_ACC_FILE_CACHED;
2976 			zv = zend_hash_find_known_hash(CG(class_table), key);
2977 			Z_CE_P(zv) = ce;
2978 		}
2979 
2980 		if (CG(unlinked_uses)) {
2981 			zend_hash_index_del(CG(unlinked_uses), (zend_long)(zend_uintptr_t) ce);
2982 		}
2983 
2984 		orig_linking_class = CG(current_linking_class);
2985 		CG(current_linking_class) = is_cacheable ? ce : NULL;
2986 
2987 		if (ce->ce_flags & ZEND_ACC_ENUM) {
2988 			/* Only register builtin enum methods during inheritance to avoid persisting them in
2989 			 * opcache. */
2990 			zend_enum_register_funcs(ce);
2991 		}
2992 
2993 		if (parent) {
2994 			if (!(parent->ce_flags & ZEND_ACC_LINKED)) {
2995 				add_dependency_obligation(ce, parent);
2996 			}
2997 			zend_do_inheritance(ce, parent);
2998 		}
2999 		if (ce->num_traits) {
3000 			zend_do_bind_traits(ce, traits_and_interfaces);
3001 		}
3002 		if (ce->num_interfaces) {
3003 			/* Also copy the parent interfaces here, so we don't need to reallocate later. */
3004 			uint32_t num_parent_interfaces = parent ? parent->num_interfaces : 0;
3005 			zend_class_entry **interfaces = emalloc(
3006 					sizeof(zend_class_entry *) * (ce->num_interfaces + num_parent_interfaces));
3007 
3008 			if (num_parent_interfaces) {
3009 				memcpy(interfaces, parent->interfaces,
3010 					   sizeof(zend_class_entry *) * num_parent_interfaces);
3011 			}
3012 			memcpy(interfaces + num_parent_interfaces, traits_and_interfaces + ce->num_traits,
3013 				   sizeof(zend_class_entry *) * ce->num_interfaces);
3014 
3015 			zend_do_implement_interfaces(ce, interfaces);
3016 		} else if (parent && parent->num_interfaces) {
3017 			zend_do_inherit_interfaces(ce, parent);
3018 		}
3019 		if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT))
3020 			&& (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
3021 				) {
3022 			zend_verify_abstract_class(ce);
3023 		}
3024 		if (ce->ce_flags & ZEND_ACC_ENUM) {
3025 			zend_verify_enum(ce);
3026 		}
3027 
3028 		/* Normally Stringable is added during compilation. However, if it is imported from a trait,
3029 		 * we need to explicilty add the interface here. */
3030 		if (ce->__tostring && !(ce->ce_flags & ZEND_ACC_TRAIT)
3031 			&& !zend_class_implements_interface(ce, zend_ce_stringable)) {
3032 			ZEND_ASSERT(ce->__tostring->common.fn_flags & ZEND_ACC_TRAIT_CLONE);
3033 			ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES;
3034 			ce->num_interfaces++;
3035 			ce->interfaces = perealloc(ce->interfaces,
3036 									   sizeof(zend_class_entry *) * ce->num_interfaces, ce->type == ZEND_INTERNAL_CLASS);
3037 			ce->interfaces[ce->num_interfaces - 1] = zend_ce_stringable;
3038 			do_interface_implementation(ce, zend_ce_stringable);
3039 		}
3040 
3041 		zend_build_properties_info_table(ce);
3042 	} zend_catch {
3043 		/* Do not leak recorded errors to the next linked class. */
3044 		if (!orig_record_errors) {
3045 			EG(record_errors) = false;
3046 			zend_free_recorded_errors();
3047 		}
3048 		zend_bailout();
3049 	} zend_end_try();
3050 
3051 	EG(record_errors) = orig_record_errors;
3052 
3053 	if (!(ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE)) {
3054 		ce->ce_flags |= ZEND_ACC_LINKED;
3055 	} else {
3056 		ce->ce_flags |= ZEND_ACC_NEARLY_LINKED;
3057 		if (CG(current_linking_class)) {
3058 			ce->ce_flags |= ZEND_ACC_CACHEABLE;
3059 		}
3060 		load_delayed_classes(ce);
3061 		if (ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE) {
3062 			resolve_delayed_variance_obligations(ce);
3063 		}
3064 		if (ce->ce_flags & ZEND_ACC_CACHEABLE) {
3065 			ce->ce_flags &= ~ZEND_ACC_CACHEABLE;
3066 		} else {
3067 			CG(current_linking_class) = NULL;
3068 		}
3069 	}
3070 
3071 	if (!CG(current_linking_class)) {
3072 		is_cacheable = 0;
3073 	}
3074 	CG(current_linking_class) = orig_linking_class;
3075 
3076 	if (is_cacheable) {
3077 		HashTable *ht = (HashTable*)ce->inheritance_cache;
3078 		zend_class_entry *new_ce;
3079 
3080 		ce->inheritance_cache = NULL;
3081 		new_ce = zend_inheritance_cache_add(ce, proto, parent, traits_and_interfaces, ht);
3082 		if (new_ce) {
3083 			zv = zend_hash_find_known_hash(CG(class_table), key);
3084 			ce = new_ce;
3085 			Z_CE_P(zv) = ce;
3086 		}
3087 		if (ht) {
3088 			zend_hash_destroy(ht);
3089 			FREE_HASHTABLE(ht);
3090 		}
3091 	}
3092 
3093 	if (!orig_record_errors) {
3094 		zend_free_recorded_errors();
3095 	}
3096 	if (traits_and_interfaces) {
3097 		free_alloca(traits_and_interfaces, use_heap);
3098 	}
3099 
3100 	if (ZSTR_HAS_CE_CACHE(ce->name)) {
3101 		ZSTR_SET_CE_CACHE(ce->name, ce);
3102 	}
3103 
3104 	return ce;
3105 }
3106 /* }}} */
3107 
3108 /* Check whether early binding is prevented due to unresolved types in inheritance checks. */
zend_can_early_bind(zend_class_entry * ce,zend_class_entry * parent_ce)3109 static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */
3110 {
3111 	zend_string *key;
3112 	zend_function *parent_func;
3113 	zend_property_info *parent_info;
3114 	inheritance_status overall_status = INHERITANCE_SUCCESS;
3115 
3116 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, parent_func) {
3117 		zval *zv = zend_hash_find_known_hash(&ce->function_table, key);
3118 		if (zv) {
3119 			zend_function *child_func = Z_FUNC_P(zv);
3120 			inheritance_status status =
3121 				do_inheritance_check_on_method(
3122 					child_func, child_func->common.scope,
3123 					parent_func, parent_func->common.scope,
3124 					ce, NULL,
3125 					ZEND_INHERITANCE_CHECK_SILENT | ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY);
3126 			if (UNEXPECTED(status == INHERITANCE_WARNING)) {
3127 				overall_status = INHERITANCE_WARNING;
3128 			} else if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
3129 				return status;
3130 			}
3131 		}
3132 	} ZEND_HASH_FOREACH_END();
3133 
3134 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, parent_info) {
3135 		zval *zv;
3136 		if ((parent_info->flags & ZEND_ACC_PRIVATE) || !ZEND_TYPE_IS_SET(parent_info->type)) {
3137 			continue;
3138 		}
3139 
3140 		zv = zend_hash_find_known_hash(&ce->properties_info, key);
3141 		if (zv) {
3142 			zend_property_info *child_info = Z_PTR_P(zv);
3143 			if (ZEND_TYPE_IS_SET(child_info->type)) {
3144 				inheritance_status status = property_types_compatible(parent_info, child_info);
3145 				ZEND_ASSERT(status != INHERITANCE_WARNING);
3146 				if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
3147 					return status;
3148 				}
3149 			}
3150 		}
3151 	} ZEND_HASH_FOREACH_END();
3152 
3153 	return overall_status;
3154 }
3155 /* }}} */
3156 
register_early_bound_ce(zval * delayed_early_binding,zend_string * lcname,zend_class_entry * ce)3157 static zend_always_inline bool register_early_bound_ce(zval *delayed_early_binding, zend_string *lcname, zend_class_entry *ce) {
3158 	if (delayed_early_binding) {
3159 		if (EXPECTED(!(ce->ce_flags & ZEND_ACC_PRELOADED))) {
3160 			if (zend_hash_set_bucket_key(EG(class_table), (Bucket *)delayed_early_binding, lcname) != NULL) {
3161 				Z_CE_P(delayed_early_binding) = ce;
3162 				return true;
3163 			}
3164 		} else {
3165 			/* If preloading is used, don't replace the existing bucket, add a new one. */
3166 			if (zend_hash_add_ptr(EG(class_table), lcname, ce) != NULL) {
3167 				return true;
3168 			}
3169 		}
3170 		zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
3171 		return false;
3172 	}
3173 	if (zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL) {
3174 		return true;
3175 	}
3176 	return false;
3177 }
3178 
zend_try_early_bind(zend_class_entry * ce,zend_class_entry * parent_ce,zend_string * lcname,zval * delayed_early_binding)3179 ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce, zend_string *lcname, zval *delayed_early_binding) /* {{{ */
3180 {
3181 	inheritance_status status;
3182 	zend_class_entry *proto = NULL;
3183 	zend_class_entry *orig_linking_class;
3184 	uint32_t is_cacheable = ce->ce_flags & ZEND_ACC_IMMUTABLE;
3185 
3186 	UPDATE_IS_CACHEABLE(parent_ce);
3187 	if (is_cacheable) {
3188 		if (zend_inheritance_cache_get && zend_inheritance_cache_add) {
3189 			zend_class_entry *ret = zend_inheritance_cache_get(ce, parent_ce, NULL);
3190 			if (ret) {
3191 				if (UNEXPECTED(!register_early_bound_ce(delayed_early_binding, lcname, ret))) {
3192 					return NULL;
3193 				}
3194 				zend_observer_class_linked_notify(ret, lcname);
3195 				return ret;
3196 			}
3197 		} else {
3198 			is_cacheable = 0;
3199 		}
3200 		proto = ce;
3201 	}
3202 
3203 	orig_linking_class = CG(current_linking_class);
3204 	CG(current_linking_class) = NULL;
3205 	status = zend_can_early_bind(ce, parent_ce);
3206 	CG(current_linking_class) = orig_linking_class;
3207 	if (EXPECTED(status != INHERITANCE_UNRESOLVED)) {
3208 		if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
3209 			/* Lazy class loading */
3210 			ce = zend_lazy_class_load(ce);
3211 		} else if (ce->ce_flags & ZEND_ACC_FILE_CACHED) {
3212 			/* Lazy class loading */
3213 			ce = zend_lazy_class_load(ce);
3214 			ce->ce_flags &= ~ZEND_ACC_FILE_CACHED;
3215 		}
3216 
3217 		if (UNEXPECTED(!register_early_bound_ce(delayed_early_binding, lcname, ce))) {
3218 			return NULL;
3219 		}
3220 
3221 		orig_linking_class = CG(current_linking_class);
3222 		CG(current_linking_class) = is_cacheable ? ce : NULL;
3223 
3224 		zend_try{
3225 			if (is_cacheable) {
3226 				zend_begin_record_errors();
3227 			}
3228 
3229 			zend_do_inheritance_ex(ce, parent_ce, status == INHERITANCE_SUCCESS);
3230 			if (parent_ce && parent_ce->num_interfaces) {
3231 				zend_do_inherit_interfaces(ce, parent_ce);
3232 			}
3233 			zend_build_properties_info_table(ce);
3234 			if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
3235 				zend_verify_abstract_class(ce);
3236 			}
3237 			ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE));
3238 			ce->ce_flags |= ZEND_ACC_LINKED;
3239 
3240 			CG(current_linking_class) = orig_linking_class;
3241 		} zend_catch {
3242 			EG(record_errors) = false;
3243 			zend_free_recorded_errors();
3244 			zend_bailout();
3245 		} zend_end_try();
3246 
3247 		EG(record_errors) = false;
3248 
3249 		if (is_cacheable) {
3250 			HashTable *ht = (HashTable*)ce->inheritance_cache;
3251 			zend_class_entry *new_ce;
3252 
3253 			ce->inheritance_cache = NULL;
3254 			new_ce = zend_inheritance_cache_add(ce, proto, parent_ce, NULL, ht);
3255 			if (new_ce) {
3256 				zval *zv = zend_hash_find_known_hash(CG(class_table), lcname);
3257 				ce = new_ce;
3258 				Z_CE_P(zv) = ce;
3259 			}
3260 			if (ht) {
3261 				zend_hash_destroy(ht);
3262 				FREE_HASHTABLE(ht);
3263 			}
3264 		}
3265 
3266 		if (ZSTR_HAS_CE_CACHE(ce->name)) {
3267 			ZSTR_SET_CE_CACHE(ce->name, ce);
3268 		}
3269 		zend_observer_class_linked_notify(ce, lcname);
3270 
3271 		return ce;
3272 	}
3273 	return NULL;
3274 }
3275 /* }}} */
3276