1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Set default_object_handlers when registering internal enums

Internal enums can be cloned and compared, unlike user enums, because we didn't set default_object_handlers when registering internal enums.

Fix by setting default_object_handlers when registering internal enums.

Fixes GH-20914
Closes GH-20915
This commit is contained in:
Arnaud Le Blanc
2026-01-13 12:32:52 +01:00
committed by GitHub
parent 1052270001
commit 075b6b85f6
10 changed files with 136 additions and 1 deletions

View File

@@ -0,0 +1,54 @@
--TEST--
Enum comparison (internal enum)
--EXTENSIONS--
zend_test
--FILE--
<?php
$foo = ZendTestUnitEnum::Foo;
$bar = ZendTestUnitEnum::Bar;
var_dump($foo === $foo);
var_dump($foo == $foo);
var_dump($foo === $bar);
var_dump($foo == $bar);
var_dump($bar === $foo);
var_dump($bar == $foo);
var_dump($foo > $foo);
var_dump($foo < $foo);
var_dump($foo >= $foo);
var_dump($foo <= $foo);
var_dump($foo > $bar);
var_dump($foo < $bar);
var_dump($foo >= $bar);
var_dump($foo <= $bar);
var_dump($foo > true);
var_dump($foo < true);
var_dump($foo >= true);
var_dump($foo <= true);
?>
--EXPECT--
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(true)
bool(true)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)

View File

@@ -0,0 +1,14 @@
--TEST--
Enum implements (internal enum)
--EXTENSIONS--
zend_test
--FILE--
<?php
var_dump(ZendTestUnitEnum::Foo instanceof _ZendTestInterface);
var_dump(ZendTestEnumWithInterface::Foo instanceof _ZendTestInterface);
?>
--EXPECT--
bool(false)
bool(true)

View File

@@ -1,5 +1,7 @@
--TEST--
Auto implement BackedEnum interface
--EXTENSIONS--
zend_test
--FILE--
<?php
@@ -13,8 +15,12 @@ enum Baz: int {
var_dump(Foo::Bar instanceof BackedEnum);
var_dump(Baz::Qux instanceof BackedEnum);
var_dump(ZendTestUnitEnum::Foo instanceof BackedEnum);
var_dump(ZendTestIntEnum::Foo instanceof BackedEnum);
?>
--EXPECT--
bool(false)
bool(true)
bool(false)
bool(true)

View File

@@ -1,5 +1,7 @@
--TEST--
Auto implement UnitEnum interface
--EXTENSIONS--
zend_test
--FILE--
<?php
@@ -11,8 +13,10 @@ class Baz {}
var_dump(Foo::Bar instanceof UnitEnum);
var_dump((new Baz()) instanceof UnitEnum);
var_dump(ZendTestUnitEnum::Foo instanceof UnitEnum);
?>
--EXPECT--
bool(true)
bool(false)
bool(true)

View File

@@ -0,0 +1,16 @@
--TEST--
Enum disallows cloning (internal enum)
--EXTENSIONS--
zend_test
--FILE--
<?php
try {
var_dump(clone ZendTestIntEnum::Foo);
} catch (Error $e) {
echo $e->getMessage() . "\n";
}
?>
--EXPECT--
Trying to clone an uncloneable object of class ZendTestIntEnum

View File

@@ -0,0 +1,18 @@
--TEST--
Enum case disallows dynamic properties (internal enum)
--EXTENSIONS--
zend_test
--FILE--
<?php
$bar = ZendTestUnitEnum::Bar;
try {
$bar->baz = 'Baz';
} catch (\Error $e) {
echo $e->getMessage();
}
?>
--EXPECT--
Cannot create dynamic property ZendTestUnitEnum::$baz

View File

@@ -528,6 +528,8 @@ ZEND_API zend_class_entry *zend_register_internal_enum(
zend_class_implements(ce, 1, zend_ce_backed_enum);
}
ce->default_object_handlers = &zend_enum_object_handlers;
return ce;
}

View File

@@ -74,6 +74,7 @@ static zend_class_entry *zend_test_ns2_ns_foo_class;
static zend_class_entry *zend_test_unit_enum;
static zend_class_entry *zend_test_string_enum;
static zend_class_entry *zend_test_int_enum;
static zend_class_entry *zend_test_enum_with_interface;
static zend_class_entry *zend_test_magic_call;
static zend_object_handlers zend_test_class_handlers;
@@ -1318,6 +1319,7 @@ PHP_MINIT_FUNCTION(zend_test)
zend_test_unit_enum = register_class_ZendTestUnitEnum();
zend_test_string_enum = register_class_ZendTestStringEnum();
zend_test_int_enum = register_class_ZendTestIntEnum();
zend_test_enum_with_interface = register_class_ZendTestEnumWithInterface(zend_test_interface);
zend_test_magic_call = register_class__ZendTestMagicCall();

View File

@@ -201,6 +201,11 @@ namespace {
case Baz = -1;
}
enum ZendTestEnumWithInterface implements _ZendTestInterface {
case Foo;
case Bar;
}
function zend_test_array_return(): array {}
/** @genstubs-expose-comment-block

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 6f76138d313c37244148004e2691ee47534f87a4 */
* Stub hash: bf65e1dd1eeeeec46687a76a7ea6554cd1971dfc */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
@@ -1189,6 +1189,20 @@ static zend_class_entry *register_class_ZendTestIntEnum(void)
}
#endif
#if (PHP_VERSION_ID >= 80100)
static zend_class_entry *register_class_ZendTestEnumWithInterface(zend_class_entry *class_entry__ZendTestInterface)
{
zend_class_entry *class_entry = zend_register_internal_enum("ZendTestEnumWithInterface", IS_UNDEF, NULL);
zend_class_implements(class_entry, 1, class_entry__ZendTestInterface);
zend_enum_add_case_cstr(class_entry, "Foo", NULL);
zend_enum_add_case_cstr(class_entry, "Bar", NULL);
return class_entry;
}
#endif
static zend_class_entry *register_class_ZendTestNS_Foo(void)
{
zend_class_entry ce, *class_entry;