]> granicus.if.org Git - php/commitdiff
Fix copying of functions in variance obligations
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 30 Jan 2020 10:55:38 +0000 (11:55 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 30 Jan 2020 10:55:38 +0000 (11:55 +0100)
Only copy sizeof(zend_internal_function) for internal functions.

Zend/tests/type_declarations/variance/internal_parent.phpt [new file with mode: 0644]
Zend/zend_inheritance.c

diff --git a/Zend/tests/type_declarations/variance/internal_parent.phpt b/Zend/tests/type_declarations/variance/internal_parent.phpt
new file mode 100644 (file)
index 0000000..eaef902
--- /dev/null
@@ -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
index 442ab8afc14b8b6c97a336e9320f155f9cc41abc..6bd35a6bb788d5b962ed8feda5ba67248ea04a03 100644 (file)
@@ -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);
 }