Skip to content

Instantly share code, notes, and snippets.

@codebymikey
Forked from joachim-n/validate PHP serialization
Last active October 11, 2024 16:15
Show Gist options
  • Save codebymikey/f94b2620b99cf26d3833afc9a9641e17 to your computer and use it in GitHub Desktop.
Save codebymikey/f94b2620b99cf26d3833afc9a9641e17 to your computer and use it in GitHub Desktop.
<?php
/**
* Checks where a serialize call would've failed.
*/
public static function check($checking_key, $data, $path = [], $processed = []) {
try {
// Attempt to serialize the data to check for serializability.
serialize($data);
} catch (\Throwable $e) {
// Serialization failed, track the issue.
$path[] = "CATCH $checking_key";
// Handle arrays recursively.
if (is_array($data)) {
foreach ($data as $key => $val) {
$path[$key] = static::check($key, $val, [], $processed);
}
} elseif (is_object($data)) {
// Generate a unique hash for the object.
$object_hash = spl_object_hash($data);
// Check if we've already processed this object to prevent recursion.
if (in_array($object_hash, $processed, true)) {
$path[] = "RECURSION $checking_key";
return $path; // Bail out on recursion.
}
// Add the object hash to the processed list.
$processed[] = $object_hash;
$ref = new \ReflectionObject($data);
$properties = [];
// Get properties, including private ones from parent classes.
do {
$properties = array_merge($properties, $ref->getProperties());
$ref = $ref->getParentClass();
} while ($ref);
foreach ($properties as $property) {
$property->setAccessible(true);
$key = $property->getName();
if (!$property->isInitialized($data)) {
continue;
}
try {
$val = $property->getValue($data);
}
catch (\Exception $access_error) {
// Ignore it.
continue;
}
$path[$key] = static::check($key, $val, [], $processed);
}
} else {
// Final case for non-object and non-array data.
$path[] = "FINAL $checking_key";
}
}
return array_filter($path);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment