xref: /php-src/Zend/zend_inheritance.c (revision 86b93bc4)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend license,     |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Andi Gutmans <andi@php.net>                                 |
16    |          Zeev Suraski <zeev@php.net>                                 |
17    +----------------------------------------------------------------------+
18 */
19 
20 #include "zend.h"
21 #include "zend_API.h"
22 #include "zend_compile.h"
23 #include "zend_execute.h"
24 #include "zend_inheritance.h"
25 #include "zend_interfaces.h"
26 #include "zend_smart_str.h"
27 #include "zend_operators.h"
28 #include "zend_exceptions.h"
29 #include "zend_enum.h"
30 #include "zend_attributes.h"
31 #include "zend_constants.h"
32 #include "zend_observer.h"
33 
34 ZEND_API zend_class_entry* (*zend_inheritance_cache_get)(zend_class_entry *ce, zend_class_entry *parent, zend_class_entry **traits_and_interfaces) = NULL;
35 ZEND_API zend_class_entry* (*zend_inheritance_cache_add)(zend_class_entry *ce, zend_class_entry *proto, zend_class_entry *parent, zend_class_entry **traits_and_interfaces, HashTable *dependencies) = NULL;
36 
37 /* Unresolved means that class declarations that are currently not available are needed to
38  * determine whether the inheritance is valid or not. At runtime UNRESOLVED should be treated
39  * as an ERROR. */
40 typedef enum {
41 	INHERITANCE_UNRESOLVED = -1,
42 	INHERITANCE_ERROR = 0,
43 	INHERITANCE_WARNING = 1,
44 	INHERITANCE_SUCCESS = 2,
45 } inheritance_status;
46 
47 static void add_dependency_obligation(zend_class_entry *ce, zend_class_entry *dependency_ce);
48 static void add_compatibility_obligation(
49 		zend_class_entry *ce, const zend_function *child_fn, zend_class_entry *child_scope,
50 		const zend_function *parent_fn, zend_class_entry *parent_scope);
51 static void add_property_compatibility_obligation(
52 		zend_class_entry *ce, const zend_property_info *child_prop,
53 		const zend_property_info *parent_prop);
54 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 = (zend_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 static 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 (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 				/* We don't have to account for refcounting because
1547 				 * zend_declare_typed_property() disallows refcounted defaults for internal classes. */
1548 				ZEND_ASSERT(!Z_REFCOUNTED_P(src));
1549 				ZVAL_COPY_VALUE_PROP(dst, src);
1550 				if (Z_OPT_TYPE_P(dst) == IS_CONSTANT_AST) {
1551 					ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
1552 					ce->ce_flags |= ZEND_ACC_HAS_AST_PROPERTIES;
1553 				}
1554 				continue;
1555 			} while (dst != end);
1556 		} else {
1557 			do {
1558 				dst--;
1559 				src--;
1560 				ZVAL_COPY_PROP(dst, src);
1561 				if (Z_OPT_TYPE_P(dst) == IS_CONSTANT_AST) {
1562 					ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
1563 					ce->ce_flags |= ZEND_ACC_HAS_AST_PROPERTIES;
1564 				}
1565 				continue;
1566 			} while (dst != end);
1567 		}
1568 		ce->default_properties_count += parent_ce->default_properties_count;
1569 	}
1570 
1571 	if (parent_ce->default_static_members_count) {
1572 		zval *src, *dst, *end;
1573 
1574 		if (ce->default_static_members_count) {
1575 			zval *table = pemalloc(sizeof(zval) * (ce->default_static_members_count + parent_ce->default_static_members_count), ce->type == ZEND_INTERNAL_CLASS);
1576 			src = ce->default_static_members_table + ce->default_static_members_count;
1577 			end = table + parent_ce->default_static_members_count;
1578 			dst = end + ce->default_static_members_count;
1579 			ce->default_static_members_table = table;
1580 			do {
1581 				dst--;
1582 				src--;
1583 				ZVAL_COPY_VALUE(dst, src);
1584 			} while (dst != end);
1585 			pefree(src, ce->type == ZEND_INTERNAL_CLASS);
1586 			end = ce->default_static_members_table;
1587 		} else {
1588 			end = pemalloc(sizeof(zval) * parent_ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
1589 			dst = end + parent_ce->default_static_members_count;
1590 			ce->default_static_members_table = end;
1591 		}
1592 		src = parent_ce->default_static_members_table + parent_ce->default_static_members_count;
1593 		do {
1594 			dst--;
1595 			src--;
1596 			if (Z_TYPE_P(src) == IS_INDIRECT) {
1597 				ZVAL_INDIRECT(dst, Z_INDIRECT_P(src));
1598 			} else {
1599 				ZVAL_INDIRECT(dst, src);
1600 			}
1601 			if (Z_TYPE_P(Z_INDIRECT_P(dst)) == IS_CONSTANT_AST) {
1602 				ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
1603 				ce->ce_flags |= ZEND_ACC_HAS_AST_STATICS;
1604 			}
1605 		} while (dst != end);
1606 		ce->default_static_members_count += parent_ce->default_static_members_count;
1607 		if (!ZEND_MAP_PTR(ce->static_members_table)) {
1608 			if (ce->type == ZEND_INTERNAL_CLASS &&
1609 					ce->info.internal.module->type == MODULE_PERSISTENT) {
1610 				ZEND_MAP_PTR_NEW(ce->static_members_table);
1611 			}
1612 		}
1613 	}
1614 
1615 	ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, property_info) {
1616 		if (property_info->ce == ce) {
1617 			if (property_info->flags & ZEND_ACC_STATIC) {
1618 				property_info->offset += parent_ce->default_static_members_count;
1619 			} else {
1620 				property_info->offset += parent_ce->default_properties_count * sizeof(zval);
1621 			}
1622 		}
1623 	} ZEND_HASH_FOREACH_END();
1624 
1625 	if (zend_hash_num_elements(&parent_ce->properties_info)) {
1626 		zend_hash_extend(&ce->properties_info,
1627 			zend_hash_num_elements(&ce->properties_info) +
1628 			zend_hash_num_elements(&parent_ce->properties_info), 0);
1629 
1630 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, property_info) {
1631 			do_inherit_property(property_info, key, ce);
1632 		} ZEND_HASH_FOREACH_END();
1633 	}
1634 
1635 	if (zend_hash_num_elements(&parent_ce->constants_table)) {
1636 		zend_class_constant *c;
1637 
1638 		zend_hash_extend(&ce->constants_table,
1639 			zend_hash_num_elements(&ce->constants_table) +
1640 			zend_hash_num_elements(&parent_ce->constants_table), 0);
1641 
1642 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->constants_table, key, c) {
1643 			do_inherit_class_constant(key, c, ce);
1644 		} ZEND_HASH_FOREACH_END();
1645 	}
1646 
1647 	if (zend_hash_num_elements(&parent_ce->function_table)) {
1648 		zend_hash_extend(&ce->function_table,
1649 			zend_hash_num_elements(&ce->function_table) +
1650 			zend_hash_num_elements(&parent_ce->function_table), 0);
1651 		uint32_t flags =
1652 			ZEND_INHERITANCE_LAZY_CHILD_CLONE |
1653 			ZEND_INHERITANCE_SET_CHILD_CHANGED |
1654 			ZEND_INHERITANCE_SET_CHILD_PROTO |
1655 			ZEND_INHERITANCE_RESET_CHILD_OVERRIDE;
1656 
1657 		if (!checked) {
1658 			flags |= ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY;
1659 		}
1660 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, func) {
1661 			do_inherit_method(key, func, ce, 0, flags);
1662 		} ZEND_HASH_FOREACH_END();
1663 	}
1664 
1665 	do_inherit_parent_constructor(ce);
1666 
1667 	if (ce->type == ZEND_INTERNAL_CLASS) {
1668 		if (parent_ce->num_interfaces) {
1669 			zend_do_inherit_interfaces(ce, parent_ce);
1670 		}
1671 
1672 		if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
1673 			ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
1674 		}
1675 	}
1676 	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);
1677 }
1678 /* }}} */
1679 
check_trait_property_or_constant_value_compatibility(zend_class_entry * ce,zval * op1,zval * op2)1680 static zend_always_inline bool check_trait_property_or_constant_value_compatibility(zend_class_entry *ce, zval *op1, zval *op2) /* {{{ */
1681 {
1682 	bool is_compatible;
1683 	zval op1_tmp, op2_tmp;
1684 
1685 	/* if any of the values is a constant, we try to resolve it */
1686 	if (UNEXPECTED(Z_TYPE_P(op1) == IS_CONSTANT_AST)) {
1687 		ZVAL_COPY_OR_DUP(&op1_tmp, op1);
1688 		if (UNEXPECTED(zval_update_constant_ex(&op1_tmp, ce) != SUCCESS)) {
1689 			zval_ptr_dtor(&op1_tmp);
1690 			return false;
1691 		}
1692 		op1 = &op1_tmp;
1693 	}
1694 	if (UNEXPECTED(Z_TYPE_P(op2) == IS_CONSTANT_AST)) {
1695 		ZVAL_COPY_OR_DUP(&op2_tmp, op2);
1696 		if (UNEXPECTED(zval_update_constant_ex(&op2_tmp, ce) != SUCCESS)) {
1697 			zval_ptr_dtor(&op2_tmp);
1698 			return false;
1699 		}
1700 		op2 = &op2_tmp;
1701 	}
1702 
1703 	is_compatible = fast_is_identical_function(op1, op2);
1704 
1705 	if (op1 == &op1_tmp) {
1706 		zval_ptr_dtor_nogc(&op1_tmp);
1707 	}
1708 	if (op2 == &op2_tmp) {
1709 		zval_ptr_dtor_nogc(&op2_tmp);
1710 	}
1711 
1712 	return is_compatible;
1713 }
1714 /* }}} */
1715 
1716 /** @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)1717 static bool do_inherit_constant_check(
1718 	zend_class_entry *ce, zend_class_constant *parent_constant, zend_string *name
1719 ) {
1720 	zval *zv = zend_hash_find_known_hash(&ce->constants_table, name);
1721 	if (zv == NULL) {
1722 		return true;
1723 	}
1724 
1725 	zend_class_constant *child_constant = Z_PTR_P(zv);
1726 	if (parent_constant->ce != child_constant->ce && (ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_FINAL)) {
1727 		zend_error_noreturn(E_COMPILE_ERROR, "%s::%s cannot override final constant %s::%s",
1728 			ZSTR_VAL(child_constant->ce->name), ZSTR_VAL(name),
1729 			ZSTR_VAL(parent_constant->ce->name), ZSTR_VAL(name)
1730 		);
1731 	}
1732 
1733 	if (child_constant->ce != parent_constant->ce && child_constant->ce != ce) {
1734 		zend_error_noreturn(E_COMPILE_ERROR,
1735 			"%s %s inherits both %s::%s and %s::%s, which is ambiguous",
1736 			zend_get_object_type_uc(ce),
1737 			ZSTR_VAL(ce->name),
1738 			ZSTR_VAL(child_constant->ce->name), ZSTR_VAL(name),
1739 			ZSTR_VAL(parent_constant->ce->name), ZSTR_VAL(name));
1740 	}
1741 
1742 	if (UNEXPECTED((ZEND_CLASS_CONST_FLAGS(child_constant) & ZEND_ACC_PPP_MASK) > (ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_PPP_MASK))) {
1743 		zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s must be %s (as in %s %s)%s",
1744 			ZSTR_VAL(ce->name), ZSTR_VAL(name),
1745 			zend_visibility_string(ZEND_CLASS_CONST_FLAGS(parent_constant)),
1746 			zend_get_object_type(parent_constant->ce),
1747 			ZSTR_VAL(parent_constant->ce->name),
1748 			(ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_PUBLIC) ? "" : " or weaker"
1749 		);
1750 	}
1751 
1752 	if (!(ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_PRIVATE) && ZEND_TYPE_IS_SET(parent_constant->type)) {
1753 		inheritance_status status = class_constant_types_compatible(parent_constant, child_constant);
1754 		if (status == INHERITANCE_ERROR) {
1755 			emit_incompatible_class_constant_error(child_constant, parent_constant, name);
1756 		} else if (status == INHERITANCE_UNRESOLVED) {
1757 			add_class_constant_compatibility_obligation(ce, child_constant, parent_constant, name);
1758 		}
1759 	}
1760 
1761 	return false;
1762 }
1763 /* }}} */
1764 
do_inherit_iface_constant(zend_string * name,zend_class_constant * c,zend_class_entry * ce,zend_class_entry * iface)1765 static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
1766 {
1767 	if (do_inherit_constant_check(ce, c, name)) {
1768 		zend_class_constant *ct;
1769 		if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1770 			ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
1771 			ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
1772 			if (iface->ce_flags & ZEND_ACC_IMMUTABLE) {
1773 				ct = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
1774 				memcpy(ct, c, sizeof(zend_class_constant));
1775 				c = ct;
1776 				Z_CONSTANT_FLAGS(c->value) |= CONST_OWNED;
1777 			}
1778 		}
1779 		if (ce->type & ZEND_INTERNAL_CLASS) {
1780 			ct = pemalloc(sizeof(zend_class_constant), 1);
1781 			memcpy(ct, c, sizeof(zend_class_constant));
1782 			c = ct;
1783 		}
1784 		zend_hash_update_ptr(&ce->constants_table, name, c);
1785 	}
1786 }
1787 /* }}} */
1788 
do_interface_implementation(zend_class_entry * ce,zend_class_entry * iface)1789 static void do_interface_implementation(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
1790 {
1791 	zend_function *func;
1792 	zend_string *key;
1793 	zend_class_constant *c;
1794 	uint32_t flags = ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY;
1795 
1796 	if (!(ce->ce_flags & ZEND_ACC_INTERFACE)) {
1797 		/* We are not setting the prototype of overridden interface methods because of abstract
1798 		 * constructors. See Zend/tests/interface_constructor_prototype_001.phpt. */
1799 		flags |=
1800 			ZEND_INHERITANCE_LAZY_CHILD_CLONE |
1801 			ZEND_INHERITANCE_SET_CHILD_PROTO |
1802 			ZEND_INHERITANCE_RESET_CHILD_OVERRIDE;
1803 	} else {
1804 		flags |=
1805 			ZEND_INHERITANCE_LAZY_CHILD_CLONE |
1806 			ZEND_INHERITANCE_RESET_CHILD_OVERRIDE;
1807 	}
1808 
1809 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) {
1810 		do_inherit_iface_constant(key, c, ce, iface);
1811 	} ZEND_HASH_FOREACH_END();
1812 
1813 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) {
1814 		do_inherit_method(key, func, ce, 1, flags);
1815 	} ZEND_HASH_FOREACH_END();
1816 
1817 	do_implement_interface(ce, iface);
1818 	if (iface->num_interfaces) {
1819 		zend_do_inherit_interfaces(ce, iface);
1820 	}
1821 }
1822 /* }}} */
1823 
zend_do_implement_interface(zend_class_entry * ce,zend_class_entry * iface)1824 ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
1825 {
1826 	uint32_t i, ignore = 0;
1827 	uint32_t current_iface_num = ce->num_interfaces;
1828 	uint32_t parent_iface_num  = ce->parent ? ce->parent->num_interfaces : 0;
1829 	zend_string *key;
1830 	zend_class_constant *c;
1831 
1832 	ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
1833 
1834 	for (i = 0; i < ce->num_interfaces; i++) {
1835 		if (ce->interfaces[i] == NULL) {
1836 			memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
1837 			i--;
1838 		} else if (ce->interfaces[i] == iface) {
1839 			if (EXPECTED(i < parent_iface_num)) {
1840 				ignore = 1;
1841 			} else {
1842 				zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
1843 			}
1844 		}
1845 	}
1846 	if (ignore) {
1847 		/* Check for attempt to redeclare interface constants */
1848 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) {
1849 			do_inherit_constant_check(ce, c, key);
1850 		} ZEND_HASH_FOREACH_END();
1851 	} else {
1852 		if (ce->num_interfaces >= current_iface_num) {
1853 			if (ce->type == ZEND_INTERNAL_CLASS) {
1854 				ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
1855 			} else {
1856 				ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
1857 			}
1858 		}
1859 		ce->interfaces[ce->num_interfaces++] = iface;
1860 
1861 		do_interface_implementation(ce, iface);
1862 	}
1863 }
1864 /* }}} */
1865 
zend_do_implement_interfaces(zend_class_entry * ce,zend_class_entry ** interfaces)1866 static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry **interfaces) /* {{{ */
1867 {
1868 	zend_class_entry *iface;
1869 	uint32_t num_parent_interfaces = ce->parent ? ce->parent->num_interfaces : 0;
1870 	uint32_t num_interfaces = num_parent_interfaces;
1871 	zend_string *key;
1872 	zend_class_constant *c;
1873 	uint32_t i, j;
1874 
1875 	for (i = 0; i < ce->num_interfaces; i++) {
1876 		iface = interfaces[num_parent_interfaces + i];
1877 		if (!(iface->ce_flags & ZEND_ACC_LINKED)) {
1878 			add_dependency_obligation(ce, iface);
1879 		}
1880 		if (UNEXPECTED(!(iface->ce_flags & ZEND_ACC_INTERFACE))) {
1881 			efree(interfaces);
1882 			zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
1883 			return;
1884 		}
1885 		for (j = 0; j < num_interfaces; j++) {
1886 			if (interfaces[j] == iface) {
1887 				if (j >= num_parent_interfaces) {
1888 					efree(interfaces);
1889 					zend_error_noreturn(E_COMPILE_ERROR, "%s %s cannot implement previously implemented interface %s",
1890 						zend_get_object_type_uc(ce),
1891 						ZSTR_VAL(ce->name),
1892 						ZSTR_VAL(iface->name));
1893 					return;
1894 				}
1895 				/* skip duplications */
1896 				ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) {
1897 					do_inherit_constant_check(ce, c, key);
1898 				} ZEND_HASH_FOREACH_END();
1899 
1900 				iface = NULL;
1901 				break;
1902 			}
1903 		}
1904 		if (iface) {
1905 			interfaces[num_interfaces] = iface;
1906 			num_interfaces++;
1907 		}
1908 	}
1909 
1910 	if (!(ce->ce_flags & ZEND_ACC_CACHED)) {
1911 		for (i = 0; i < ce->num_interfaces; i++) {
1912 			zend_string_release_ex(ce->interface_names[i].name, 0);
1913 			zend_string_release_ex(ce->interface_names[i].lc_name, 0);
1914 		}
1915 		efree(ce->interface_names);
1916 	}
1917 
1918 	ce->num_interfaces = num_interfaces;
1919 	ce->interfaces = interfaces;
1920 	ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES;
1921 
1922 	for (i = 0; i < num_parent_interfaces; i++) {
1923 		do_implement_interface(ce, ce->interfaces[i]);
1924 	}
1925 	/* Note that new interfaces can be added during this loop due to interface inheritance.
1926 	 * Use num_interfaces rather than ce->num_interfaces to not re-process the new ones. */
1927 	for (; i < num_interfaces; i++) {
1928 		do_interface_implementation(ce, ce->interfaces[i]);
1929 	}
1930 }
1931 /* }}} */
1932 
1933 
zend_inheritance_check_override(zend_class_entry * ce)1934 void zend_inheritance_check_override(zend_class_entry *ce)
1935 {
1936 	zend_function *f;
1937 
1938 	if (ce->ce_flags & ZEND_ACC_TRAIT) {
1939 		return;
1940 	}
1941 
1942 	ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, f) {
1943 		if (f->common.fn_flags & ZEND_ACC_OVERRIDE) {
1944 			ZEND_ASSERT(f->type != ZEND_INTERNAL_FUNCTION);
1945 
1946 			zend_error_at_noreturn(
1947 				E_COMPILE_ERROR, f->op_array.filename, f->op_array.line_start,
1948 				"%s::%s() has #[\\Override] attribute, but no matching parent method exists",
1949 				ZEND_FN_SCOPE_NAME(f), ZSTR_VAL(f->common.function_name));
1950 		}
1951 	} ZEND_HASH_FOREACH_END();
1952 }
1953 
1954 
fixup_trait_scope(const zend_function * fn,zend_class_entry * ce)1955 static zend_class_entry *fixup_trait_scope(const zend_function *fn, zend_class_entry *ce)
1956 {
1957 	/* self in trait methods should be resolved to the using class, not the trait. */
1958 	return fn->common.scope->ce_flags & ZEND_ACC_TRAIT ? ce : fn->common.scope;
1959 }
1960 
zend_add_trait_method(zend_class_entry * ce,zend_string * name,zend_string * key,zend_function * fn)1961 static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_string *key, zend_function *fn) /* {{{ */
1962 {
1963 	zend_function *existing_fn = NULL;
1964 	zend_function *new_fn;
1965 	bool check_inheritance = false;
1966 
1967 	if ((existing_fn = zend_hash_find_ptr(&ce->function_table, key)) != NULL) {
1968 		/* if it is the same function with the same visibility and has not been assigned a class scope yet, regardless
1969 		 * of where it is coming from there is no conflict and we do not need to add it again */
1970 		if (existing_fn->op_array.opcodes == fn->op_array.opcodes &&
1971 			(existing_fn->common.fn_flags & ZEND_ACC_PPP_MASK) == (fn->common.fn_flags & ZEND_ACC_PPP_MASK) &&
1972 			(existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
1973 			return;
1974 		}
1975 
1976 		/* Abstract method signatures from the trait must be satisfied. */
1977 		if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
1978 			/* "abstract private" methods in traits were not available prior to PHP 8.
1979 			 * As such, "abstract protected" was sometimes used to indicate trait requirements,
1980 			 * even though the "implementing" method was private. Do not check visibility
1981 			 * requirements to maintain backwards-compatibility with such usage.
1982 			 */
1983 			do_inheritance_check_on_method(
1984 				existing_fn, fixup_trait_scope(existing_fn, ce), fn, fixup_trait_scope(fn, ce),
1985 				ce, NULL, ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_RESET_CHILD_OVERRIDE);
1986 			return;
1987 		}
1988 
1989 		if (existing_fn->common.scope == ce) {
1990 			/* members from the current class override trait methods */
1991 			return;
1992 		} else if (UNEXPECTED((existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT)
1993 				&& !(existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT))) {
1994 			/* two traits can't define the same non-abstract method */
1995 			zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s::%s has not been applied as %s::%s, because of collision with %s::%s",
1996 				ZSTR_VAL(fn->common.scope->name), ZSTR_VAL(fn->common.function_name),
1997 				ZSTR_VAL(ce->name), ZSTR_VAL(name),
1998 				ZSTR_VAL(existing_fn->common.scope->name), ZSTR_VAL(existing_fn->common.function_name));
1999 		} else {
2000 			check_inheritance = true;
2001 		}
2002 	}
2003 
2004 	if (UNEXPECTED(fn->type == ZEND_INTERNAL_FUNCTION)) {
2005 		new_fn = zend_arena_alloc(&CG(arena), sizeof(zend_internal_function));
2006 		memcpy(new_fn, fn, sizeof(zend_internal_function));
2007 		new_fn->common.fn_flags |= ZEND_ACC_ARENA_ALLOCATED;
2008 	} else {
2009 		new_fn = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
2010 		memcpy(new_fn, fn, sizeof(zend_op_array));
2011 		new_fn->op_array.fn_flags &= ~ZEND_ACC_IMMUTABLE;
2012 	}
2013 	new_fn->common.fn_flags |= ZEND_ACC_TRAIT_CLONE;
2014 
2015 	/* Reassign method name, in case it is an alias. */
2016 	new_fn->common.function_name = name;
2017 	function_add_ref(new_fn);
2018 	fn = zend_hash_update_ptr(&ce->function_table, key, new_fn);
2019 	zend_add_magic_method(ce, fn, key);
2020 
2021 	if (check_inheritance) {
2022 		/* Inherited members are overridden by members inserted by traits.
2023 		 * Check whether the trait method fulfills the inheritance requirements. */
2024 		uint32_t flags = ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY;
2025 		if (!(existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT)) {
2026 			flags |= ZEND_INHERITANCE_SET_CHILD_CHANGED |ZEND_INHERITANCE_SET_CHILD_PROTO |
2027 				ZEND_INHERITANCE_RESET_CHILD_OVERRIDE;
2028 		}
2029 		do_inheritance_check_on_method(
2030 			fn, fixup_trait_scope(fn, ce), existing_fn, fixup_trait_scope(existing_fn, ce),
2031 			ce, NULL, flags);
2032 	}
2033 }
2034 /* }}} */
2035 
zend_fixup_trait_method(zend_function * fn,zend_class_entry * ce)2036 static void zend_fixup_trait_method(zend_function *fn, zend_class_entry *ce) /* {{{ */
2037 {
2038 	if ((fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
2039 
2040 		fn->common.scope = ce;
2041 
2042 		if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
2043 			ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2044 		}
2045 		if (fn->type == ZEND_USER_FUNCTION && fn->op_array.static_variables) {
2046 			ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
2047 		}
2048 	}
2049 }
2050 /* }}} */
2051 
zend_traits_check_private_final_inheritance(uint32_t original_fn_flags,zend_function * fn_copy,zend_string * name)2052 static void zend_traits_check_private_final_inheritance(uint32_t original_fn_flags, zend_function *fn_copy, zend_string *name)
2053 {
2054 	/* If the function was originally already private+final, then it will have already been warned about.
2055 	 * If the function became private+final only after applying modifiers, we need to emit the same warning. */
2056 	if ((original_fn_flags & (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)) != (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
2057 		&& (fn_copy->common.fn_flags & (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)) == (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
2058 		&& !zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2059 		zend_error(E_COMPILE_WARNING, "Private methods cannot be final as they are never overridden by other classes");
2060 	}
2061 }
2062 
zend_traits_copy_functions(zend_string * fnname,zend_function * fn,zend_class_entry * ce,HashTable * exclude_table,zend_class_entry ** aliases)2063 static void zend_traits_copy_functions(zend_string *fnname, zend_function *fn, zend_class_entry *ce, HashTable *exclude_table, zend_class_entry **aliases) /* {{{ */
2064 {
2065 	zend_trait_alias  *alias, **alias_ptr;
2066 	zend_string       *lcname;
2067 	zend_function      fn_copy;
2068 	int                i;
2069 
2070 	/* apply aliases which are qualified with a class name, there should not be any ambiguity */
2071 	if (ce->trait_aliases) {
2072 		alias_ptr = ce->trait_aliases;
2073 		alias = *alias_ptr;
2074 		i = 0;
2075 		while (alias) {
2076 			/* Scope unset or equal to the function we compare to, and the alias applies to fn */
2077 			if (alias->alias != NULL
2078 				&& fn->common.scope == aliases[i]
2079 				&& zend_string_equals_ci(alias->trait_method.method_name, fnname)
2080 			) {
2081 				fn_copy = *fn;
2082 				if (alias->modifiers & ZEND_ACC_PPP_MASK) {
2083 					fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags & ~ZEND_ACC_PPP_MASK);
2084 				} else {
2085 					fn_copy.common.fn_flags = alias->modifiers | fn->common.fn_flags;
2086 				}
2087 
2088 				zend_traits_check_private_final_inheritance(fn->common.fn_flags, &fn_copy, alias->alias);
2089 
2090 				lcname = zend_string_tolower(alias->alias);
2091 				zend_add_trait_method(ce, alias->alias, lcname, &fn_copy);
2092 				zend_string_release_ex(lcname, 0);
2093 			}
2094 			alias_ptr++;
2095 			alias = *alias_ptr;
2096 			i++;
2097 		}
2098 	}
2099 
2100 	if (exclude_table == NULL || zend_hash_find(exclude_table, fnname) == NULL) {
2101 		/* is not in hashtable, thus, function is not to be excluded */
2102 		memcpy(&fn_copy, fn, fn->type == ZEND_USER_FUNCTION ? sizeof(zend_op_array) : sizeof(zend_internal_function));
2103 
2104 		/* apply aliases which have not alias name, just setting visibility */
2105 		if (ce->trait_aliases) {
2106 			alias_ptr = ce->trait_aliases;
2107 			alias = *alias_ptr;
2108 			i = 0;
2109 			while (alias) {
2110 				/* Scope unset or equal to the function we compare to, and the alias applies to fn */
2111 				if (alias->alias == NULL && alias->modifiers != 0
2112 					&& fn->common.scope == aliases[i]
2113 					&& zend_string_equals_ci(alias->trait_method.method_name, fnname)
2114 				) {
2115 					if (alias->modifiers & ZEND_ACC_PPP_MASK) {
2116 						fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags & ~ZEND_ACC_PPP_MASK);
2117 					} else {
2118 						fn_copy.common.fn_flags = alias->modifiers | fn->common.fn_flags;
2119 					}
2120 				}
2121 				alias_ptr++;
2122 				alias = *alias_ptr;
2123 				i++;
2124 			}
2125 		}
2126 
2127 		zend_traits_check_private_final_inheritance(fn->common.fn_flags, &fn_copy, fnname);
2128 
2129 		zend_add_trait_method(ce, fn->common.function_name, fnname, &fn_copy);
2130 	}
2131 }
2132 /* }}} */
2133 
zend_check_trait_usage(zend_class_entry * ce,zend_class_entry * trait,zend_class_entry ** traits)2134 static uint32_t zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait, zend_class_entry **traits) /* {{{ */
2135 {
2136 	uint32_t i;
2137 
2138 	if (UNEXPECTED((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT)) {
2139 		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));
2140 		return 0;
2141 	}
2142 
2143 	for (i = 0; i < ce->num_traits; i++) {
2144 		if (traits[i] == trait) {
2145 			return i;
2146 		}
2147 	}
2148 	zend_error_noreturn(E_COMPILE_ERROR, "Required Trait %s wasn't added to %s", ZSTR_VAL(trait->name), ZSTR_VAL(ce->name));
2149 	return 0;
2150 }
2151 /* }}} */
2152 
zend_traits_init_trait_structures(zend_class_entry * ce,zend_class_entry ** traits,HashTable *** exclude_tables_ptr,zend_class_entry *** aliases_ptr)2153 static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_entry **traits, HashTable ***exclude_tables_ptr, zend_class_entry ***aliases_ptr) /* {{{ */
2154 {
2155 	size_t i, j = 0;
2156 	zend_trait_precedence **precedences;
2157 	zend_trait_precedence *cur_precedence;
2158 	zend_trait_method_reference *cur_method_ref;
2159 	zend_string *lc_trait_name;
2160 	zend_string *lcname;
2161 	HashTable **exclude_tables = NULL;
2162 	zend_class_entry **aliases = NULL;
2163 	zend_class_entry *trait;
2164 
2165 	/* resolve class references */
2166 	if (ce->trait_precedences) {
2167 		exclude_tables = ecalloc(ce->num_traits, sizeof(HashTable*));
2168 		i = 0;
2169 		precedences = ce->trait_precedences;
2170 		ce->trait_precedences = NULL;
2171 		while ((cur_precedence = precedences[i])) {
2172 			/** Resolve classes for all precedence operations. */
2173 			cur_method_ref = &cur_precedence->trait_method;
2174 			lc_trait_name = zend_string_tolower(cur_method_ref->class_name);
2175 			trait = zend_hash_find_ptr(EG(class_table), lc_trait_name);
2176 			zend_string_release_ex(lc_trait_name, 0);
2177 			if (!trait || !(trait->ce_flags & ZEND_ACC_LINKED)) {
2178 				zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name));
2179 			}
2180 			zend_check_trait_usage(ce, trait, traits);
2181 
2182 			/** Ensure that the preferred method is actually available. */
2183 			lcname = zend_string_tolower(cur_method_ref->method_name);
2184 			if (!zend_hash_exists(&trait->function_table, lcname)) {
2185 				zend_error_noreturn(E_COMPILE_ERROR,
2186 						   "A precedence rule was defined for %s::%s but this method does not exist",
2187 						   ZSTR_VAL(trait->name),
2188 						   ZSTR_VAL(cur_method_ref->method_name));
2189 			}
2190 
2191 			/** With the other traits, we are more permissive.
2192 				We do not give errors for those. This allows to be more
2193 				defensive in such definitions.
2194 				However, we want to make sure that the insteadof declaration
2195 				is consistent in itself.
2196 			 */
2197 
2198 			for (j = 0; j < cur_precedence->num_excludes; j++) {
2199 				zend_string* class_name = cur_precedence->exclude_class_names[j];
2200 				zend_class_entry *exclude_ce;
2201 				uint32_t trait_num;
2202 
2203 				lc_trait_name = zend_string_tolower(class_name);
2204 				exclude_ce = zend_hash_find_ptr(EG(class_table), lc_trait_name);
2205 				zend_string_release_ex(lc_trait_name, 0);
2206 				if (!exclude_ce || !(exclude_ce->ce_flags & ZEND_ACC_LINKED)) {
2207 					zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(class_name));
2208 				}
2209 				trait_num = zend_check_trait_usage(ce, exclude_ce, traits);
2210 				if (!exclude_tables[trait_num]) {
2211 					ALLOC_HASHTABLE(exclude_tables[trait_num]);
2212 					zend_hash_init(exclude_tables[trait_num], 0, NULL, NULL, 0);
2213 				}
2214 				if (zend_hash_add_empty_element(exclude_tables[trait_num], lcname) == NULL) {
2215 					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));
2216 				}
2217 
2218 				/* make sure that the trait method is not from a class mentioned in
2219 				 exclude_from_classes, for consistency */
2220 				if (trait == exclude_ce) {
2221 					zend_error_noreturn(E_COMPILE_ERROR,
2222 							   "Inconsistent insteadof definition. "
2223 							   "The method %s is to be used from %s, but %s is also on the exclude list",
2224 							   ZSTR_VAL(cur_method_ref->method_name),
2225 							   ZSTR_VAL(trait->name),
2226 							   ZSTR_VAL(trait->name));
2227 				}
2228 			}
2229 			zend_string_release_ex(lcname, 0);
2230 			i++;
2231 		}
2232 		ce->trait_precedences = precedences;
2233 	}
2234 
2235 	if (ce->trait_aliases) {
2236 		i = 0;
2237 		while (ce->trait_aliases[i]) {
2238 			i++;
2239 		}
2240 		aliases = ecalloc(i, sizeof(zend_class_entry*));
2241 		i = 0;
2242 		while (ce->trait_aliases[i]) {
2243 			zend_trait_alias *cur_alias = ce->trait_aliases[i];
2244 			cur_method_ref = &ce->trait_aliases[i]->trait_method;
2245 			lcname = zend_string_tolower(cur_method_ref->method_name);
2246 			if (cur_method_ref->class_name) {
2247 				/* For all aliases with an explicit class name, resolve the class now. */
2248 				lc_trait_name = zend_string_tolower(cur_method_ref->class_name);
2249 				trait = zend_hash_find_ptr(EG(class_table), lc_trait_name);
2250 				zend_string_release_ex(lc_trait_name, 0);
2251 				if (!trait || !(trait->ce_flags & ZEND_ACC_LINKED)) {
2252 					zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name));
2253 				}
2254 				zend_check_trait_usage(ce, trait, traits);
2255 				aliases[i] = trait;
2256 
2257 				/* And, ensure that the referenced method is resolvable, too. */
2258 				if (!zend_hash_exists(&trait->function_table, lcname)) {
2259 					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));
2260 				}
2261 			} else {
2262 				/* Find out which trait this method refers to. */
2263 				trait = NULL;
2264 				for (j = 0; j < ce->num_traits; j++) {
2265 					if (traits[j]) {
2266 						if (zend_hash_exists(&traits[j]->function_table, lcname)) {
2267 							if (!trait) {
2268 								trait = traits[j];
2269 								continue;
2270 							}
2271 
2272 							zend_error_noreturn(E_COMPILE_ERROR,
2273 								"An alias was defined for method %s(), which exists in both %s and %s. Use %s::%s or %s::%s to resolve the ambiguity",
2274 								ZSTR_VAL(cur_method_ref->method_name),
2275 								ZSTR_VAL(trait->name), ZSTR_VAL(traits[j]->name),
2276 								ZSTR_VAL(trait->name), ZSTR_VAL(cur_method_ref->method_name),
2277 								ZSTR_VAL(traits[j]->name), ZSTR_VAL(cur_method_ref->method_name));
2278 						}
2279 					}
2280 				}
2281 
2282 				/* Non-absolute method reference refers to method that does not exist. */
2283 				if (!trait) {
2284 					if (cur_alias->alias) {
2285 						zend_error_noreturn(E_COMPILE_ERROR,
2286 							"An alias (%s) was defined for method %s(), but this method does not exist",
2287 							ZSTR_VAL(cur_alias->alias),
2288 							ZSTR_VAL(cur_alias->trait_method.method_name));
2289 					} else {
2290 						zend_error_noreturn(E_COMPILE_ERROR,
2291 							"The modifiers of the trait method %s() are changed, but this method does not exist. Error",
2292 							ZSTR_VAL(cur_alias->trait_method.method_name));
2293 					}
2294 				}
2295 
2296 				aliases[i] = trait;
2297 			}
2298 			zend_string_release_ex(lcname, 0);
2299 			i++;
2300 		}
2301 	}
2302 
2303 	*exclude_tables_ptr = exclude_tables;
2304 	*aliases_ptr = aliases;
2305 }
2306 /* }}} */
2307 
zend_do_traits_method_binding(zend_class_entry * ce,zend_class_entry ** traits,HashTable ** exclude_tables,zend_class_entry ** aliases)2308 static void zend_do_traits_method_binding(zend_class_entry *ce, zend_class_entry **traits, HashTable **exclude_tables, zend_class_entry **aliases) /* {{{ */
2309 {
2310 	uint32_t i;
2311 	zend_string *key;
2312 	zend_function *fn;
2313 
2314 	if (exclude_tables) {
2315 		for (i = 0; i < ce->num_traits; i++) {
2316 			if (traits[i]) {
2317 				/* copies functions, applies defined aliasing, and excludes unused trait methods */
2318 				ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) {
2319 					zend_traits_copy_functions(key, fn, ce, exclude_tables[i], aliases);
2320 				} ZEND_HASH_FOREACH_END();
2321 
2322 				if (exclude_tables[i]) {
2323 					zend_hash_destroy(exclude_tables[i]);
2324 					FREE_HASHTABLE(exclude_tables[i]);
2325 					exclude_tables[i] = NULL;
2326 				}
2327 			}
2328 		}
2329 	} else {
2330 		for (i = 0; i < ce->num_traits; i++) {
2331 			if (traits[i]) {
2332 				ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->function_table, key, fn) {
2333 					zend_traits_copy_functions(key, fn, ce, NULL, aliases);
2334 				} ZEND_HASH_FOREACH_END();
2335 			}
2336 		}
2337 	}
2338 
2339 	ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, fn) {
2340 		zend_fixup_trait_method(fn, ce);
2341 	} ZEND_HASH_FOREACH_END();
2342 }
2343 /* }}} */
2344 
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)2345 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) /* {{{ */
2346 {
2347 	/* This function is used to show the place of the existing conflicting
2348 	 * definition in error messages when conflicts occur. Since trait constants
2349 	 * are flattened into the constants table of the composing class, and thus
2350 	 * we lose information about which constant was defined in which trait, a
2351 	 * process like this is needed to find the location of the first definition
2352 	 * of the constant from traits.
2353 	 */
2354 	size_t i;
2355 
2356 	if (colliding_ce == ce) {
2357 		for (i = 0; i < current_trait; i++) {
2358 			if (traits[i]
2359 				&& zend_hash_exists(&traits[i]->constants_table, constant_name)) {
2360 				return traits[i];
2361 			}
2362 		}
2363 	}
2364 	/* Traits don't have it, then the composing class (or trait) itself has it. */
2365 	return colliding_ce;
2366 }
2367 /* }}} */
2368 
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)2369 static void emit_incompatible_trait_constant_error(
2370 	zend_class_entry *ce, zend_class_constant *existing_constant, zend_class_constant *trait_constant, zend_string *name,
2371 	zend_class_entry **traits, size_t current_trait
2372 ) {
2373 	zend_error_noreturn(E_COMPILE_ERROR,
2374 		"%s and %s define the same constant (%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
2375 		ZSTR_VAL(find_first_constant_definition(ce, traits, current_trait, name, existing_constant->ce)->name),
2376 		ZSTR_VAL(trait_constant->ce->name),
2377 		ZSTR_VAL(name),
2378 		ZSTR_VAL(ce->name)
2379 	);
2380 }
2381 
do_trait_constant_check(zend_class_entry * ce,zend_class_constant * trait_constant,zend_string * name,zend_class_entry ** traits,size_t current_trait)2382 static bool do_trait_constant_check(
2383 	zend_class_entry *ce, zend_class_constant *trait_constant, zend_string *name, zend_class_entry **traits, size_t current_trait
2384 ) {
2385 	uint32_t flags_mask = ZEND_ACC_PPP_MASK | ZEND_ACC_FINAL;
2386 
2387 	zval *zv = zend_hash_find_known_hash(&ce->constants_table, name);
2388 	if (zv == NULL) {
2389 		/* No existing constant of the same name, so this one can be added */
2390 		return true;
2391 	}
2392 
2393 	zend_class_constant *existing_constant = Z_PTR_P(zv);
2394 
2395 	if ((ZEND_CLASS_CONST_FLAGS(trait_constant) & flags_mask) != (ZEND_CLASS_CONST_FLAGS(existing_constant) & flags_mask)) {
2396 		emit_incompatible_trait_constant_error(ce, existing_constant, trait_constant, name, traits, current_trait);
2397 		return false;
2398 	}
2399 
2400 	if (ZEND_TYPE_IS_SET(trait_constant->type) != ZEND_TYPE_IS_SET(existing_constant->type)) {
2401 		emit_incompatible_trait_constant_error(ce, existing_constant, trait_constant, name, traits, current_trait);
2402 		return false;
2403 	} else if (ZEND_TYPE_IS_SET(trait_constant->type)) {
2404 		inheritance_status status1 = zend_perform_covariant_type_check(ce, existing_constant->type, traits[current_trait], trait_constant->type);
2405 		inheritance_status status2 = zend_perform_covariant_type_check(traits[current_trait], trait_constant->type, ce, existing_constant->type);
2406 		if (status1 == INHERITANCE_ERROR || status2 == INHERITANCE_ERROR) {
2407 			emit_incompatible_trait_constant_error(ce, existing_constant, trait_constant, name, traits, current_trait);
2408 			return false;
2409 		}
2410 	}
2411 
2412 	if (!check_trait_property_or_constant_value_compatibility(ce, &trait_constant->value, &existing_constant->value)) {
2413 		/* There is an existing constant of the same name, and it conflicts with the new one, so let's throw a fatal error */
2414 		emit_incompatible_trait_constant_error(ce, existing_constant, trait_constant, name, traits, current_trait);
2415 		return false;
2416 	}
2417 
2418 	/* There is an existing constant which is compatible with the new one, so no need to add it */
2419 	return false;
2420 }
2421 
zend_do_traits_constant_binding(zend_class_entry * ce,zend_class_entry ** traits)2422 static void zend_do_traits_constant_binding(zend_class_entry *ce, zend_class_entry **traits) /* {{{ */
2423 {
2424 	size_t i;
2425 
2426 	for (i = 0; i < ce->num_traits; i++) {
2427 		zend_string *constant_name;
2428 		zend_class_constant *constant;
2429 
2430 		if (!traits[i]) {
2431 			continue;
2432 		}
2433 
2434 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->constants_table, constant_name, constant) {
2435 			if (do_trait_constant_check(ce, constant, constant_name, traits, i)) {
2436 				zend_class_constant *ct = NULL;
2437 
2438 				ct = zend_arena_alloc(&CG(arena),sizeof(zend_class_constant));
2439 				memcpy(ct, constant, sizeof(zend_class_constant));
2440 				constant = ct;
2441 
2442 				if (Z_TYPE(constant->value) == IS_CONSTANT_AST) {
2443 					ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
2444 					ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
2445 				}
2446 
2447 				/* Unlike interface implementations and class inheritances,
2448 				 * access control of the trait constants is done by the scope
2449 				 * of the composing class. So let's replace the ce here.
2450 				 */
2451 				constant->ce = ce;
2452 
2453 				Z_TRY_ADDREF(constant->value);
2454 				constant->doc_comment = constant->doc_comment ? zend_string_copy(constant->doc_comment) : NULL;
2455 				if (constant->attributes && (!(GC_FLAGS(constant->attributes) & IS_ARRAY_IMMUTABLE))) {
2456 					GC_ADDREF(constant->attributes);
2457 				}
2458 
2459 				zend_hash_update_ptr(&ce->constants_table, constant_name, constant);
2460 			}
2461 		} ZEND_HASH_FOREACH_END();
2462 	}
2463 }
2464 /* }}} */
2465 
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)2466 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) /* {{{ */
2467 {
2468 	size_t i;
2469 
2470 	if (colliding_ce == ce) {
2471 		for (i = 0; i < current_trait; i++) {
2472 			if (traits[i]
2473 			 && zend_hash_exists(&traits[i]->properties_info, prop_name)) {
2474 				return traits[i];
2475 			}
2476 		}
2477 	}
2478 
2479 	return colliding_ce;
2480 }
2481 /* }}} */
2482 
zend_do_traits_property_binding(zend_class_entry * ce,zend_class_entry ** traits)2483 static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_entry **traits) /* {{{ */
2484 {
2485 	size_t i;
2486 	zend_property_info *property_info;
2487 	zend_property_info *colliding_prop;
2488 	zend_property_info *new_prop;
2489 	zend_string* prop_name;
2490 	zval* prop_value;
2491 	zend_string *doc_comment;
2492 
2493 	/* In the following steps the properties are inserted into the property table
2494 	 * for that, a very strict approach is applied:
2495 	 * - check for compatibility, if not compatible with any property in class -> fatal
2496 	 * - if compatible, then strict notice
2497 	 */
2498 	for (i = 0; i < ce->num_traits; i++) {
2499 		if (!traits[i]) {
2500 			continue;
2501 		}
2502 		ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->properties_info, prop_name, property_info) {
2503 			uint32_t flags = property_info->flags;
2504 
2505 			/* next: check for conflicts with current class */
2506 			if ((colliding_prop = zend_hash_find_ptr(&ce->properties_info, prop_name)) != NULL) {
2507 				if ((colliding_prop->flags & ZEND_ACC_PRIVATE) && colliding_prop->ce != ce) {
2508 					zend_hash_del(&ce->properties_info, prop_name);
2509 					flags |= ZEND_ACC_CHANGED;
2510 				} else {
2511 					bool is_compatible = false;
2512 					uint32_t flags_mask = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC | ZEND_ACC_READONLY;
2513 
2514 					if ((colliding_prop->flags & flags_mask) == (flags & flags_mask) &&
2515 						property_types_compatible(property_info, colliding_prop) == INHERITANCE_SUCCESS
2516 					) {
2517 						/* the flags are identical, thus, the properties may be compatible */
2518 						zval *op1, *op2;
2519 
2520 						if (flags & ZEND_ACC_STATIC) {
2521 							op1 = &ce->default_static_members_table[colliding_prop->offset];
2522 							op2 = &traits[i]->default_static_members_table[property_info->offset];
2523 							ZVAL_DEINDIRECT(op1);
2524 							ZVAL_DEINDIRECT(op2);
2525 						} else {
2526 							op1 = &ce->default_properties_table[OBJ_PROP_TO_NUM(colliding_prop->offset)];
2527 							op2 = &traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)];
2528 						}
2529 						is_compatible = check_trait_property_or_constant_value_compatibility(ce, op1, op2);
2530 					}
2531 
2532 					if (!is_compatible) {
2533 						zend_error_noreturn(E_COMPILE_ERROR,
2534 								"%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
2535 								ZSTR_VAL(find_first_property_definition(ce, traits, i, prop_name, colliding_prop->ce)->name),
2536 								ZSTR_VAL(property_info->ce->name),
2537 								ZSTR_VAL(prop_name),
2538 								ZSTR_VAL(ce->name));
2539 					}
2540 					if (!(flags & ZEND_ACC_STATIC)) {
2541 						continue;
2542 					}
2543 				}
2544 			}
2545 
2546 			if ((ce->ce_flags & ZEND_ACC_READONLY_CLASS) && !(property_info->flags & ZEND_ACC_READONLY)) {
2547 				zend_error_noreturn(E_COMPILE_ERROR,
2548 					"Readonly class %s cannot use trait with a non-readonly property %s::$%s",
2549 					ZSTR_VAL(ce->name),
2550 					ZSTR_VAL(property_info->ce->name),
2551 					ZSTR_VAL(prop_name)
2552 				);
2553 			}
2554 
2555 			/* property not found, so lets add it */
2556 			if (flags & ZEND_ACC_STATIC) {
2557 				prop_value = &traits[i]->default_static_members_table[property_info->offset];
2558 				ZEND_ASSERT(Z_TYPE_P(prop_value) != IS_INDIRECT);
2559 			} else {
2560 				prop_value = &traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)];
2561 			}
2562 
2563 			Z_TRY_ADDREF_P(prop_value);
2564 			doc_comment = property_info->doc_comment ? zend_string_copy(property_info->doc_comment) : NULL;
2565 
2566 			zend_type type = property_info->type;
2567 			/* Assumption: only userland classes can use traits, as such the type must be arena allocated */
2568 			zend_type_copy_ctor(&type, /* use arena */ true, /* persistent */ false);
2569 			new_prop = zend_declare_typed_property(ce, prop_name, prop_value, flags, doc_comment, type);
2570 
2571 			if (property_info->attributes) {
2572 				new_prop->attributes = property_info->attributes;
2573 
2574 				if (!(GC_FLAGS(new_prop->attributes) & IS_ARRAY_IMMUTABLE)) {
2575 					GC_ADDREF(new_prop->attributes);
2576 				}
2577 			}
2578 		} ZEND_HASH_FOREACH_END();
2579 	}
2580 }
2581 /* }}} */
2582 
zend_do_bind_traits(zend_class_entry * ce,zend_class_entry ** traits)2583 static void zend_do_bind_traits(zend_class_entry *ce, zend_class_entry **traits) /* {{{ */
2584 {
2585 	HashTable **exclude_tables;
2586 	zend_class_entry **aliases;
2587 
2588 	ZEND_ASSERT(ce->num_traits > 0);
2589 
2590 	/* complete initialization of trait structures in ce */
2591 	zend_traits_init_trait_structures(ce, traits, &exclude_tables, &aliases);
2592 
2593 	/* first care about all methods to be flattened into the class */
2594 	zend_do_traits_method_binding(ce, traits, exclude_tables, aliases);
2595 
2596 	if (aliases) {
2597 		efree(aliases);
2598 	}
2599 
2600 	if (exclude_tables) {
2601 		efree(exclude_tables);
2602 	}
2603 
2604 	/* then flatten the constants and properties into it, to, mostly to notify developer about problems */
2605 	zend_do_traits_constant_binding(ce, traits);
2606 	zend_do_traits_property_binding(ce, traits);
2607 }
2608 /* }}} */
2609 
2610 #define MAX_ABSTRACT_INFO_CNT 3
2611 #define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
2612 #define DISPLAY_ABSTRACT_FN(idx) \
2613 	ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
2614 	ai.afn[idx] ? "::" : "", \
2615 	ai.afn[idx] ? ZSTR_VAL(ai.afn[idx]->common.function_name) : "", \
2616 	ai.afn[idx] && ai.afn[idx + 1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
2617 
2618 typedef struct _zend_abstract_info {
2619 	zend_function *afn[MAX_ABSTRACT_INFO_CNT + 1];
2620 	int cnt;
2621 } zend_abstract_info;
2622 
zend_verify_abstract_class_function(zend_function * fn,zend_abstract_info * ai)2623 static void zend_verify_abstract_class_function(zend_function *fn, zend_abstract_info *ai) /* {{{ */
2624 {
2625 	if (ai->cnt < MAX_ABSTRACT_INFO_CNT) {
2626 		ai->afn[ai->cnt] = fn;
2627 	}
2628 	ai->cnt++;
2629 }
2630 /* }}} */
2631 
zend_verify_abstract_class(zend_class_entry * ce)2632 void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */
2633 {
2634 	zend_function *func;
2635 	zend_abstract_info ai;
2636 	bool is_explicit_abstract = (ce->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) != 0;
2637 	bool can_be_abstract = (ce->ce_flags & ZEND_ACC_ENUM) == 0;
2638 	memset(&ai, 0, sizeof(ai));
2639 
2640 	ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, func) {
2641 		if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
2642 			/* If the class is explicitly abstract, we only check private abstract methods,
2643 			 * because only they must be declared in the same class. */
2644 			if (!is_explicit_abstract || (func->common.fn_flags & ZEND_ACC_PRIVATE)) {
2645 				zend_verify_abstract_class_function(func, &ai);
2646 			}
2647 		}
2648 	} ZEND_HASH_FOREACH_END();
2649 
2650 	if (ai.cnt) {
2651 		zend_error_noreturn(E_ERROR, !is_explicit_abstract && can_be_abstract
2652 			? "%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 ")"
2653 			: "%s %s must implement %d abstract private method%s (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
2654 			zend_get_object_type_uc(ce),
2655 			ZSTR_VAL(ce->name), ai.cnt,
2656 			ai.cnt > 1 ? "s" : "",
2657 			DISPLAY_ABSTRACT_FN(0),
2658 			DISPLAY_ABSTRACT_FN(1),
2659 			DISPLAY_ABSTRACT_FN(2)
2660 			);
2661 	} else {
2662 		/* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */
2663 		ce->ce_flags &= ~ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2664 	}
2665 }
2666 /* }}} */
2667 
2668 typedef struct {
2669 	enum {
2670 		OBLIGATION_DEPENDENCY,
2671 		OBLIGATION_COMPATIBILITY,
2672 		OBLIGATION_PROPERTY_COMPATIBILITY,
2673 		OBLIGATION_CLASS_CONSTANT_COMPATIBILITY
2674 	} type;
2675 	union {
2676 		zend_class_entry *dependency_ce;
2677 		struct {
2678 			/* Traits may use temporary on-stack functions during inheritance checks,
2679 			 * so use copies of functions here as well. */
2680 			zend_function parent_fn;
2681 			zend_function child_fn;
2682 			zend_class_entry *child_scope;
2683 			zend_class_entry *parent_scope;
2684 		};
2685 		struct {
2686 			const zend_property_info *parent_prop;
2687 			const zend_property_info *child_prop;
2688 		};
2689 		struct {
2690 			const zend_string *const_name;
2691 			const zend_class_constant *parent_const;
2692 			const zend_class_constant *child_const;
2693 		};
2694 	};
2695 } variance_obligation;
2696 
variance_obligation_dtor(zval * zv)2697 static void variance_obligation_dtor(zval *zv) {
2698 	efree(Z_PTR_P(zv));
2699 }
2700 
variance_obligation_ht_dtor(zval * zv)2701 static void variance_obligation_ht_dtor(zval *zv) {
2702 	zend_hash_destroy(Z_PTR_P(zv));
2703 	FREE_HASHTABLE(Z_PTR_P(zv));
2704 }
2705 
get_or_init_obligations_for_class(zend_class_entry * ce)2706 static HashTable *get_or_init_obligations_for_class(zend_class_entry *ce) {
2707 	HashTable *ht;
2708 	zend_ulong key;
2709 	if (!CG(delayed_variance_obligations)) {
2710 		ALLOC_HASHTABLE(CG(delayed_variance_obligations));
2711 		zend_hash_init(CG(delayed_variance_obligations), 0, NULL, variance_obligation_ht_dtor, 0);
2712 	}
2713 
2714 	key = (zend_ulong) (uintptr_t) ce;
2715 	ht = zend_hash_index_find_ptr(CG(delayed_variance_obligations), key);
2716 	if (ht) {
2717 		return ht;
2718 	}
2719 
2720 	ALLOC_HASHTABLE(ht);
2721 	zend_hash_init(ht, 0, NULL, variance_obligation_dtor, 0);
2722 	zend_hash_index_add_new_ptr(CG(delayed_variance_obligations), key, ht);
2723 	ce->ce_flags |= ZEND_ACC_UNRESOLVED_VARIANCE;
2724 	return ht;
2725 }
2726 
add_dependency_obligation(zend_class_entry * ce,zend_class_entry * dependency_ce)2727 static void add_dependency_obligation(zend_class_entry *ce, zend_class_entry *dependency_ce) {
2728 	HashTable *obligations = get_or_init_obligations_for_class(ce);
2729 	variance_obligation *obligation = emalloc(sizeof(variance_obligation));
2730 	obligation->type = OBLIGATION_DEPENDENCY;
2731 	obligation->dependency_ce = dependency_ce;
2732 	zend_hash_next_index_insert_ptr(obligations, obligation);
2733 }
2734 
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)2735 static void add_compatibility_obligation(
2736 		zend_class_entry *ce,
2737 		const zend_function *child_fn, zend_class_entry *child_scope,
2738 		const zend_function *parent_fn, zend_class_entry *parent_scope) {
2739 	HashTable *obligations = get_or_init_obligations_for_class(ce);
2740 	variance_obligation *obligation = emalloc(sizeof(variance_obligation));
2741 	obligation->type = OBLIGATION_COMPATIBILITY;
2742 	/* Copy functions, because they may be stack-allocated in the case of traits. */
2743 	if (child_fn->common.type == ZEND_INTERNAL_FUNCTION) {
2744 		memcpy(&obligation->child_fn, child_fn, sizeof(zend_internal_function));
2745 	} else {
2746 		memcpy(&obligation->child_fn, child_fn, sizeof(zend_op_array));
2747 	}
2748 	if (parent_fn->common.type == ZEND_INTERNAL_FUNCTION) {
2749 		memcpy(&obligation->parent_fn, parent_fn, sizeof(zend_internal_function));
2750 	} else {
2751 		memcpy(&obligation->parent_fn, parent_fn, sizeof(zend_op_array));
2752 	}
2753 	obligation->child_scope = child_scope;
2754 	obligation->parent_scope = parent_scope;
2755 	zend_hash_next_index_insert_ptr(obligations, obligation);
2756 }
2757 
add_property_compatibility_obligation(zend_class_entry * ce,const zend_property_info * child_prop,const zend_property_info * parent_prop)2758 static void add_property_compatibility_obligation(
2759 		zend_class_entry *ce, const zend_property_info *child_prop,
2760 		const zend_property_info *parent_prop) {
2761 	HashTable *obligations = get_or_init_obligations_for_class(ce);
2762 	variance_obligation *obligation = emalloc(sizeof(variance_obligation));
2763 	obligation->type = OBLIGATION_PROPERTY_COMPATIBILITY;
2764 	obligation->child_prop = child_prop;
2765 	obligation->parent_prop = parent_prop;
2766 	zend_hash_next_index_insert_ptr(obligations, obligation);
2767 }
2768 
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)2769 static void add_class_constant_compatibility_obligation(
2770 		zend_class_entry *ce, const zend_class_constant *child_const,
2771 		const zend_class_constant *parent_const, const zend_string *const_name) {
2772 	HashTable *obligations = get_or_init_obligations_for_class(ce);
2773 	variance_obligation *obligation = emalloc(sizeof(variance_obligation));
2774 	obligation->type = OBLIGATION_CLASS_CONSTANT_COMPATIBILITY;
2775 	obligation->const_name = const_name;
2776 	obligation->child_const = child_const;
2777 	obligation->parent_const = parent_const;
2778 	zend_hash_next_index_insert_ptr(obligations, obligation);
2779 }
2780 
2781 static void resolve_delayed_variance_obligations(zend_class_entry *ce);
2782 
check_variance_obligation(variance_obligation * obligation)2783 static void check_variance_obligation(variance_obligation *obligation) {
2784 	if (obligation->type == OBLIGATION_DEPENDENCY) {
2785 		zend_class_entry *dependency_ce = obligation->dependency_ce;
2786 		if (dependency_ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE) {
2787 			zend_class_entry *orig_linking_class = CG(current_linking_class);
2788 
2789 			CG(current_linking_class) =
2790 				(dependency_ce->ce_flags & ZEND_ACC_CACHEABLE) ? dependency_ce : NULL;
2791 			resolve_delayed_variance_obligations(dependency_ce);
2792 			CG(current_linking_class) = orig_linking_class;
2793 		}
2794 	} else if (obligation->type == OBLIGATION_COMPATIBILITY) {
2795 		inheritance_status status = zend_do_perform_implementation_check(
2796 			&obligation->child_fn, obligation->child_scope,
2797 			&obligation->parent_fn, obligation->parent_scope);
2798 		if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
2799 			emit_incompatible_method_error(
2800 				&obligation->child_fn, obligation->child_scope,
2801 				&obligation->parent_fn, obligation->parent_scope, status);
2802 		}
2803 		/* Either the compatibility check was successful or only threw a warning. */
2804 	} else if (obligation->type == OBLIGATION_PROPERTY_COMPATIBILITY) {
2805 		inheritance_status status =
2806 			property_types_compatible(obligation->parent_prop, obligation->child_prop);
2807 		if (status != INHERITANCE_SUCCESS) {
2808 			emit_incompatible_property_error(obligation->child_prop, obligation->parent_prop);
2809 		}
2810 	} else {
2811 		ZEND_ASSERT(obligation->type == OBLIGATION_CLASS_CONSTANT_COMPATIBILITY);
2812 		inheritance_status status =
2813 		class_constant_types_compatible(obligation->parent_const, obligation->child_const);
2814 		if (status != INHERITANCE_SUCCESS) {
2815 			emit_incompatible_class_constant_error(obligation->child_const, obligation->parent_const, obligation->const_name);
2816 		}
2817 	}
2818 }
2819 
load_delayed_classes(zend_class_entry * ce)2820 static void load_delayed_classes(zend_class_entry *ce) {
2821 	HashTable *delayed_autoloads = CG(delayed_autoloads);
2822 	if (!delayed_autoloads) {
2823 		return;
2824 	}
2825 
2826 	/* Autoloading can trigger linking of another class, which may register new delayed autoloads.
2827 	 * For that reason, this code uses a loop that pops and loads the first element of the HT. If
2828 	 * this triggers linking, then the remaining classes may get loaded when linking the newly
2829 	 * loaded class. This is important, as otherwise necessary dependencies may not be available
2830 	 * if the new class is lower in the hierarchy than the current one. */
2831 	HashPosition pos = 0;
2832 	zend_string *name;
2833 	zend_ulong idx;
2834 	while (zend_hash_get_current_key_ex(delayed_autoloads, &name, &idx, &pos)
2835 			!= HASH_KEY_NON_EXISTENT) {
2836 		zend_string_addref(name);
2837 		zend_hash_del(delayed_autoloads, name);
2838 		zend_lookup_class(name);
2839 		zend_string_release(name);
2840 		if (EG(exception)) {
2841 			zend_exception_uncaught_error(
2842 				"During inheritance of %s, while autoloading %s",
2843 				ZSTR_VAL(ce->name), ZSTR_VAL(name));
2844 		}
2845 	}
2846 }
2847 
resolve_delayed_variance_obligations(zend_class_entry * ce)2848 static void resolve_delayed_variance_obligations(zend_class_entry *ce) {
2849 	HashTable *all_obligations = CG(delayed_variance_obligations), *obligations;
2850 	zend_ulong num_key = (zend_ulong) (uintptr_t) ce;
2851 
2852 	ZEND_ASSERT(all_obligations != NULL);
2853 	obligations = zend_hash_index_find_ptr(all_obligations, num_key);
2854 	ZEND_ASSERT(obligations != NULL);
2855 
2856 	variance_obligation *obligation;
2857 	ZEND_HASH_FOREACH_PTR(obligations, obligation) {
2858 		check_variance_obligation(obligation);
2859 	} ZEND_HASH_FOREACH_END();
2860 
2861 	zend_inheritance_check_override(ce);
2862 
2863 	ce->ce_flags &= ~ZEND_ACC_UNRESOLVED_VARIANCE;
2864 	ce->ce_flags |= ZEND_ACC_LINKED;
2865 	zend_hash_index_del(all_obligations, num_key);
2866 }
2867 
check_unrecoverable_load_failure(zend_class_entry * ce)2868 static void check_unrecoverable_load_failure(zend_class_entry *ce) {
2869 	/* If this class has been used while unlinked through a variance obligation, it is not legal
2870 	 * to remove the class from the class table and throw an exception, because there is already
2871 	 * a dependence on the inheritance hierarchy of this specific class. Instead we fall back to
2872 	 * a fatal error, as would happen if we did not allow exceptions in the first place. */
2873 	if (CG(unlinked_uses)
2874 			&& zend_hash_index_del(CG(unlinked_uses), (zend_long)(uintptr_t)ce) == SUCCESS) {
2875 		zend_exception_uncaught_error(
2876 			"During inheritance of %s with variance dependencies", ZSTR_VAL(ce->name));
2877 	}
2878 }
2879 
2880 #define zend_update_inherited_handler(handler) do { \
2881 		if (ce->handler == (zend_function*)op_array) { \
2882 			ce->handler = (zend_function*)new_op_array; \
2883 		} \
2884 	} while (0)
2885 
zend_lazy_class_load(zend_class_entry * pce)2886 static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce)
2887 {
2888 	zend_class_entry *ce;
2889 	Bucket *p, *end;
2890 
2891 	ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
2892 	memcpy(ce, pce, sizeof(zend_class_entry));
2893 	ce->ce_flags &= ~ZEND_ACC_IMMUTABLE;
2894 	ce->refcount = 1;
2895 	ce->inheritance_cache = NULL;
2896 	if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
2897 		ZEND_MAP_PTR_NEW(ce->mutable_data);
2898 	} else {
2899 		ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
2900 	}
2901 
2902 	/* properties */
2903 	if (ce->default_properties_table) {
2904 		zval *dst = emalloc(sizeof(zval) * ce->default_properties_count);
2905 		zval *src = ce->default_properties_table;
2906 		zval *end = src + ce->default_properties_count;
2907 
2908 		ce->default_properties_table = dst;
2909 		for (; src != end; src++, dst++) {
2910 			ZVAL_COPY_VALUE_PROP(dst, src);
2911 		}
2912 	}
2913 
2914 	/* methods */
2915 	ce->function_table.pDestructor = ZEND_FUNCTION_DTOR;
2916 	if (!(HT_FLAGS(&ce->function_table) & HASH_FLAG_UNINITIALIZED)) {
2917 		p = emalloc(HT_SIZE(&ce->function_table));
2918 		memcpy(p, HT_GET_DATA_ADDR(&ce->function_table), HT_USED_SIZE(&ce->function_table));
2919 		HT_SET_DATA_ADDR(&ce->function_table, p);
2920 		p = ce->function_table.arData;
2921 		end = p + ce->function_table.nNumUsed;
2922 		for (; p != end; p++) {
2923 			zend_op_array *op_array, *new_op_array;
2924 
2925 			op_array = Z_PTR(p->val);
2926 			ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
2927 			ZEND_ASSERT(op_array->scope == pce);
2928 			ZEND_ASSERT(op_array->prototype == NULL);
2929 			new_op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
2930 			Z_PTR(p->val) = new_op_array;
2931 			memcpy(new_op_array, op_array, sizeof(zend_op_array));
2932 			new_op_array->fn_flags &= ~ZEND_ACC_IMMUTABLE;
2933 			new_op_array->scope = ce;
2934 			ZEND_MAP_PTR_INIT(new_op_array->run_time_cache, NULL);
2935 			ZEND_MAP_PTR_INIT(new_op_array->static_variables_ptr, NULL);
2936 
2937 			zend_update_inherited_handler(constructor);
2938 			zend_update_inherited_handler(destructor);
2939 			zend_update_inherited_handler(clone);
2940 			zend_update_inherited_handler(__get);
2941 			zend_update_inherited_handler(__set);
2942 			zend_update_inherited_handler(__call);
2943 			zend_update_inherited_handler(__isset);
2944 			zend_update_inherited_handler(__unset);
2945 			zend_update_inherited_handler(__tostring);
2946 			zend_update_inherited_handler(__callstatic);
2947 			zend_update_inherited_handler(__debugInfo);
2948 			zend_update_inherited_handler(__serialize);
2949 			zend_update_inherited_handler(__unserialize);
2950 		}
2951 	}
2952 
2953 	/* static members */
2954 	if (ce->default_static_members_table) {
2955 		zval *dst = emalloc(sizeof(zval) * ce->default_static_members_count);
2956 		zval *src = ce->default_static_members_table;
2957 		zval *end = src + ce->default_static_members_count;
2958 
2959 		ce->default_static_members_table = dst;
2960 		for (; src != end; src++, dst++) {
2961 			ZVAL_COPY_VALUE(dst, src);
2962 		}
2963 	}
2964 	ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
2965 
2966 	/* properties_info */
2967 	if (!(HT_FLAGS(&ce->properties_info) & HASH_FLAG_UNINITIALIZED)) {
2968 		p = emalloc(HT_SIZE(&ce->properties_info));
2969 		memcpy(p, HT_GET_DATA_ADDR(&ce->properties_info), HT_USED_SIZE(&ce->properties_info));
2970 		HT_SET_DATA_ADDR(&ce->properties_info, p);
2971 		p = ce->properties_info.arData;
2972 		end = p + ce->properties_info.nNumUsed;
2973 		for (; p != end; p++) {
2974 			zend_property_info *prop_info, *new_prop_info;
2975 
2976 			prop_info = Z_PTR(p->val);
2977 			ZEND_ASSERT(prop_info->ce == pce);
2978 			new_prop_info= zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
2979 			Z_PTR(p->val) = new_prop_info;
2980 			memcpy(new_prop_info, prop_info, sizeof(zend_property_info));
2981 			new_prop_info->ce = ce;
2982 			/* Deep copy the type information */
2983 			zend_type_copy_ctor(&new_prop_info->type, /* use_arena */ true, /* persistent */ false);
2984 		}
2985 	}
2986 
2987 	/* constants table */
2988 	if (!(HT_FLAGS(&ce->constants_table) & HASH_FLAG_UNINITIALIZED)) {
2989 		p = emalloc(HT_SIZE(&ce->constants_table));
2990 		memcpy(p, HT_GET_DATA_ADDR(&ce->constants_table), HT_USED_SIZE(&ce->constants_table));
2991 		HT_SET_DATA_ADDR(&ce->constants_table, p);
2992 		p = ce->constants_table.arData;
2993 		end = p + ce->constants_table.nNumUsed;
2994 		for (; p != end; p++) {
2995 			zend_class_constant *c, *new_c;
2996 
2997 			c = Z_PTR(p->val);
2998 			ZEND_ASSERT(c->ce == pce);
2999 			new_c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
3000 			Z_PTR(p->val) = new_c;
3001 			memcpy(new_c, c, sizeof(zend_class_constant));
3002 			new_c->ce = ce;
3003 		}
3004 	}
3005 
3006 	return ce;
3007 }
3008 
3009 #ifndef ZEND_WIN32
3010 # define UPDATE_IS_CACHEABLE(ce) do { \
3011 			if ((ce)->type == ZEND_USER_CLASS) { \
3012 				is_cacheable &= (ce)->ce_flags; \
3013 			} \
3014 		} while (0)
3015 #else
3016 // TODO: ASLR may cause different addresses in different workers ???
3017 # define UPDATE_IS_CACHEABLE(ce) do { \
3018 			is_cacheable &= (ce)->ce_flags; \
3019 		} while (0)
3020 #endif
3021 
zend_do_link_class(zend_class_entry * ce,zend_string * lc_parent_name,zend_string * key)3022 ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name, zend_string *key) /* {{{ */
3023 {
3024 	/* Load parent/interface dependencies first, so we can still gracefully abort linking
3025 	 * with an exception and remove the class from the class table. This is only possible
3026 	 * if no variance obligations on the current class have been added during autoloading. */
3027 	zend_class_entry *parent = NULL;
3028 	zend_class_entry **traits_and_interfaces = NULL;
3029 	zend_class_entry *proto = NULL;
3030 	zend_class_entry *orig_linking_class;
3031 	uint32_t is_cacheable = ce->ce_flags & ZEND_ACC_IMMUTABLE;
3032 	uint32_t i, j;
3033 	zval *zv;
3034 	ALLOCA_FLAG(use_heap)
3035 
3036 	SET_ALLOCA_FLAG(use_heap);
3037 	ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_LINKED));
3038 
3039 	if (ce->parent_name) {
3040 		parent = zend_fetch_class_by_name(
3041 			ce->parent_name, lc_parent_name,
3042 			ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED | ZEND_FETCH_CLASS_EXCEPTION);
3043 		if (!parent) {
3044 			check_unrecoverable_load_failure(ce);
3045 			return NULL;
3046 		}
3047 		UPDATE_IS_CACHEABLE(parent);
3048 	}
3049 
3050 	if (ce->num_traits || ce->num_interfaces) {
3051 		traits_and_interfaces = do_alloca(sizeof(zend_class_entry*) * (ce->num_traits + ce->num_interfaces), use_heap);
3052 
3053 		for (i = 0; i < ce->num_traits; i++) {
3054 			zend_class_entry *trait = zend_fetch_class_by_name(ce->trait_names[i].name,
3055 				ce->trait_names[i].lc_name, ZEND_FETCH_CLASS_TRAIT);
3056 			if (UNEXPECTED(trait == NULL)) {
3057 				free_alloca(traits_and_interfaces, use_heap);
3058 				return NULL;
3059 			}
3060 			if (UNEXPECTED(!(trait->ce_flags & ZEND_ACC_TRAIT))) {
3061 				zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ZSTR_VAL(ce->name), ZSTR_VAL(trait->name));
3062 				free_alloca(traits_and_interfaces, use_heap);
3063 				return NULL;
3064 			}
3065 			for (j = 0; j < i; j++) {
3066 				if (traits_and_interfaces[j] == trait) {
3067 					/* skip duplications */
3068 					trait = NULL;
3069 					break;
3070 				}
3071 			}
3072 			traits_and_interfaces[i] = trait;
3073 			if (trait) {
3074 				UPDATE_IS_CACHEABLE(trait);
3075 			}
3076 		}
3077 	}
3078 
3079 	if (ce->num_interfaces) {
3080 		for (i = 0; i < ce->num_interfaces; i++) {
3081 			zend_class_entry *iface = zend_fetch_class_by_name(
3082 				ce->interface_names[i].name, ce->interface_names[i].lc_name,
3083 				ZEND_FETCH_CLASS_INTERFACE |
3084 				ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED | ZEND_FETCH_CLASS_EXCEPTION);
3085 			if (!iface) {
3086 				check_unrecoverable_load_failure(ce);
3087 				free_alloca(traits_and_interfaces, use_heap);
3088 				return NULL;
3089 			}
3090 			traits_and_interfaces[ce->num_traits + i] = iface;
3091 			if (iface) {
3092 				UPDATE_IS_CACHEABLE(iface);
3093 			}
3094 		}
3095 	}
3096 
3097 #ifndef ZEND_WIN32
3098 	if (ce->ce_flags & ZEND_ACC_ENUM) {
3099 		/* We will add internal methods. */
3100 		is_cacheable = false;
3101 	}
3102 #endif
3103 
3104 	bool orig_record_errors = EG(record_errors);
3105 
3106 	if (ce->ce_flags & ZEND_ACC_IMMUTABLE && is_cacheable) {
3107 		if (zend_inheritance_cache_get && zend_inheritance_cache_add) {
3108 			zend_class_entry *ret = zend_inheritance_cache_get(ce, parent, traits_and_interfaces);
3109 			if (ret) {
3110 				if (traits_and_interfaces) {
3111 					free_alloca(traits_and_interfaces, use_heap);
3112 				}
3113 				zv = zend_hash_find_known_hash(CG(class_table), key);
3114 				Z_CE_P(zv) = ret;
3115 				return ret;
3116 			}
3117 
3118 			/* Make sure warnings (such as deprecations) thrown during inheritance
3119 			 * will be recorded in the inheritance cache. */
3120 			zend_begin_record_errors();
3121 		} else {
3122 			is_cacheable = 0;
3123 		}
3124 		proto = ce;
3125 	}
3126 
3127 	zend_try {
3128 		if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
3129 			/* Lazy class loading */
3130 			ce = zend_lazy_class_load(ce);
3131 			zv = zend_hash_find_known_hash(CG(class_table), key);
3132 			Z_CE_P(zv) = ce;
3133 		} else if (ce->ce_flags & ZEND_ACC_FILE_CACHED) {
3134 			/* Lazy class loading */
3135 			ce = zend_lazy_class_load(ce);
3136 			ce->ce_flags &= ~ZEND_ACC_FILE_CACHED;
3137 			zv = zend_hash_find_known_hash(CG(class_table), key);
3138 			Z_CE_P(zv) = ce;
3139 		}
3140 
3141 		if (CG(unlinked_uses)) {
3142 			zend_hash_index_del(CG(unlinked_uses), (zend_long)(uintptr_t) ce);
3143 		}
3144 
3145 		orig_linking_class = CG(current_linking_class);
3146 		CG(current_linking_class) = is_cacheable ? ce : NULL;
3147 
3148 		if (ce->ce_flags & ZEND_ACC_ENUM) {
3149 			/* Only register builtin enum methods during inheritance to avoid persisting them in
3150 			 * opcache. */
3151 			zend_enum_register_funcs(ce);
3152 		}
3153 
3154 		if (parent) {
3155 			if (!(parent->ce_flags & ZEND_ACC_LINKED)) {
3156 				add_dependency_obligation(ce, parent);
3157 			}
3158 			zend_do_inheritance(ce, parent);
3159 		}
3160 		if (ce->num_traits) {
3161 			zend_do_bind_traits(ce, traits_and_interfaces);
3162 		}
3163 		if (ce->num_interfaces) {
3164 			/* Also copy the parent interfaces here, so we don't need to reallocate later. */
3165 			uint32_t num_parent_interfaces = parent ? parent->num_interfaces : 0;
3166 			zend_class_entry **interfaces = emalloc(
3167 					sizeof(zend_class_entry *) * (ce->num_interfaces + num_parent_interfaces));
3168 
3169 			if (num_parent_interfaces) {
3170 				memcpy(interfaces, parent->interfaces,
3171 					   sizeof(zend_class_entry *) * num_parent_interfaces);
3172 			}
3173 			memcpy(interfaces + num_parent_interfaces, traits_and_interfaces + ce->num_traits,
3174 				   sizeof(zend_class_entry *) * ce->num_interfaces);
3175 
3176 			zend_do_implement_interfaces(ce, interfaces);
3177 		} else if (parent && parent->num_interfaces) {
3178 			zend_do_inherit_interfaces(ce, parent);
3179 		}
3180 		if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT))
3181 			&& (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
3182 				) {
3183 			zend_verify_abstract_class(ce);
3184 		}
3185 		if (ce->ce_flags & ZEND_ACC_ENUM) {
3186 			zend_verify_enum(ce);
3187 		}
3188 
3189 		/* Normally Stringable is added during compilation. However, if it is imported from a trait,
3190 		 * we need to explicitly add the interface here. */
3191 		if (ce->__tostring && !(ce->ce_flags & ZEND_ACC_TRAIT)
3192 			&& !zend_class_implements_interface(ce, zend_ce_stringable)) {
3193 			ZEND_ASSERT(ce->__tostring->common.fn_flags & ZEND_ACC_TRAIT_CLONE);
3194 			ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES;
3195 			ce->num_interfaces++;
3196 			ce->interfaces = perealloc(ce->interfaces,
3197 									   sizeof(zend_class_entry *) * ce->num_interfaces, ce->type == ZEND_INTERNAL_CLASS);
3198 			ce->interfaces[ce->num_interfaces - 1] = zend_ce_stringable;
3199 			do_interface_implementation(ce, zend_ce_stringable);
3200 		}
3201 
3202 		zend_build_properties_info_table(ce);
3203 	} zend_catch {
3204 		/* Do not leak recorded errors to the next linked class. */
3205 		if (!orig_record_errors) {
3206 			EG(record_errors) = false;
3207 			zend_free_recorded_errors();
3208 		}
3209 		zend_bailout();
3210 	} zend_end_try();
3211 
3212 	EG(record_errors) = orig_record_errors;
3213 
3214 	if (!(ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE)) {
3215 		zend_inheritance_check_override(ce);
3216 		ce->ce_flags |= ZEND_ACC_LINKED;
3217 	} else {
3218 		ce->ce_flags |= ZEND_ACC_NEARLY_LINKED;
3219 		if (CG(current_linking_class)) {
3220 			ce->ce_flags |= ZEND_ACC_CACHEABLE;
3221 		}
3222 		load_delayed_classes(ce);
3223 		if (ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE) {
3224 			resolve_delayed_variance_obligations(ce);
3225 		}
3226 		if (ce->ce_flags & ZEND_ACC_CACHEABLE) {
3227 			ce->ce_flags &= ~ZEND_ACC_CACHEABLE;
3228 		} else {
3229 			CG(current_linking_class) = NULL;
3230 		}
3231 	}
3232 
3233 	if (!CG(current_linking_class)) {
3234 		is_cacheable = 0;
3235 	}
3236 	CG(current_linking_class) = orig_linking_class;
3237 
3238 	if (is_cacheable) {
3239 		HashTable *ht = (HashTable*)ce->inheritance_cache;
3240 		zend_class_entry *new_ce;
3241 
3242 		ce->inheritance_cache = NULL;
3243 		new_ce = zend_inheritance_cache_add(ce, proto, parent, traits_and_interfaces, ht);
3244 		if (new_ce) {
3245 			zv = zend_hash_find_known_hash(CG(class_table), key);
3246 			ce = new_ce;
3247 			Z_CE_P(zv) = ce;
3248 		}
3249 		if (ht) {
3250 			zend_hash_destroy(ht);
3251 			FREE_HASHTABLE(ht);
3252 		}
3253 	}
3254 
3255 	if (!orig_record_errors) {
3256 		zend_free_recorded_errors();
3257 	}
3258 	if (traits_and_interfaces) {
3259 		free_alloca(traits_and_interfaces, use_heap);
3260 	}
3261 
3262 	if (ZSTR_HAS_CE_CACHE(ce->name)) {
3263 		ZSTR_SET_CE_CACHE(ce->name, ce);
3264 	}
3265 
3266 	return ce;
3267 }
3268 /* }}} */
3269 
3270 /* 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)3271 static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */
3272 {
3273 	zend_string *key;
3274 	zend_function *parent_func;
3275 	zend_property_info *parent_info;
3276 	zend_class_constant *parent_const;
3277 	inheritance_status overall_status = INHERITANCE_SUCCESS;
3278 
3279 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, parent_func) {
3280 		zval *zv = zend_hash_find_known_hash(&ce->function_table, key);
3281 		if (zv) {
3282 			zend_function *child_func = Z_FUNC_P(zv);
3283 			inheritance_status status =
3284 				do_inheritance_check_on_method(
3285 					child_func, child_func->common.scope,
3286 					parent_func, parent_func->common.scope,
3287 					ce, NULL,
3288 					ZEND_INHERITANCE_CHECK_SILENT | ZEND_INHERITANCE_CHECK_PROTO | ZEND_INHERITANCE_CHECK_VISIBILITY);
3289 			if (UNEXPECTED(status == INHERITANCE_WARNING)) {
3290 				overall_status = INHERITANCE_WARNING;
3291 			} else if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
3292 				return status;
3293 			}
3294 		}
3295 	} ZEND_HASH_FOREACH_END();
3296 
3297 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->properties_info, key, parent_info) {
3298 		zval *zv;
3299 		if ((parent_info->flags & ZEND_ACC_PRIVATE) || !ZEND_TYPE_IS_SET(parent_info->type)) {
3300 			continue;
3301 		}
3302 
3303 		zv = zend_hash_find_known_hash(&ce->properties_info, key);
3304 		if (zv) {
3305 			zend_property_info *child_info = Z_PTR_P(zv);
3306 			if (ZEND_TYPE_IS_SET(child_info->type)) {
3307 				inheritance_status status = property_types_compatible(parent_info, child_info);
3308 				ZEND_ASSERT(status != INHERITANCE_WARNING);
3309 				if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
3310 					return status;
3311 				}
3312 			}
3313 		}
3314 	} ZEND_HASH_FOREACH_END();
3315 
3316 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&parent_ce->constants_table, key, parent_const) {
3317 		zval *zv;
3318 		if ((ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PRIVATE) || !ZEND_TYPE_IS_SET(parent_const->type)) {
3319 			continue;
3320 		}
3321 
3322 		zv = zend_hash_find_known_hash(&ce->constants_table, key);
3323 		if (zv) {
3324 			zend_class_constant *child_const = Z_PTR_P(zv);
3325 			if (ZEND_TYPE_IS_SET(child_const->type)) {
3326 				inheritance_status status = class_constant_types_compatible(parent_const, child_const);
3327 				ZEND_ASSERT(status != INHERITANCE_WARNING);
3328 				if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
3329 					return status;
3330 				}
3331 			}
3332 		}
3333 	} ZEND_HASH_FOREACH_END();
3334 
3335 	return overall_status;
3336 }
3337 /* }}} */
3338 
register_early_bound_ce(zval * delayed_early_binding,zend_string * lcname,zend_class_entry * ce)3339 static zend_always_inline bool register_early_bound_ce(zval *delayed_early_binding, zend_string *lcname, zend_class_entry *ce) {
3340 	if (delayed_early_binding) {
3341 		if (EXPECTED(!(ce->ce_flags & ZEND_ACC_PRELOADED))) {
3342 			if (zend_hash_set_bucket_key(EG(class_table), (Bucket *)delayed_early_binding, lcname) != NULL) {
3343 				Z_CE_P(delayed_early_binding) = ce;
3344 				return true;
3345 			}
3346 		} else {
3347 			/* If preloading is used, don't replace the existing bucket, add a new one. */
3348 			if (zend_hash_add_ptr(EG(class_table), lcname, ce) != NULL) {
3349 				return true;
3350 			}
3351 		}
3352 		zend_class_entry *old_ce = zend_hash_find_ptr(EG(class_table), lcname);
3353 		ZEND_ASSERT(old_ce);
3354 		zend_class_redeclaration_error(E_COMPILE_ERROR, old_ce);
3355 		return false;
3356 	}
3357 	if (zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL) {
3358 		return true;
3359 	}
3360 	return false;
3361 }
3362 
zend_try_early_bind(zend_class_entry * ce,zend_class_entry * parent_ce,zend_string * lcname,zval * delayed_early_binding)3363 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) /* {{{ */
3364 {
3365 	inheritance_status status;
3366 	zend_class_entry *proto = NULL;
3367 	zend_class_entry *orig_linking_class;
3368 
3369 	if (ce->ce_flags & ZEND_ACC_LINKED) {
3370 		ZEND_ASSERT(ce->parent == NULL);
3371 		if (UNEXPECTED(!register_early_bound_ce(delayed_early_binding, lcname, ce))) {
3372 			return NULL;
3373 		}
3374 		zend_observer_class_linked_notify(ce, lcname);
3375 		return ce;
3376 	}
3377 
3378 	uint32_t is_cacheable = ce->ce_flags & ZEND_ACC_IMMUTABLE;
3379 	UPDATE_IS_CACHEABLE(parent_ce);
3380 	if (is_cacheable) {
3381 		if (zend_inheritance_cache_get && zend_inheritance_cache_add) {
3382 			zend_class_entry *ret = zend_inheritance_cache_get(ce, parent_ce, NULL);
3383 			if (ret) {
3384 				if (UNEXPECTED(!register_early_bound_ce(delayed_early_binding, lcname, ret))) {
3385 					return NULL;
3386 				}
3387 				zend_observer_class_linked_notify(ret, lcname);
3388 				return ret;
3389 			}
3390 		} else {
3391 			is_cacheable = 0;
3392 		}
3393 		proto = ce;
3394 	}
3395 
3396 	orig_linking_class = CG(current_linking_class);
3397 	CG(current_linking_class) = NULL;
3398 	status = zend_can_early_bind(ce, parent_ce);
3399 	CG(current_linking_class) = orig_linking_class;
3400 	if (EXPECTED(status != INHERITANCE_UNRESOLVED)) {
3401 		if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
3402 			/* Lazy class loading */
3403 			ce = zend_lazy_class_load(ce);
3404 		} else if (ce->ce_flags & ZEND_ACC_FILE_CACHED) {
3405 			/* Lazy class loading */
3406 			ce = zend_lazy_class_load(ce);
3407 			ce->ce_flags &= ~ZEND_ACC_FILE_CACHED;
3408 		}
3409 
3410 		if (UNEXPECTED(!register_early_bound_ce(delayed_early_binding, lcname, ce))) {
3411 			return NULL;
3412 		}
3413 
3414 		orig_linking_class = CG(current_linking_class);
3415 		CG(current_linking_class) = is_cacheable ? ce : NULL;
3416 
3417 		zend_try{
3418 			if (is_cacheable) {
3419 				zend_begin_record_errors();
3420 			}
3421 
3422 			zend_do_inheritance_ex(ce, parent_ce, status == INHERITANCE_SUCCESS);
3423 			if (parent_ce && parent_ce->num_interfaces) {
3424 				zend_do_inherit_interfaces(ce, parent_ce);
3425 			}
3426 			zend_build_properties_info_table(ce);
3427 			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) {
3428 				zend_verify_abstract_class(ce);
3429 			}
3430 			zend_inheritance_check_override(ce);
3431 			ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE));
3432 			ce->ce_flags |= ZEND_ACC_LINKED;
3433 
3434 			CG(current_linking_class) = orig_linking_class;
3435 		} zend_catch {
3436 			EG(record_errors) = false;
3437 			zend_free_recorded_errors();
3438 			zend_bailout();
3439 		} zend_end_try();
3440 
3441 		EG(record_errors) = false;
3442 
3443 		if (is_cacheable) {
3444 			HashTable *ht = (HashTable*)ce->inheritance_cache;
3445 			zend_class_entry *new_ce;
3446 
3447 			ce->inheritance_cache = NULL;
3448 			new_ce = zend_inheritance_cache_add(ce, proto, parent_ce, NULL, ht);
3449 			if (new_ce) {
3450 				zval *zv = zend_hash_find_known_hash(CG(class_table), lcname);
3451 				ce = new_ce;
3452 				Z_CE_P(zv) = ce;
3453 			}
3454 			if (ht) {
3455 				zend_hash_destroy(ht);
3456 				FREE_HASHTABLE(ht);
3457 			}
3458 		}
3459 
3460 		if (ZSTR_HAS_CE_CACHE(ce->name)) {
3461 			ZSTR_SET_CE_CACHE(ce->name, ce);
3462 		}
3463 		zend_observer_class_linked_notify(ce, lcname);
3464 
3465 		return ce;
3466 	}
3467 	return NULL;
3468 }
3469 /* }}} */
3470