mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Ensure correct signatures for magic methods
This commit is contained in:
parent
650801ce45
commit
e3d06fc79d
30 changed files with 506 additions and 3 deletions
20
UPGRADING
20
UPGRADING
|
@ -236,6 +236,26 @@ PHP 8.0 UPGRADE NOTES
|
||||||
"Illegal string offset 'string'" for illegal string offsets. The behavior
|
"Illegal string offset 'string'" for illegal string offsets. The behavior
|
||||||
of explicit casts to int/float from strings has not been changed.
|
of explicit casts to int/float from strings has not been changed.
|
||||||
RFC: https://wiki.php.net/rfc/saner-numeric-strings
|
RFC: https://wiki.php.net/rfc/saner-numeric-strings
|
||||||
|
. Magic Methods will now have their arguments and return types
|
||||||
|
checked if they have them declared. The signatures should
|
||||||
|
match the following list:
|
||||||
|
|
||||||
|
__call(string $name, array $arguments): mixed
|
||||||
|
__callStatic(string $name, array $arguments): mixed
|
||||||
|
__clone(): void
|
||||||
|
__debugInfo(): ?array
|
||||||
|
__get(string $name): mixed
|
||||||
|
__invoke(mixed $arguments): mixed
|
||||||
|
__isset(string $name): bool
|
||||||
|
__serialize(): array
|
||||||
|
__set(string $name, mixed $value): void
|
||||||
|
__set_state(array $properties): object
|
||||||
|
__sleep(): array
|
||||||
|
__unserialize(array $data): void
|
||||||
|
__unset(string $name): void
|
||||||
|
__wakeup(): void
|
||||||
|
|
||||||
|
RFC: https://wiki.php.net/rfc/magic-methods-signature
|
||||||
|
|
||||||
- COM:
|
- COM:
|
||||||
. Removed the ability to import case-insensitive constants from type
|
. Removed the ability to import case-insensitive constants from type
|
||||||
|
|
10
Zend/tests/magic_methods_011.phpt
Normal file
10
Zend/tests/magic_methods_011.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__set first parameter should be a string when typed
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
function __set(\Countable $name, $value) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__set(): Parameter #1 ($name) must be of type string when declared in %s on line %d
|
10
Zend/tests/magic_methods_012.phpt
Normal file
10
Zend/tests/magic_methods_012.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__get first parameter should be a string when typed
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
function __get(int $name) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__get(): Parameter #1 ($name) must be of type string when declared in %s on line %d
|
10
Zend/tests/magic_methods_013.phpt
Normal file
10
Zend/tests/magic_methods_013.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__isset first parameter should be a string when typed
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
function __isset(\stdClass $name) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__isset(): Parameter #1 ($name) must be of type string when declared in %s on line %d
|
10
Zend/tests/magic_methods_014.phpt
Normal file
10
Zend/tests/magic_methods_014.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__unset first parameter should be a string when typed
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
function __unset(array $name) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__unset(): Parameter #1 ($name) must be of type string when declared in %s on line %d
|
10
Zend/tests/magic_methods_015.phpt
Normal file
10
Zend/tests/magic_methods_015.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__call first parameter should be a string typed
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
function __call(int $name, array $arguments) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__call(): Parameter #1 ($name) must be of type string when declared in %s on line %d
|
10
Zend/tests/magic_methods_016.phpt
Normal file
10
Zend/tests/magic_methods_016.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__call second parameter should be an array when typed
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
function __call(string $name, \Arguments $arguments) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__call(): Parameter #2 ($arguments) must be of type array when declared in %s on line %d
|
10
Zend/tests/magic_methods_017.phpt
Normal file
10
Zend/tests/magic_methods_017.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__callStatic first parameter should be a string typed
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
static function __callStatic(int $name, array $arguments) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__callStatic(): Parameter #1 ($name) must be of type string when declared in %s on line %d
|
10
Zend/tests/magic_methods_018.phpt
Normal file
10
Zend/tests/magic_methods_018.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__callStatic second parameter should be an array typed
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
static function __callStatic(string $name, \Arguments $args) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__callStatic(): Parameter #2 ($args) must be of type array when declared in %s on line %d
|
10
Zend/tests/magic_methods_019.phpt
Normal file
10
Zend/tests/magic_methods_019.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__unserialize first parameter must be an array
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public function __unserialize(string $name) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__unserialize(): Parameter #1 ($name) must be of type array when declared in %s on line %d
|
70
Zend/tests/magic_methods_inheritance_rules.phpt
Normal file
70
Zend/tests/magic_methods_inheritance_rules.phpt
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
--TEST--
|
||||||
|
Magic Methods inheritance rules
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class ValidMagicMethods {
|
||||||
|
public function __call(string $name, array $arguments): mixed {}
|
||||||
|
|
||||||
|
public static function __callStatic(string $name, array $arguments): mixed {}
|
||||||
|
|
||||||
|
public function __clone(): void {}
|
||||||
|
|
||||||
|
public function __debugInfo(): ?array {}
|
||||||
|
|
||||||
|
public function __get(string $name): mixed {}
|
||||||
|
|
||||||
|
public function __invoke(mixed $arguments): mixed {}
|
||||||
|
|
||||||
|
public function __isset(string $name): bool {}
|
||||||
|
|
||||||
|
public function __serialize(): array {}
|
||||||
|
|
||||||
|
public function __set(string $name, mixed $value): void {}
|
||||||
|
|
||||||
|
public static function __set_state(array $properties): object {}
|
||||||
|
|
||||||
|
public function __sleep(): array {}
|
||||||
|
|
||||||
|
public function __toString(): string {}
|
||||||
|
|
||||||
|
public function __unserialize(array $data): void {}
|
||||||
|
|
||||||
|
public function __unset(string $name): void {}
|
||||||
|
|
||||||
|
public function __wakeup(): void {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NarrowedReturnType extends ValidMagicMethods {
|
||||||
|
public function __call(string $name, array $arguments): string|float|null {}
|
||||||
|
|
||||||
|
public static function __callStatic(string $name, array $arguments): ?array {}
|
||||||
|
|
||||||
|
public function __debugInfo(): array {}
|
||||||
|
|
||||||
|
public function __get(string $name): int|string {}
|
||||||
|
|
||||||
|
public function __invoke(mixed $arguments): object {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WidenedArgumentType extends NarrowedReturnType {
|
||||||
|
public function __call(string|array $name, array|string $arguments): string|float|null {}
|
||||||
|
|
||||||
|
public static function __callStatic(string|object $name, array|object $arguments): ?array {}
|
||||||
|
|
||||||
|
public function __get(string|array $name): int|string {}
|
||||||
|
|
||||||
|
public function __isset(string|bool $name): bool {}
|
||||||
|
|
||||||
|
public function __set(string|bool|float $name, mixed $value): void {}
|
||||||
|
|
||||||
|
public static function __set_state(string|array $properties): object {}
|
||||||
|
|
||||||
|
public function __unserialize(array|string $data): void {}
|
||||||
|
|
||||||
|
public function __unset(string|array $name): void {}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo 'No problems!';
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
No problems!
|
|
@ -0,0 +1,18 @@
|
||||||
|
--TEST--
|
||||||
|
Magic Methods inheritance rules on a non-trivial class hierarchy
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class A {
|
||||||
|
public function __get(string|array $name): mixed {} // valid
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {
|
||||||
|
public function __get(string|array|object $name): int {} // also valid
|
||||||
|
}
|
||||||
|
|
||||||
|
class C extends B {
|
||||||
|
public function __get(string|array $name): int {} // this is invalid
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Declaration of C::__get(array|string $name): int must be compatible with B::__get(object|array|string $name): int in %s on line %d
|
|
@ -0,0 +1,18 @@
|
||||||
|
--TEST--
|
||||||
|
Magic Methods inheritance rules on a non-trivial class hierarchy
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class A {
|
||||||
|
public function __get(string|array $name): mixed {} // valid
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {
|
||||||
|
public function __get(string|array|object $name): int {} // also valid
|
||||||
|
}
|
||||||
|
|
||||||
|
class C extends B {
|
||||||
|
public function __get(string|array|object $name): int|float {} // this is invalid
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Declaration of C::__get(object|array|string $name): int|float must be compatible with B::__get(object|array|string $name): int in %s on line %d
|
10
Zend/tests/magic_methods_sleep.phpt
Normal file
10
Zend/tests/magic_methods_sleep.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__sleep cannot take arguments
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public function __sleep(string $name) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Method Foo::__sleep() cannot take arguments in %s on line %d
|
10
Zend/tests/magic_methods_wakeup.phpt
Normal file
10
Zend/tests/magic_methods_wakeup.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__wakeup cannot take arguments
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public function __wakeup(string $name) {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Method Foo::__wakeup() cannot take arguments in %s on line %d
|
|
@ -1,10 +1,11 @@
|
||||||
--TEST--
|
--TEST--
|
||||||
__clone cannot declare a return type
|
__clone can only declare void return
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
class Foo {
|
class Foo {
|
||||||
function __clone() : Foo {}
|
function __clone() : Foo {}
|
||||||
}
|
}
|
||||||
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: %s::%s() cannot declare a return type in %s on line %d
|
Fatal error: Foo::__clone(): Return type must be void when declared in %s on line %d
|
||||||
|
|
10
Zend/tests/return_types/033.phpt
Normal file
10
Zend/tests/return_types/033.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__set can only declare void return
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
function __set($name, $value) : string {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__set(): Return type must be void when declared in %s on line %d
|
10
Zend/tests/return_types/034.phpt
Normal file
10
Zend/tests/return_types/034.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__isset can only declare a boolean return type
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
function __isset($name) : \stdClass|bool {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__isset(): Return type must be bool when declared in %s on line %d
|
10
Zend/tests/return_types/035.phpt
Normal file
10
Zend/tests/return_types/035.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__unset can only declare void return
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
function __unset($name) : bool {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__unset(): Return type must be void when declared in %s on line %d
|
11
Zend/tests/return_types/036.phpt
Normal file
11
Zend/tests/return_types/036.phpt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
--TEST--
|
||||||
|
__toString can only declare string return type
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public function __toString(): bool {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Declaration of Foo::__toString(): bool must be compatible with Stringable::__toString(): string in %s on line %d
|
11
Zend/tests/return_types/037.phpt
Normal file
11
Zend/tests/return_types/037.phpt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
--TEST--
|
||||||
|
__debugInfo can only declare array as return type
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public function __debugInfo(): bool {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__debugInfo(): Return type must be ?array when declared in %s on line %d
|
10
Zend/tests/return_types/038.phpt
Normal file
10
Zend/tests/return_types/038.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__serialize can only declare array as return type
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public function __serialize(): \stdClass {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__serialize(): Return type must be array when declared in %s on line %d
|
10
Zend/tests/return_types/039.phpt
Normal file
10
Zend/tests/return_types/039.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__unserialize can only declare void return
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public function __unserialize(array $data): array {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__unserialize(): Return type must be void when declared in %s on line %d
|
10
Zend/tests/return_types/040.phpt
Normal file
10
Zend/tests/return_types/040.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__sleep can only declare return as array
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public function __sleep(): bool|int {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__sleep(): Return type must be array when declared in %s on line %d
|
10
Zend/tests/return_types/041.phpt
Normal file
10
Zend/tests/return_types/041.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__wakeup can only declare return void
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public function __wakeup(): bool {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__wakeup(): Return type must be void when declared in %s on line %d
|
24
Zend/tests/return_types/042.phpt
Normal file
24
Zend/tests/return_types/042.phpt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
--TEST--
|
||||||
|
__debugInfo can declare union return type
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class UnionType {
|
||||||
|
public function __debugInfo(): array|null {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnionType2 {
|
||||||
|
public function __debugInfo(): null|array {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnionTypeOldStyle {
|
||||||
|
public function __debugInfo(): ?array {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JustAnArray {
|
||||||
|
public function __debugInfo(): array {}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo 'No problems!';
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
No problems!
|
29
Zend/tests/return_types/043.phpt
Normal file
29
Zend/tests/return_types/043.phpt
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
--TEST--
|
||||||
|
Some magic methods can declare mixed return type
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public function __get($name): bool {}
|
||||||
|
public function __call($name, $args): string {}
|
||||||
|
public static function __callStatic($name, $args): self {}
|
||||||
|
public function __invoke(): self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
public function __get($name): string|array {}
|
||||||
|
public function __call($name, $args): int|float {}
|
||||||
|
public static function __callStatic($name, $args): ?object {}
|
||||||
|
public function __invoke(): Foo|int {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Baz {
|
||||||
|
public function __get($name): mixed {}
|
||||||
|
public function __call($name, $args): mixed {}
|
||||||
|
public static function __callStatic($name, $args): mixed {}
|
||||||
|
public function __invoke(): mixed {}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo 'Okay!';
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Okay!
|
10
Zend/tests/return_types/044.phpt
Normal file
10
Zend/tests/return_types/044.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
__set_state can only declare object as return
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo {
|
||||||
|
public static function __set_state($properties): bool {}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Foo::__set_state(): Return type must be object when declared in %s on line %d
|
|
@ -2048,6 +2048,31 @@ static void zend_check_magic_method_args(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void zend_check_magic_method_arg_type(uint32_t arg_num, const zend_class_entry *ce, const zend_function *fptr, int error_type, int arg_type)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
ZEND_TYPE_IS_SET(fptr->common.arg_info[arg_num].type)
|
||||||
|
&& !(ZEND_TYPE_FULL_MASK(fptr->common.arg_info[arg_num].type) & arg_type)
|
||||||
|
) {
|
||||||
|
zend_error(error_type, "%s::%s(): Parameter #%d ($%s) must be of type %s when declared",
|
||||||
|
ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name),
|
||||||
|
arg_num + 1, ZSTR_VAL(fptr->common.arg_info[arg_num].name),
|
||||||
|
ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(arg_type))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zend_check_magic_method_return_type(const zend_class_entry *ce, const zend_function *fptr, int error_type, int return_type)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)
|
||||||
|
&& (ZEND_TYPE_FULL_MASK(fptr->common.arg_info[-1].type) & ~return_type)
|
||||||
|
) {
|
||||||
|
zend_error(error_type, "%s::%s(): Return type must be %s when declared",
|
||||||
|
ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name),
|
||||||
|
ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(return_type))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void zend_check_magic_method_non_static(
|
static void zend_check_magic_method_non_static(
|
||||||
const zend_class_entry *ce, const zend_function *fptr, int error_type)
|
const zend_class_entry *ce, const zend_function *fptr, int error_type)
|
||||||
{
|
{
|
||||||
|
@ -2102,31 +2127,42 @@ ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce,
|
||||||
} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
|
} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
|
||||||
zend_check_magic_method_args(0, ce, fptr, error_type);
|
zend_check_magic_method_args(0, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_no_return_type(ce, fptr, error_type);
|
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
|
||||||
} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
|
} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
|
||||||
zend_check_magic_method_args(1, ce, fptr, error_type);
|
zend_check_magic_method_args(1, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
|
||||||
} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
|
} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
|
||||||
zend_check_magic_method_args(2, ce, fptr, error_type);
|
zend_check_magic_method_args(2, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
|
||||||
|
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
|
||||||
} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
|
} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
|
||||||
zend_check_magic_method_args(1, ce, fptr, error_type);
|
zend_check_magic_method_args(1, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
|
||||||
|
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
|
||||||
} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
|
} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
|
||||||
zend_check_magic_method_args(1, ce, fptr, error_type);
|
zend_check_magic_method_args(1, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
|
||||||
|
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_BOOL);
|
||||||
} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
|
} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
|
||||||
zend_check_magic_method_args(2, ce, fptr, error_type);
|
zend_check_magic_method_args(2, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
|
||||||
|
zend_check_magic_method_arg_type(1, ce, fptr, error_type, MAY_BE_ARRAY);
|
||||||
} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
|
} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
|
||||||
zend_check_magic_method_args(2, ce, fptr, error_type);
|
zend_check_magic_method_args(2, ce, fptr, error_type);
|
||||||
zend_check_magic_method_static(ce, fptr, error_type);
|
zend_check_magic_method_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
|
||||||
|
zend_check_magic_method_arg_type(1, ce, fptr, error_type, MAY_BE_ARRAY);
|
||||||
} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
|
} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
|
||||||
zend_check_magic_method_args(0, ce, fptr, error_type);
|
zend_check_magic_method_args(0, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
|
@ -2135,21 +2171,36 @@ ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce,
|
||||||
zend_check_magic_method_args(0, ce, fptr, error_type);
|
zend_check_magic_method_args(0, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_return_type(ce, fptr, error_type, (MAY_BE_ARRAY | MAY_BE_NULL));
|
||||||
} else if (zend_string_equals_literal(lcname, "__serialize")) {
|
} else if (zend_string_equals_literal(lcname, "__serialize")) {
|
||||||
zend_check_magic_method_args(0, ce, fptr, error_type);
|
zend_check_magic_method_args(0, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_ARRAY);
|
||||||
} else if (zend_string_equals_literal(lcname, "__unserialize")) {
|
} else if (zend_string_equals_literal(lcname, "__unserialize")) {
|
||||||
zend_check_magic_method_args(1, ce, fptr, error_type);
|
zend_check_magic_method_args(1, ce, fptr, error_type);
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_ARRAY);
|
||||||
|
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
|
||||||
} else if (zend_string_equals_literal(lcname, "__set_state")) {
|
} else if (zend_string_equals_literal(lcname, "__set_state")) {
|
||||||
zend_check_magic_method_args(1, ce, fptr, error_type);
|
zend_check_magic_method_args(1, ce, fptr, error_type);
|
||||||
zend_check_magic_method_static(ce, fptr, error_type);
|
zend_check_magic_method_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_OBJECT);
|
||||||
} else if (zend_string_equals_literal(lcname, "__invoke")) {
|
} else if (zend_string_equals_literal(lcname, "__invoke")) {
|
||||||
zend_check_magic_method_non_static(ce, fptr, error_type);
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
zend_check_magic_method_public(ce, fptr, error_type);
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
} else if (zend_string_equals_literal(lcname, "__sleep")) {
|
||||||
|
zend_check_magic_method_args(0, ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_ARRAY);
|
||||||
|
} else if (zend_string_equals_literal(lcname, "__wakeup")) {
|
||||||
|
zend_check_magic_method_args(0, ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_non_static(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_public(ce, fptr, error_type);
|
||||||
|
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
|
@ -32,10 +32,14 @@ class TestClass
|
||||||
|
|
||||||
public final function fin() {}
|
public final function fin() {}
|
||||||
|
|
||||||
|
public function __construct() {}
|
||||||
|
|
||||||
public function __destruct() {}
|
public function __destruct() {}
|
||||||
|
|
||||||
public function __call($a, $b) {}
|
public function __call($a, $b) {}
|
||||||
|
|
||||||
|
public static function __callStatic($a, $b) {}
|
||||||
|
|
||||||
public function __clone() {}
|
public function __clone() {}
|
||||||
|
|
||||||
public function __get($a) {}
|
public function __get($a) {}
|
||||||
|
@ -44,6 +48,8 @@ class TestClass
|
||||||
|
|
||||||
public function __unset($a) {}
|
public function __unset($a) {}
|
||||||
|
|
||||||
|
public function __invoke() {}
|
||||||
|
|
||||||
public function __isset($a) {}
|
public function __isset($a) {}
|
||||||
|
|
||||||
public function __tostring() {}
|
public function __tostring() {}
|
||||||
|
@ -55,6 +61,12 @@ class TestClass
|
||||||
public static function __set_state($a) {}
|
public static function __set_state($a) {}
|
||||||
|
|
||||||
public function __autoload() {}
|
public function __autoload() {}
|
||||||
|
|
||||||
|
public function __serialize() {}
|
||||||
|
|
||||||
|
public function __unserialize($data) {}
|
||||||
|
|
||||||
|
public function __debugInfo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DerivedClass extends TestClass {}
|
class DerivedClass extends TestClass {}
|
||||||
|
@ -102,6 +114,10 @@ Modifiers for method TestClass::fin():
|
||||||
0x00000021
|
0x00000021
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__construct():
|
||||||
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
Modifiers for method TestClass::__destruct():
|
Modifiers for method TestClass::__destruct():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
@ -110,6 +126,10 @@ Modifiers for method TestClass::__call():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__callStatic():
|
||||||
|
0x00000011
|
||||||
|
|
||||||
|
|
||||||
Modifiers for method TestClass::__clone():
|
Modifiers for method TestClass::__clone():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
@ -126,6 +146,10 @@ Modifiers for method TestClass::__unset():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__invoke():
|
||||||
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
Modifiers for method TestClass::__isset():
|
Modifiers for method TestClass::__isset():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
@ -150,6 +174,18 @@ Modifiers for method TestClass::__autoload():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__serialize():
|
||||||
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__unserialize():
|
||||||
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__debugInfo():
|
||||||
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
Modifiers for method TestClass::foo():
|
Modifiers for method TestClass::foo():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
@ -166,6 +202,10 @@ Modifiers for method TestClass::fin():
|
||||||
0x00000021
|
0x00000021
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__construct():
|
||||||
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
Modifiers for method TestClass::__destruct():
|
Modifiers for method TestClass::__destruct():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
@ -174,6 +214,10 @@ Modifiers for method TestClass::__call():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__callStatic():
|
||||||
|
0x00000011
|
||||||
|
|
||||||
|
|
||||||
Modifiers for method TestClass::__clone():
|
Modifiers for method TestClass::__clone():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
@ -190,6 +234,10 @@ Modifiers for method TestClass::__unset():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__invoke():
|
||||||
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
Modifiers for method TestClass::__isset():
|
Modifiers for method TestClass::__isset():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
@ -214,6 +262,18 @@ Modifiers for method TestClass::__autoload():
|
||||||
0x00000001
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__serialize():
|
||||||
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__unserialize():
|
||||||
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
|
Modifiers for method TestClass::__debugInfo():
|
||||||
|
0x00000001
|
||||||
|
|
||||||
|
|
||||||
Modifiers for method TestInterface::int():
|
Modifiers for method TestInterface::int():
|
||||||
0x00000041
|
0x00000041
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue