views:

671

answers:

5

What's the best way to determine whether or not a string is the result / output of the serialize() function?

+9  A: 

I'd say, try to unserialize it ;-)

Quoting the manual :

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

So, you have to check if the return value is false or not (with === or !==, to be sure not to have any problem with 0 or null or anything that equals to false, I'd say).

Just beware the notice : you might want/need to use the @ operator.

For instance :

$str = 'hjkl';
$data = @unserialize($str);
if ($data !== false) {
    echo "ok";
} else {
    echo "not ok";
}

Will get you :

not ok


EDIT : Oh, and like @Peter said (thanks to him!), you might run into trouble if you are trying to unserialize the representation of a boolean false :-(

So, checking that your serialized string is not equal to "b:0;" might be helpful too ; something like this should do the trick, I suppose :

$data = @unserialize($str);
if ($str === 'b:0;' || $data !== false) {
    echo "ok";
} else {
    echo "not ok";
}

testing that special case before trying to unserialize would be an optimization -- but probably not that usefull, if you don't often have a false serialized value.

Pascal MARTIN
But what if the unserialized value is a boolean with a value of FALSE?
Peter
@Peter - it's a String
Isaac Waller
@Peter : excellent remark ; I've edited my answer with a proposition to deal with that case ; thanks !
Pascal MARTIN
Thanks. :) I assumed this was probably going to be the answer.. Just seems to me that there should be a way to find out if it's serialized before actually forcing the parser to attempt to process it.
Lorren Biffin
I added an another answer below that addresses the "false as a valid value" problem below. Let me know what you think.
Peter Bailey
A: 

My guess is that you are coding incorrectly causing this dilemma. Since there is no build-in PHP way to handle this (that is efficient @karim79) I really recommend you look at solving this problem before your code gets to this point. Would you mind explaining a little more about why you are ending up with random strings or serialized objects?

Xeoncross
+2  A: 
$data = @unserialize($str);
if($data !== false || $str === 'b:0;')
    echo 'ok';
else
    echo "not ok";

Correctly handles the case of serialize(false). :)

chaos
+2  A: 

Despite Pascal MARTIN's excellent answer, I was curious if you could approach this another way, so I did this just as a mental exercise

<?php

ini_set( 'display_errors', 1 );
ini_set( 'track_errors', 1 );
error_reporting( E_ALL );

$valueToUnserialize = serialize( false );
//$valueToUnserialize = "a"; # uncomment this for another test

$unserialized = @unserialize( $valueToUnserialize );

if ( FALSE === $unserialized && isset( $php_errormsg ) && strpos( $php_errormsg, 'unserialize' ) !== FALSE )
{
  echo 'Value could not be unserialized<br>';
  echo $valueToUnserialize;
} else {
  echo 'Value was unserialized!<br>';
  var_dump( $unserialized );
}

And it actually works. The only caveat is that it will likely break if you have a registered error handler because of how $php_errormsg works.

Peter Bailey
+1 : This one is fun, I have to admit -- wouldn't have thought about it ! And I don't find a way to make it fail, too ^^ Nice work ! And thanks for the comment on my answer : without it, I would probably not have seen this answer.
Pascal MARTIN
+1  A: 

@Xeoncross

For example: when you put serialized data into a cookie. Then the value of this cookie becomes untrusted and is has to be checked before you do anything with it.

Matthias