Skip to content

Commit 814a932

Browse files
committed
Add ZEND_ACC_NOT_SERIALIZABLE flag
This prevents serialization and unserialization of a class and its children in a way that does not depend on the zend_class_serialize_deny and zend_class_unserialize_deny handlers that will be going away in PHP 9 together with the Serializable interface. In stubs, `@not-serializable` can be used to set this flag. This patch only uses the new flag for a handful of Zend classes, converting the remainder is left for later. Closes GH-7249. Fixes bug #81111.
1 parent 273720d commit 814a932

23 files changed

+125
-31
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ PHP NEWS
1515
- Reflection:
1616
. Fixed bug #80097 (ReflectionAttribute is not a Reflector). (beberlei)
1717

18+
- Standard:
19+
. Fixed bug #81111 (Serialization is unexpectedly allowed on anonymous classes
20+
with __serialize()). (Nikita)
21+
1822
08 Jul 2021, PHP 8.1.0alpha3
1923

2024
- Core:

UPGRADING.INTERNALS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ PHP 8.1 INTERNALS UPGRADE NOTES
4747
implementations. Use ZEND_LONG_FMT and ZEND_ULONG_FMT instead.
4848
e. ZEND_ATOL() now returns the integer instead of assigning it as part of the
4949
macro. Replace ZEND_ATOL(i, s) with i = ZEND_ATOL(s).
50+
f. Non-serializable classes should be indicated using the
51+
ZEND_ACC_NOT_SERIALIZABLE (@not-serializable in stubs) rather than the
52+
zend_class_(un)serialize_deny handlers. Support for the serialization
53+
handlers will be dropped in the future.
5054

5155
========================
5256
2. Build system changes

Zend/tests/generators/errors/serialize_unserialize_error.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ Stack trace:
3232
#0 %s(%d): serialize(Object(Generator))
3333
#1 {main}
3434

35+
Exception: Unserialization of 'Generator' is not allowed in %s:%d
36+
Stack trace:
37+
#0 %s(%d): unserialize('O:9:"Generator"...')
38+
#1 {main}
3539

36-
Warning: Erroneous data format for unserializing 'Generator' in %sserialize_unserialize_error.php on line %d
37-
38-
Notice: unserialize(): Error at offset 19 of 20 bytes in %sserialize_unserialize_error.php on line %d
39-
bool(false)
4040
Exception: Unserialization of 'Generator' is not allowed in %s:%d
4141
Stack trace:
4242
#0 %s(%d): unserialize('C:9:"Generator"...')

Zend/zend_closures.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -640,8 +640,6 @@ void zend_register_closure_ce(void) /* {{{ */
640640
{
641641
zend_ce_closure = register_class_Closure();
642642
zend_ce_closure->create_object = zend_closure_new;
643-
zend_ce_closure->serialize = zend_class_serialize_deny;
644-
zend_ce_closure->unserialize = zend_class_unserialize_deny;
645643

646644
memcpy(&closure_handlers, &std_object_handlers, sizeof(zend_object_handlers));
647645
closure_handlers.free_obj = zend_closure_free_storage;

Zend/zend_closures.stub.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
/** @generate-class-entries */
44

5-
/** @strict-properties */
5+
/**
6+
* @strict-properties
7+
* @not-serializable
8+
*/
69
final class Closure
710
{
811
private function __construct() {}

Zend/zend_closures_arginfo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 7c4df531cdb30ac4206f43f0d40098666466b9a6 */
2+
* Stub hash: e3b480674671a698814db282c5ea34d438fe519d */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure___construct, 0, 0, 0)
55
ZEND_END_ARG_INFO()
@@ -47,7 +47,7 @@ static zend_class_entry *register_class_Closure(void)
4747

4848
INIT_CLASS_ENTRY(ce, "Closure", class_Closure_methods);
4949
class_entry = zend_register_internal_class_ex(&ce, NULL);
50-
class_entry->ce_flags |= ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES;
50+
class_entry->ce_flags |= ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE;
5151

5252
return class_entry;
5353
}

Zend/zend_compile.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7671,8 +7671,7 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{
76717671

76727672
if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) {
76737673
/* Serialization is not supported for anonymous classes */
7674-
ce->serialize = zend_class_serialize_deny;
7675-
ce->unserialize = zend_class_unserialize_deny;
7674+
ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
76767675
}
76777676

76787677
if (extends_ast) {

Zend/zend_compile.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ typedef struct _zend_oparray_context {
238238
/* or IS_CONSTANT_VISITED_MARK | | | */
239239
#define ZEND_CLASS_CONST_IS_CASE (1 << 6) /* | | | X */
240240
/* | | | */
241-
/* Class Flags (unused: 29...) | | | */
241+
/* Class Flags (unused: 30...) | | | */
242242
/* =========== | | | */
243243
/* | | | */
244244
/* Special class types | | | */
@@ -301,6 +301,9 @@ typedef struct _zend_oparray_context {
301301
/* loaded from file cache to process memory | | | */
302302
#define ZEND_ACC_FILE_CACHED (1 << 27) /* X | | | */
303303
/* | | | */
304+
/* Class cannot be serialized or unserialized | | | */
305+
#define ZEND_ACC_NOT_SERIALIZABLE (1 << 29) /* X | | | */
306+
/* | | | */
304307
/* Function Flags (unused: 27-30) | | | */
305308
/* ============== | | | */
306309
/* | | | */

Zend/zend_fibers.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -868,8 +868,6 @@ void zend_register_fiber_ce(void)
868868
{
869869
zend_ce_fiber = register_class_Fiber();
870870
zend_ce_fiber->create_object = zend_fiber_object_create;
871-
zend_ce_fiber->serialize = zend_class_serialize_deny;
872-
zend_ce_fiber->unserialize = zend_class_unserialize_deny;
873871

874872
zend_fiber_handlers = std_object_handlers;
875873
zend_fiber_handlers.dtor_obj = zend_fiber_object_destroy;

Zend/zend_fibers.stub.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
/** @generate-class-entries */
44

5-
/** @strict-properties */
5+
/**
6+
* @strict-properties
7+
* @not-serializable
8+
*/
69
final class Fiber
710
{
811
public function __construct(callable $callback) {}

0 commit comments

Comments
 (0)