4

When using unserialize in php, what is the safest way to handle potential situations where the variable cannot be unserialized.

for example (not that i would ever this, just for examples sake):

$myVar = true;

$result = unserialize($myVar);

This will return false, which is fine. But it also throws a nasty notice.

I have been doing the following:

$result = @unserialize($myVar);

which feels hacky. So what is the best way to unserialize when there is a possibility of false

Marty Wallace
  • 34,046
  • 53
  • 137
  • 200
  • 2
    I guess the ideal solution would be to only unserialize a variable that you are certain contains a serialized string. You shouldn't be accepting serialized PHP data from an untrusted external source, for security reasons, so you should be able to be pretty confident that a variable that you think is a serialized string is indeed so. If you're not confident of that, you have a bigger problem. – Spudley Dec 20 '12 at 21:47
  • I kind of think a "nasty notice" is a good reply to a failed unserialize (you can and should not display those notices for a live site anyways). What exactly did you mean by "safest" and "best"? I kind of think `@unserialize` is fine if you aren't concerned with being notified of the error. – Wesley Murch Dec 20 '12 at 21:51
  • @Spudley I totally get what you are saying. I suppose thats actually the real challenge here. Due to the nature of my problem, I simply cannot see a way to ensure that the model i am loading will always have this particular property set and serialized. – Marty Wallace Dec 20 '12 at 21:51
  • @WesleyMurch - I would have thought false was enough. Since the notice is being thrown, php is obviously saying "there is something wrong here" as opposed to just true or false response. Therefore how should this be handled safely in well constructed code – Marty Wallace Dec 20 '12 at 21:52
  • 1
    php is saying something is wrong because of `Unserialization can result in code being loaded and executed due to object instantiation and autoloading, and a malicious user may be able to exploit this.`, see the last section in the manual: http://php.net/manual/en/function.unserialize.php – jeroen Dec 20 '12 at 21:55
  • what other values can it possibly have? If it's going to be `true` or `false` or a serialized string, you could check the type with `if(is_string(...))` or something like that. But you won't get much beyond that without actually doing some parsing of the string, which is somewhat self-defeating. – Spudley Dec 20 '12 at 21:56
  • @spudley - its going to be an array so @unserialize($value); if (is_array($result... ?? – Marty Wallace Dec 20 '12 at 21:57
  • the other thing I'd suggest is possibly to use a different transport mechanism. Unless you actually need to maintain object types and state within your PHP code, you could use JSON or something like that instead, which would give you easier error handling. – Spudley Dec 20 '12 at 21:57
  • no, I meant check the type before `unserialize()`, so you know that it's a string beforehand. it won't be fail-safe, but if you can say that "if I get a string then it's a serialized value" then checking the type should be sufficient. – Spudley Dec 20 '12 at 21:59
  • I don't think you have other options: http://stackoverflow.com/a/1369946/1229260 – Tchoupi Dec 20 '12 at 21:59
  • @spudley - i simply need to store an array. It will never be used in javascript. Do you think json would be a good fit here? – Marty Wallace Dec 20 '12 at 21:59
  • 1
    yes. JSON is great for transporting array data, regardless of whether you're using Javascript or not. It's pretty much become a cross-language standard for this kind of thing now. – Spudley Dec 20 '12 at 22:00

1 Answers1

2

You can use an error handler with try / catch:

set_error_handler('exceptions_error_handler');
function exceptions_error_handler($severity, $message, $filename, $lineno) {
  if (error_reporting() == 0) {
    return;
  }
  if (error_reporting() & $severity) {
    throw new ErrorException($message, 0, $severity, $filename, $lineno);
  }
}
$string = 'bob';
try {
   $result = unserialize($string);
} catch (Exception $e) {
   echo 'Caught exception: ',  $e->getMessage(), "\n";
}
if(isset($result)) {
    //Continue code for valid serialized array here
}
Pitchinnate
  • 7,517
  • 1
  • 20
  • 37
  • However just like comments above, I would recommend JSON over serialized arrays. I was answering the question posted. – Pitchinnate Dec 20 '12 at 22:14