Check to See If a String Is Serialized

Check to see if a string is serialized?

From WordPress core functions:

<?php
function is_serialized( $data, $strict = true ) {
// If it isn't a string, it isn't serialized.
if ( ! is_string( $data ) ) {
return false;
}
$data = trim( $data );
if ( 'N;' === $data ) {
return true;
}
if ( strlen( $data ) < 4 ) {
return false;
}
if ( ':' !== $data[1] ) {
return false;
}
if ( $strict ) {
$lastc = substr( $data, -1 );
if ( ';' !== $lastc && '}' !== $lastc ) {
return false;
}
} else {
$semicolon = strpos( $data, ';' );
$brace = strpos( $data, '}' );
// Either ; or } must exist.
if ( false === $semicolon && false === $brace ) {
return false;
}
// But neither must be in the first X characters.
if ( false !== $semicolon && $semicolon < 3 ) {
return false;
}
if ( false !== $brace && $brace < 4 ) {
return false;
}
}
$token = $data[0];
switch ( $token ) {
case 's':
if ( $strict ) {
if ( '"' !== substr( $data, -2, 1 ) ) {
return false;
}
} elseif ( false === strpos( $data, '"' ) ) {
return false;
}
// Or else fall through.
case 'a':
case 'O':
return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
case 'b':
case 'i':
case 'd':
$end = $strict ? '$' : '';
return (bool) preg_match( "/^{$token}:[0-9.E+-]+;$end/", $data );
}
return false;
}

Check if string is serialized in PHP

$array = @unserialize($string);
if ($array === false && $string !== 'b:0;') {
// woops, that didn't appear to be anything serialized
}

The $string !== 'b:0;' checks to see if the serialized string may have been the value false. If this check is important to you you may want to trim the serialized string or otherwise preprocess it to make sure this works.

How to find out if a string is a serialized object/array or just a string?

Well, you can tell by looking at the format. When you serialize an array, you get a string that looks like a:1:{i:0;s:3:"foo"} And if you serialize an object, you get: o:7:"myclass":1:{s:3:"foo";s:3:"bar";}.

So if you want to test rudimentary, you can do these two regexes:

^a:\d+:{.*?}$

And

^o:\d+:"[a-z0-9_]+":\d+:{.*?}$

for arrays and objects respectively.

Note that this just checks for the generic form. To tell if it's a valid serialized string, you need to run it through unserialize() and test the return is_array($result) and is_object($result)...

checking value if it serialized or not

there's a couple of functions out there:

is_serialized
http://www.cs278.org/blog/2009/10/23/php-function-is_serialized/

couple more suggestions here:
Check to see if a string is serialized?

Checking for Serialized Objects

It's a pretty common misconception that you have to manually serialize objects before putting them in session. That is not the case. You can simply assign an object instance to a slot in $_SESSION, and PHP will automagically serialize and unserialize it for you, between requests.

How can I test for a serialized variable? Without throwing E_NOTICE if string is not serialized

When you try to unserialize it, it returns false if it is not serialized. It also returns a an E_NOTICE which is where that output is coming from.

From the manual:

In case the passed string is not unserializeable, FALSE is returned
and E_NOTICE is issued.

Check if the return value of unserialize ===false

How to check if a String contains Deserializable data in C#?

Ensuring that a string represents a valid serialized object is nearly as hard as performing deserialization itself, because you would need to walk the serialized object graph, figuring out where each serialized field starts, and what would be the data that goes into that field.

The only operations that you could save are the allocations of the object and its dependents. These operations are certainly not free, but they are highly optimized, so your savings are not going to be overly significant.

Instead of pre-validating the string before deserialization, you could take a speculative approach, and assume that your deserialization will succeed. Your code could jump right into deserializing your string, and in most cases it will succeed!* To ensure that your code does not break when the string is invalid, wrap deserialization calls into a try/catch, and watch for deserialization exceptions. If you catch any of them, you know that the string was invalid; if you do not catch deserialization exceptions, you would know that the string is valid, and you would also have your deserialized object ready for use.

Assuming XML serialization, your code could do something like this:

static bool TryDeserialize<T>(string xmlStr, out T obj) {
var ser = new XmlSerializer(typeof(T));
using(var stringReader = new StringReader(xmlStr)) {
using (var xmlReader = new XmlTextReader(stringReader)) {
try {
obj = ser.Deserialize(xmlReader);
} catch {
obj = default(T);
return false;
}
}
}
return true;
}



* If your deserialization fails the overwhelming majority of the time, you may need to re-think this strategy.

Check whether binary serialized data matches the class which serialized it

But I really would like to know if there is a way to detect if the class does not match the serialized data?

One way to detect it would be to serialize the existing class with the same data as in the previous serialized file and then compare the digital fingerprints of the previous and current serialized files.

I do not want to do the serialization myself via implementing ISerializable because the class and its properties is quite large and might be changed.

Since you are using the BinaryFormatter and dealing with potentially significant versioning issues, i think your only option is to implement ISerializable and handle deserialization yourself whether you like it or not.

Check if value can be serialized to JSON in Node.js

Based on the comment you could check if evaluated itself can be stringified, or if ti would return undefined. If it can be stringified you can complete finalized the json response using '{"data":'+stringified+'}'. Doing this concatenation is save, because stringified would be a valid JSON value.

function evaluate(expression, context, callback) {
try {
var evaluated = safeEval(expression, context);
var stringified = JSON.stringify(evaluated);

if (typeof stringified === 'undefined') {
throw new Error('could not be stringified');
}

callback('{"data":' + stringified + '}');
} catch (err) {
callback(JSON.stringify({
error: err.name + ': ' + err.message
}));
}
}

If the response is more complex, with more then the data field then this solution might be better:

function evaluate(expression, context, callback) {
try {
var evaluated = safeEval(expression, context);
var stringified = JSON.stringify({
data: evaluated
});

if (typeof JSON.parse(stringified).data === 'undefined') {
throw new Error('could not be stringified');
}

callback(stringified);
} catch (err) {
callback(JSON.stringify({
error: err.name + ': ' + err.message
}));
}
}


Related Topics



Leave a reply



Submit