[php-src] Issue #9708: `object_properties_load` allows `__unserialize` to set wrong property type in GMP, SplFixedArray, etc.
| From: | TysonAndre | Date: | Mon, 10 Oct 2022 16:30:30 +0000 |
| Subject: | [php-src] Issue #9708: `object_properties_load` allows `__unserialize` to set wrong property type in GMP, SplFixedArray, etc. | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-242568@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/9708
Author: TysonAndre
### Description
The following code:
```php
<?php
class ObjectPropertiesLoadBug extends GMP {
public int $a;
public int $b;
}
$ser =
'O:23:"ObjectPropertiesLoadBug":2:{i:0;s:1:"0";i:1;a:2:{s:1:"a";s:8:"NOTANINT";s:1:"b";R:4;}}';
var_dump(unserialize($ser));
echo "Done\n";
```
Resulted in this output:
```
object(ObjectPropertiesLoadBug)#1 (3) {
["a"]=>
&string(8) "NOTANINT"
["b"]=>
&string(8) "NOTANINT"
["num"]=>
string(1) "0"
}
php: .../php-src/Zend/zend_execute.c:3653: zend_ref_del_type_source: Assertion `source_list->ptr
== prop' failed.
[1] 634981 abort (core dumped) php object_properties_load.php
```
But I expected this output instead:
```
Uncaught TypeError: Cannot assign string to property ObjectPropertiesLoadBug::$a of type int
```
This bug probably affects anything using object_properties_load in
__unserialize in php
7.4 and newer (including PECLs), where typed properties were first introduced.
Related to #9707
The same issue can be reproduced even without references
```php
<?php
class ObjectPropertiesLoadBug extends GMP {
public int $a;
}
$ser =
'O:23:"ObjectPropertiesLoadBug":2:{i:0;s:1:"0";i:1;a:1:{s:1:"a";s:8:"NOTANINT";}}';
var_export(unserialize($ser)); // expected TypeError
/*
\ObjectPropertiesLoadBug::__set_state(array(
'a' => 'NOTANINT',
))
*/
```
object_properties_load should probably do something similar to the ZEND_ASSIGN_REF, opcode handler
and call something similar to zend_assign_to_variable_reference if prop_info has types
1. If the new value is already a reference: delete the original reference in the backing C property
table if needed, add that object's property info to the variable's reference group, and
then set the typed property to that new reference
2. If the new value was a non-reference: Delete the original reference in the backing C property
table if needed, then store the value the way a regular ZEND_ASSIGN_OBJ opcode handler (for property
assignment, e.g. $obj->propName = $value;) would behave
### PHP Version
8.1 - 8.3-dev
### Operating System
_No response_