Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Zend/tests/debug_info/debug_info-error-0.0.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ $c = new C(0.0);
var_dump($c);
?>
--EXPECTF--
Fatal error: __debuginfo() must return an array in %s on line %d
Fatal error: __debugInfo() must return an array in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/debug_info/debug_info-error-0.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ $c = new C(0);
var_dump($c);
?>
--EXPECTF--
Fatal error: __debuginfo() must return an array in %s on line %d
Fatal error: __debugInfo() must return an array in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/debug_info/debug_info-error-1.0.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ $c = new C(1.0);
var_dump($c);
?>
--EXPECTF--
Fatal error: __debuginfo() must return an array in %s on line %d
Fatal error: __debugInfo() must return an array in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/debug_info/debug_info-error-1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ $c = new C(1);
var_dump($c);
?>
--EXPECTF--
Fatal error: __debuginfo() must return an array in %s on line %d
Fatal error: __debugInfo() must return an array in %s on line %d
20 changes: 20 additions & 0 deletions Zend/tests/debug_info/debug_info-error-case-insensitive.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
Testing __debugInfo() magic method declared with non-canonical case
--FILE--
<?php

class C {
public $val;
public function __DEBUGINFO() {
return $this->val;
}
public function __construct($val) {
$this->val = $val;
}
}

$c = new C(1);
var_dump($c);
?>
--EXPECTF--
Fatal error: __debugInfo() must return an array in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/debug_info/debug_info-error-empty_str.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ $c = new C("");
var_dump($c);
?>
--EXPECTF--
Fatal error: __debuginfo() must return an array in %s on line %d
Fatal error: __debugInfo() must return an array in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/debug_info/debug_info-error-false.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ $c = new C(false);
var_dump($c);
?>
--EXPECTF--
Fatal error: __debuginfo() must return an array in %s on line %d
Fatal error: __debugInfo() must return an array in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/debug_info/debug_info-error-object.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ $c = new C(new stdClass);
var_dump($c);
?>
--EXPECTF--
Fatal error: __debuginfo() must return an array in %s on line %d
Fatal error: __debugInfo() must return an array in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/debug_info/debug_info-error-resource.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ $c = new C(fopen("data:text/plain,Foo", 'r'));
var_dump($c);
?>
--EXPECTF--
Fatal error: __debuginfo() must return an array in %s on line %d
Fatal error: __debugInfo() must return an array in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/debug_info/debug_info-error-str.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ $c = new C("foo");
var_dump($c);
?>
--EXPECTF--
Fatal error: __debuginfo() must return an array in %s on line %d
Fatal error: __debugInfo() must return an array in %s on line %d
2 changes: 1 addition & 1 deletion Zend/tests/debug_info/debug_info-error-true.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ $c = new C(true);
var_dump($c);
?>
--EXPECTF--
Fatal error: __debuginfo() must return an array in %s on line %d
Fatal error: __debugInfo() must return an array in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
--TEST--
Stringable is automatically implemented for __toString() declared with non-canonical case
--FILE--
<?php

class Test {
public function __TOSTRING() {
return "foo";
}
}

var_dump(new Test instanceof Stringable);
var_dump((new ReflectionClass(Test::class))->getInterfaceNames());
var_dump((string) new Test);

?>
--EXPECT--
bool(true)
array(1) {
[0]=>
string(10) "Stringable"
}
string(3) "foo"
24 changes: 12 additions & 12 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -2809,18 +2809,18 @@ ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce,
zend_check_magic_method_public(ce, fptr);
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_LCNAME)) {
zend_check_magic_method_args(2, ce, fptr, error_type);
zend_check_magic_method_static(ce, fptr, error_type);
zend_check_magic_method_public(ce, fptr);
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_LCNAME)) {
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);
zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_STRING);
} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_LCNAME)) {
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);
Expand All @@ -2829,18 +2829,18 @@ ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce,
zend_error(E_DEPRECATED, "Returning null from %s::__debugInfo() is deprecated, make the return type non-nullable and return an empty array instead",
ZSTR_VAL(ce->name));
}
} else if (zend_string_equals_literal(lcname, "__serialize")) {
} else if (zend_string_equals_literal(lcname, ZEND_SERIALIZE_FUNC_NAME)) {
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);
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, ZEND_UNSERIALIZE_FUNC_NAME)) {
zend_check_magic_method_args(1, ce, fptr, error_type);
zend_check_magic_method_non_static(ce, fptr, error_type);
zend_check_magic_method_public(ce, fptr);
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, ZEND_SET_STATE_FUNC_NAME)) {
zend_check_magic_method_args(1, ce, fptr, error_type);
zend_check_magic_method_static(ce, fptr, error_type);
zend_check_magic_method_public(ce, fptr);
Expand Down Expand Up @@ -2888,16 +2888,16 @@ ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, c
} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
ce->__isset = fptr;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_LCNAME)) {
ce->__callstatic = fptr;
} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_LCNAME)) {
ce->__tostring = fptr;
} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_LCNAME)) {
ce->__debugInfo = fptr;
ce->ce_flags |= ZEND_ACC_USE_GUARDS;
} else if (zend_string_equals_literal(lcname, "__serialize")) {
} else if (zend_string_equals_literal(lcname, ZEND_SERIALIZE_FUNC_NAME)) {
ce->__serialize = fptr;
} else if (zend_string_equals_literal(lcname, "__unserialize")) {
} else if (zend_string_equals_literal(lcname, ZEND_UNSERIALIZE_FUNC_NAME)) {
ce->__unserialize = fptr;
}
}
Expand Down Expand Up @@ -3111,7 +3111,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend

/* If not specified, add __toString() return type for compatibility with Stringable
* interface. */
if (scope && zend_string_equals_literal_ci(internal_function->function_name, "__tostring") &&
if (scope && zend_string_equals_literal_ci(internal_function->function_name, ZEND_TOSTRING_FUNC_LCNAME) &&
!(internal_function->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
zend_error(E_CORE_WARNING, "%s::__toString() implemented without string return type",
ZSTR_VAL(scope->name));
Expand Down
4 changes: 2 additions & 2 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -8610,7 +8610,7 @@ static zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string
}

zend_add_magic_method(ce, (zend_function *) op_array, lcname);
if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)
if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_LCNAME)
&& !(ce->ce_flags & ZEND_ACC_TRAIT)) {
add_stringable_interface(ce);
}
Expand Down Expand Up @@ -8841,7 +8841,7 @@ static zend_op_array *zend_compile_func_decl_ex(
}

zend_compile_params(params_ast, return_type_ast,
is_method && zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME) ? IS_STRING : 0);
is_method && zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_LCNAME) ? IS_STRING : 0);
if (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) {
zend_mark_function_as_generator();
zend_emit_op(NULL, ZEND_GENERATOR_CREATE, NULL, NULL);
Expand Down
16 changes: 12 additions & 4 deletions Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ typedef struct _zend_oparray_context {
#define ZEND_ACC_USES_THIS (1 << 17) /* | X | | */
/* | | | */
/* call through user function trampoline. e.g. | | | */
/* __call, __callstatic | | | */
/* __call, __callStatic | | | */
#define ZEND_ACC_CALL_VIA_TRAMPOLINE (1 << 18) /* | X | | */
/* | | | */
/* disable inline caching | | | */
Expand Down Expand Up @@ -1249,10 +1249,18 @@ END_EXTERN_C()
#define ZEND_UNSET_FUNC_NAME "__unset"
#define ZEND_ISSET_FUNC_NAME "__isset"
#define ZEND_CALL_FUNC_NAME "__call"
#define ZEND_CALLSTATIC_FUNC_NAME "__callstatic"
#define ZEND_TOSTRING_FUNC_NAME "__tostring"
#define ZEND_CALLSTATIC_FUNC_NAME "__callStatic"
#define ZEND_CALLSTATIC_FUNC_LCNAME "__callstatic"
#define ZEND_TOSTRING_FUNC_NAME "__toString"
#define ZEND_TOSTRING_FUNC_LCNAME "__tostring"
#define ZEND_INVOKE_FUNC_NAME "__invoke"
#define ZEND_DEBUGINFO_FUNC_NAME "__debuginfo"
#define ZEND_DEBUGINFO_FUNC_NAME "__debugInfo"
#define ZEND_DEBUGINFO_FUNC_LCNAME "__debuginfo"
#define ZEND_SLEEP_FUNC_NAME "__sleep"
#define ZEND_WAKEUP_FUNC_NAME "__wakeup"
#define ZEND_SERIALIZE_FUNC_NAME "__serialize"
#define ZEND_UNSERIALIZE_FUNC_NAME "__unserialize"
#define ZEND_SET_STATE_FUNC_NAME "__set_state"

/* The following constants may be combined in CG(compiler_options)
* to change the default compiler behavior */
Expand Down
26 changes: 13 additions & 13 deletions Zend/zend_enum.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,21 @@ static void zend_verify_enum_magic_methods(const zend_class_entry *ce)
{
// Only __get, __call, __debugInfo and __invoke are allowed

ZEND_ENUM_DISALLOW_MAGIC_METHOD(constructor, "__construct");
ZEND_ENUM_DISALLOW_MAGIC_METHOD(destructor, "__destruct");
ZEND_ENUM_DISALLOW_MAGIC_METHOD(clone, "__clone");
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__get, "__get");
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__set, "__set");
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__unset, "__unset");
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__isset, "__isset");
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__tostring, "__toString");
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__serialize, "__serialize");
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__unserialize, "__unserialize");
ZEND_ENUM_DISALLOW_MAGIC_METHOD(constructor, ZEND_CONSTRUCTOR_FUNC_NAME);
ZEND_ENUM_DISALLOW_MAGIC_METHOD(destructor, ZEND_DESTRUCTOR_FUNC_NAME);
ZEND_ENUM_DISALLOW_MAGIC_METHOD(clone, ZEND_CLONE_FUNC_NAME);
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__get, ZEND_GET_FUNC_NAME);
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__set, ZEND_SET_FUNC_NAME);
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__unset, ZEND_UNSET_FUNC_NAME);
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__isset, ZEND_ISSET_FUNC_NAME);
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__tostring, ZEND_TOSTRING_FUNC_NAME);
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__serialize, ZEND_SERIALIZE_FUNC_NAME);
ZEND_ENUM_DISALLOW_MAGIC_METHOD(__unserialize, ZEND_UNSERIALIZE_FUNC_NAME);

static const char *const forbidden_methods[] = {
"__sleep",
"__wakeup",
"__set_state",
ZEND_SLEEP_FUNC_NAME,
ZEND_WAKEUP_FUNC_NAME,
ZEND_SET_STATE_FUNC_NAME,
};

uint32_t forbidden_methods_length = sizeof(forbidden_methods) / sizeof(forbidden_methods[0]);
Expand Down
Loading