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