MDL-70823 core: safer alternative for unserializing objects.

This commit is contained in:
Paul Holden 2021-10-21 17:29:05 +01:00 committed by Sara Arjona
parent bc3890b60d
commit e22fded5fe
2 changed files with 38 additions and 0 deletions

View File

@ -10404,6 +10404,21 @@ function unserialize_array($expression) {
return $value;
}
/**
* Safe method for unserializing given input that is expected to contain only a serialized instance of an stdClass object
*
* If any class type other than stdClass is included in the input string, it will not be instantiated and will be cast to an
* stdClass object. The initial cast to array, then back to object is to ensure we are always returning the correct type,
* otherwise we would return an instances of {@see __PHP_Incomplete_class} for malformed strings
*
* @param string $input
* @return stdClass
*/
function unserialize_object(string $input): stdClass {
$instance = (array) unserialize($input, ['allowed_classes' => [stdClass::class]]);
return (object) $instance;
}
/**
* The lang_string class
*

View File

@ -4543,6 +4543,29 @@ EOF;
$this->assertEquals($a, unserialize_array(serialize($a)));
}
/**
* Test method for safely unserializing a serialized object of type stdClass
*/
public function test_unserialize_object(): void {
$object = (object) [
'foo' => 42,
'bar' => 'Hamster',
'innerobject' => (object) [
'baz' => 'happy',
],
];
// We should get back the same object we serialized.
$serializedobject = serialize($object);
$this->assertEquals($object, unserialize_object($serializedobject));
// Try serializing a different class, not allowed.
$langstr = new lang_string('no');
$serializedlangstr = serialize($langstr);
$unserializedlangstr = unserialize_object($serializedlangstr);
$this->assertInstanceOf(stdClass::class, $unserializedlangstr);
}
/**
* Test that the component_class_callback returns the correct default value when the class was not found.
*