Skip to content

Add ZEND_ACC_NOT_SERIALIZABLE flag #7249

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

Conversation

nikic
Copy link
Member

@nikic nikic commented Jul 16, 2021

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.

Copy link
Contributor

@TysonAndre TysonAndre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM other than the question about not removing zend_class_serialize_deny /zend_class_unserialize_deny

@@ -7662,8 +7662,7 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{

if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) {
/* Serialization is not supported for anonymous classes */
ce->serialize = zend_class_serialize_deny;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be safer to add ZEND_ACC_NOT_SERIALIZABLE but keep zend_class_serialize_deny until the next minor release, especially with the feature freeze in a few days.

Older releases of msgpack and igbinary (and possibly others) would depend on zend_class_serialize_deny and zend_class_unserialize_deny to work correctly, and some of them would have releases that would compile in 8.1.0+ stable or be used to beta test 8.1

(e.g. to avoid unserializing an invalid Closure)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@krakjoe Thoughts on this? I'd rather not duplicate the info, and we're still half a year away from the release.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like duplication either, and I don't like leaving broken API exposed for longer than we must.

@TysonAndre
Copy link
Contributor

It'd be useful to add a test that the bug is fixed.

Fixing all class entries can be left for a subsequent PR, but in order for php, igbinary, msgpack, etc. to be able to test this and avoid regressions, it'd be useful to change at least one non-final class entry.

--- a/ext/curl/curl_file.c
+++ b/ext/curl/curl_file.c
@@ -149,6 +149,7 @@ void curlfile_register_class(void)
        curl_CURLFile_class = register_class_CURLFile();
        curl_CURLFile_class->serialize = zend_class_serialize_deny;
        curl_CURLFile_class->unserialize = zend_class_unserialize_deny;
+       curl_CURLFile_class->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
 
        curl_CURLStringFile_class = register_class_CURLStringFile();
 }
--TEST--
Test refusing to serialize/unserialize unserializable classes
--INI--
error_reporting=E_ALL
--FILE--
<?php
// https://bugs.php.net/bug.php?id=81111
function check_serialize_throws($obj) {
    try {
        var_dump(serialize($obj));
    } catch (Throwable $e) {
        echo "Caught: " . $e->getMessage() . "\n";
    }
}
class Something extends CURLFile {
    public function __serialize() { return []; }
    public function __unserialize($value) { return new self('file'); }
}

check_serialize_throws(new Something('file'));
check_serialize_throws(new class () {
    public function __serialize() { return []; }
    public function __unserialize($value) { }
});

?>
--EXPECTF--
Caught: Serialization of 'Something' is not allowed
Caught: Serialization of 'class@anonymous' is not allowed

@krakjoe
Copy link
Member

krakjoe commented Jul 19, 2021

@nikic can you merge this today, so we have time for follow ups please.

@dstogov
Copy link
Member

dstogov commented Jul 19, 2021

LGTM

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants