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