Repository navigation
Reject classes that keep their state internally in deepclone_from_array() - #53
Conversation
have you reported this to php-src so that a fix is implemented ? |
|
That's for the extensions to fix, likely with a |
|
ah, I missed that those are about non-core extensions. So adapted question: have you reported it to the extension maintainers ? |
…ay() deepclone_to_array() and deepclone_hydrate() reject the internal classes that keep their state out of their properties and declare no serialization API, like Redis, Imagick or the AMQP and Relay classes, but deepclone_from_array() created them when a payload named them, eg one produced by the polyfill. unserialize() creates them that way too, without their state, and some crash PHP then: RedisCluster::acl() or ImagickDraw::affine() segfault on such objects, and a Relay\Table does when destroyed. The class lookup of deepclone_from_array() now applies the same rule, which the three functions share in one helper, and throws NotInstantiableException. User classes that extend such a class without declaring a serialization API are rejected too, eg a subclass of RedisCluster, which crashed the same way, in all three functions. That's one more flag test per class and call for user classes. IteratorIterator and the other internal iterators wrapping another one are rejected too, instead of being created like unserialize() does, and so are their user subclasses.
a9cce4c to
f7b2c3c
Compare
|
Done: phpredis/phpredis#2938, Imagick/imagick#800, php-amqp/php-amqp#640, krakjoe/apcu#633, msgpack/msgpack-php#190, php-memcached-dev/php-memcached#583, and cachewerk/relay#226 since Relay is closed source. |
…te out of their properties (nicolas-grekas) This PR was merged into the 1.x branch. Discussion ---------- [DeepClone] Reject more internal classes that keep their state out of their properties | Q | A | ------------- | --- | Branch? | 1.x | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | - | License | MIT Builds on #703. The extension rejects the internal classes that keep their state out of their properties and declare no serialization API, in `deepclone_to_array()`, `deepclone_hydrate()` and, with symfony/php-ext-deepclone#53, `deepclone_from_array()`. The polyfill can't see which classes do so and knew only the ones of zip, xmlreader, xmlwriter, snmp and tidy: it exported a `Redis` or an `Imagick` without its state, and `deepclone_from_array()` created them, which can crash PHP, eg when a bare `Relay\Table` is destroyed or a clone of a bare `AMQPConnection` is dumped. It now also knows the classes of the redis, relay, imagick, amqp, apcu and msgpack extensions, and rejects them before creating a prototype, together with their user subclasses that declare no serialization API. Classes of other extensions stay accepted. Like the extension, `deepclone_from_array()` now also rejects the internal classes whose state `serialize()` loses, like `IteratorIterator`, as `deepclone_hydrate()` already did, and both reject their user subclasses too, unless they declare a serialization API. Commits ------- 14a31d4 [DeepClone] Reject more internal classes that keep their state out of their properties
Builds on #50 and #52.
deepclone_to_array()anddeepclone_hydrate()reject the internal classes that keep their state out of their properties and declare no serialization API, likeRedis,Imagickor the AMQP and Relay classes, butdeepclone_from_array()created them when a payload named them, eg one produced by the polyfill.unserialize()creates them that way too, and some crash PHP then:RedisCluster::acl()orImagickDraw::affine()segfault on such objects, and aRelay\Tabledoes when destroyed.The class lookup of
deepclone_from_array()now applies the same rule, which the three functions share in one helper, and throwsNotInstantiableException. User classes that extend such a class without declaring a serialization API are rejected too, in all three functions: a subclass ofRedisClustercrashed the same way. For user classes, that's one more flag test per class and call.IteratorIteratorand the other internal iterators wrapping another one are rejected too, where #50 created them likeunserialize()does, and so are their user subclasses. Payloads that carry serialized strings still create whateverunserialize()creates from them, unless$allowed_classesexcludes it.The polyfill gets the same change in symfony/polyfill#708, for the classes of the extensions it knows, as it can't tell which classes keep their state internally.