diff --git a/generated/8.1/functionsList.php b/generated/8.1/functionsList.php index b3c4aaaf..0c5a1d2d 100644 --- a/generated/8.1/functionsList.php +++ b/generated/8.1/functionsList.php @@ -1052,6 +1052,7 @@ 'unixtojd', 'unlink', 'unpack', + 'unserialize', 'uopz_extend', 'uopz_implement', 'variant_date_to_timestamp', diff --git a/generated/8.1/rector-migrate.php b/generated/8.1/rector-migrate.php index a3a1ebf2..8f007641 100644 --- a/generated/8.1/rector-migrate.php +++ b/generated/8.1/rector-migrate.php @@ -1060,6 +1060,7 @@ 'unixtojd' => 'Safe\unixtojd', 'unlink' => 'Safe\unlink', 'unpack' => 'Safe\unpack', + 'unserialize' => 'Safe\unserialize', 'uopz_extend' => 'Safe\uopz_extend', 'uopz_implement' => 'Safe\uopz_implement', 'variant_date_to_timestamp' => 'Safe\variant_date_to_timestamp', diff --git a/generated/8.2/functionsList.php b/generated/8.2/functionsList.php index a6f203e2..626dced8 100644 --- a/generated/8.2/functionsList.php +++ b/generated/8.2/functionsList.php @@ -1089,6 +1089,7 @@ 'unixtojd', 'unlink', 'unpack', + 'unserialize', 'uopz_extend', 'uopz_implement', 'variant_date_to_timestamp', diff --git a/generated/8.2/rector-migrate.php b/generated/8.2/rector-migrate.php index 7dfc8482..9fe4243f 100644 --- a/generated/8.2/rector-migrate.php +++ b/generated/8.2/rector-migrate.php @@ -1097,6 +1097,7 @@ 'unixtojd' => 'Safe\unixtojd', 'unlink' => 'Safe\unlink', 'unpack' => 'Safe\unpack', + 'unserialize' => 'Safe\unserialize', 'uopz_extend' => 'Safe\uopz_extend', 'uopz_implement' => 'Safe\uopz_implement', 'variant_date_to_timestamp' => 'Safe\variant_date_to_timestamp', diff --git a/generated/8.3/rector-migrate.php b/generated/8.3/rector-migrate.php index 7dfc8482..9fe4243f 100644 --- a/generated/8.3/rector-migrate.php +++ b/generated/8.3/rector-migrate.php @@ -1097,6 +1097,7 @@ 'unixtojd' => 'Safe\unixtojd', 'unlink' => 'Safe\unlink', 'unpack' => 'Safe\unpack', + 'unserialize' => 'Safe\unserialize', 'uopz_extend' => 'Safe\uopz_extend', 'uopz_implement' => 'Safe\uopz_implement', 'variant_date_to_timestamp' => 'Safe\variant_date_to_timestamp', diff --git a/generated/8.4/functionsList.php b/generated/8.4/functionsList.php index b29dc325..7a193dbf 100644 --- a/generated/8.4/functionsList.php +++ b/generated/8.4/functionsList.php @@ -1066,6 +1066,7 @@ 'unixtojd', 'unlink', 'unpack', + 'unserialize', 'uopz_extend', 'uopz_implement', 'variant_date_to_timestamp', diff --git a/generated/8.4/rector-migrate.php b/generated/8.4/rector-migrate.php index ec0e3bc1..638e033f 100644 --- a/generated/8.4/rector-migrate.php +++ b/generated/8.4/rector-migrate.php @@ -1074,6 +1074,7 @@ 'unixtojd' => 'Safe\unixtojd', 'unlink' => 'Safe\unlink', 'unpack' => 'Safe\unpack', + 'unserialize' => 'Safe\unserialize', 'uopz_extend' => 'Safe\uopz_extend', 'uopz_implement' => 'Safe\uopz_implement', 'variant_date_to_timestamp' => 'Safe\variant_date_to_timestamp', diff --git a/generated/8.5/functionsList.php b/generated/8.5/functionsList.php index 38632ffa..b092d545 100644 --- a/generated/8.5/functionsList.php +++ b/generated/8.5/functionsList.php @@ -1068,6 +1068,7 @@ 'unixtojd', 'unlink', 'unpack', + 'unserialize', 'uopz_extend', 'uopz_implement', 'variant_date_to_timestamp', diff --git a/generated/8.5/rector-migrate.php b/generated/8.5/rector-migrate.php index 120389a9..d582da48 100644 --- a/generated/8.5/rector-migrate.php +++ b/generated/8.5/rector-migrate.php @@ -1076,6 +1076,7 @@ 'unixtojd' => 'Safe\unixtojd', 'unlink' => 'Safe\unlink', 'unpack' => 'Safe\unpack', + 'unserialize' => 'Safe\unserialize', 'uopz_extend' => 'Safe\uopz_extend', 'uopz_implement' => 'Safe\uopz_implement', 'variant_date_to_timestamp' => 'Safe\variant_date_to_timestamp', diff --git a/generated/8.6/functionsList.php b/generated/8.6/functionsList.php index 0f3c363f..9ef815d4 100644 --- a/generated/8.6/functionsList.php +++ b/generated/8.6/functionsList.php @@ -1068,6 +1068,7 @@ 'unixtojd', 'unlink', 'unpack', + 'unserialize', 'uopz_extend', 'uopz_implement', 'variant_date_to_timestamp', diff --git a/generated/8.6/rector-migrate.php b/generated/8.6/rector-migrate.php index 6de64fa9..23eaee4f 100644 --- a/generated/8.6/rector-migrate.php +++ b/generated/8.6/rector-migrate.php @@ -1076,6 +1076,7 @@ 'unixtojd' => 'Safe\unixtojd', 'unlink' => 'Safe\unlink', 'unpack' => 'Safe\unpack', + 'unserialize' => 'Safe\unserialize', 'uopz_extend' => 'Safe\uopz_extend', 'uopz_implement' => 'Safe\uopz_implement', 'variant_date_to_timestamp' => 'Safe\variant_date_to_timestamp', diff --git a/lib/special_cases.php b/lib/special_cases.php index b416438e..29c182ce 100644 --- a/lib/special_cases.php +++ b/lib/special_cases.php @@ -514,3 +514,64 @@ function ftp_raw(\FTP\Connection $ftp, string $command): array } return $safeResult; } + +/** + * Creates a PHP value from a stored representation + * + * @param string $data
+ * The serialized string. + * + * If the variable being unserialized is an object, after successfully + * reconstructing the object PHP will automatically attempt to call the + * __wakeup member function (if it exists). + * + * unserialize_callback_func directive + * + * It's possible to set a callback-function which will be called, + * if an undefined class should be instantiated during unserializing. + * (to prevent getting an incomplete object "__PHP_Incomplete_Class".) + * Use your "php.ini", ini_set or ".htaccess" + * to define 'unserialize_callback_func'. Everytime an undefined class + * should be instantiated, it'll be called. To disable this feature just + * empty this setting. + * + * @param mixed[] $options [optional] + * Any options to be provided to unserialize(), as an associative array. + * + * The 'allowed_classes' option key may be set to a value that is + * either an array of class names which should be accepted, FALSE to + * accept no classes, or TRUE to accept all classes. If this option is defined + * and unserialize() encounters an object of a class that isn't to be accepted, + * then the object will be instantiated as __PHP_Incomplete_Class instead. + * Omitting this option is the same as defining it as TRUE: PHP will attempt + * to instantiate objects of any class. + * + * @return mixed The converted value is returned, and can be a boolean, + * integer, float, string, array or object. + * + * In case the passed value is not unserializeable, an \ErrorException will + * be thrown. + */ +function unserialize(string $data, array $options = []): mixed +{ + error_clear_last(); + + $previous = set_error_handler(function ($severity, $message, $file, $line) use (&$previous) { + $unserialize_error_msg_prefix = 'unserialize():'; + if (str_starts_with($message, $unserialize_error_msg_prefix)) { + throw new \ErrorException($message, 0, $severity, $file, $line); + } + + if (!$previous) { + return false; + } + + return $previous($severity, $message, $file, $line); + }); + + try { + return \unserialize($data, $options); + } finally { + restore_error_handler(); + } +} diff --git a/tests/SpecialCasesTest.php b/tests/SpecialCasesTest.php index 5b8e4a7f..08f5e36c 100644 --- a/tests/SpecialCasesTest.php +++ b/tests/SpecialCasesTest.php @@ -41,6 +41,23 @@ public function testFgetcsvReturnFalseonEndOfFile(): void \fclose($handle); } + public function testUnserialize(): void + { + $data = new stdClass(); + $serialized_data = \serialize($data); + $this->assertEquals($data, \Safe\unserialize($serialized_data)); + + $serialized_data = \serialize(false); + $this->assertFalse(\Safe\unserialize($serialized_data)); + } + + public function testUnserializeOnInvalidData(): void + { + $this->expectException(Exception::class); + $this->expectExceptionMessage('unserialize(): Error at offset 0 of 8 bytes'); + \Safe\unserialize('invalid{'); + } + /*public function testFgetcsvThrowsOnError() { if (($handle = \fopen(__DIR__."/csv/test3.csv", "r")) === false) {