Skip to content

object_properties_load allows __unserialize to set wrong property type in GMP, SplFixedArray, etc. #9708

Open
@TysonAndre

Description

@TysonAndre

Description

The following code:

<?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
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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions