summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-01-30 11:55:38 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-01-30 11:55:38 +0100
commit68596ed71e44b64d15bb51cb67671ae8e41538f6 (patch)
treecef56c72a525b871670756a819b211fb05a2a608
parenta73f98eda9b62d8d5024cd55c7d9c2b0b9380414 (diff)
downloadphp-git-68596ed71e44b64d15bb51cb67671ae8e41538f6.tar.gz
Fix copying of functions in variance obligations
Only copy sizeof(zend_internal_function) for internal functions.
-rw-r--r--Zend/tests/type_declarations/variance/internal_parent.phpt12
-rw-r--r--Zend/zend_inheritance.c13
2 files changed, 23 insertions, 2 deletions
diff --git a/Zend/tests/type_declarations/variance/internal_parent.phpt b/Zend/tests/type_declarations/variance/internal_parent.phpt
new file mode 100644
index 0000000000..eaef902b66
--- /dev/null
+++ b/Zend/tests/type_declarations/variance/internal_parent.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Internal class as parent
+--FILE--
+<?php
+
+class Test extends DateTime {
+ public static function createFromFormat($format, $time, Wrong $timezone = null) { }
+}
+
+?>
+--EXPECTF--
+Warning: Could not check compatibility between Test::createFromFormat($format, $time, ?Wrong $timezone = NULL) and DateTime::createFromFormat($format, $time, ?DateTimeZone $object = NULL), because class Wrong is not available in %s on line %d
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index 442ab8afc1..6bd35a6bb7 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -2294,8 +2294,17 @@ static void add_compatibility_obligation(
HashTable *obligations = get_or_init_obligations_for_class(ce);
variance_obligation *obligation = emalloc(sizeof(variance_obligation));
obligation->type = OBLIGATION_COMPATIBILITY;
- obligation->child_fn = *child_fn;
- obligation->parent_fn = *parent_fn;
+ /* Copy functions, because they may be stack-allocated in the case of traits. */
+ if (child_fn->common.type == ZEND_INTERNAL_FUNCTION) {
+ memcpy(&obligation->child_fn, child_fn, sizeof(zend_internal_function));
+ } else {
+ memcpy(&obligation->child_fn, child_fn, sizeof(zend_op_array));
+ }
+ if (parent_fn->common.type == ZEND_INTERNAL_FUNCTION) {
+ memcpy(&obligation->parent_fn, parent_fn, sizeof(zend_internal_function));
+ } else {
+ memcpy(&obligation->parent_fn, parent_fn, sizeof(zend_op_array));
+ }
obligation->always_error = always_error;
zend_hash_next_index_insert_ptr(obligations, obligation);
}