Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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