Wie kann man eine Deserialisierungsausnahme abfangen?

Lesezeit: 4 Minuten

Eugenes Benutzeravatar
Eugen

Ist es möglich, eine Ausnahme in PHP abzufangen, wenn unserialize() erzeugt einen Fehler?

Ein einfacher Weg ist:

$ret = @unserialize($foo);
if($ret === null){
   //Error case
}

Aber es ist nicht die modernste Lösung.

Der beste Weg ist, wie bereits erwähnt, ein benutzerdefinierter Fehler-/Ausnahmehandler (nicht nur für diesen Fall). Aber je nachdem, was Sie tun, kann es übertrieben sein.

  • pro Dokumentation: Falls der übergebene String nicht deserialisierbar ist, wird FALSE zurückgegeben. Zum Glück würden nur wenige ausreichen serialize(false)

    – ggesichtslos

    29. Januar 2014 um 11:26 Uhr

  • “Falls der übergebene String nicht deserialisierbar ist, wird FALSE zurückgegeben und E_NOTICE wird ausgegeben.” Ein E_ wird ebenfalls geworfen.

    – Zedee

    29. Mai 2015 um 12:02 Uhr


  • Das @ Symbol wird für diese Lösung benötigt, da PHP sonst auf dem Bildschirm einen Hinweis ausgibt, wenn die Deserialisierung fehlschlägt.

    – Flori

    19. März 2018 um 9:30 Uhr

  • Das ist keine gute Antwort. Der ursprünglich serialisierte Wert war möglicherweise null. serialize(NULL) ist "N;" was deserialisiert zu NULL. Niemand serialisiert null unter den meisten Bedingungen, aber dies könnte in einigen komplexen, automatisierten Systemen oder Berechnungen passieren – zB die Ausgabe einer anhaltenden Problemberechnung (wobei NULL nicht dasselbe wie FALSE ist).

    – S. Kobold

    13. September 2018 um 23:13 Uhr

  • Sie müssen die Prüfung auf mindestens ändern if($foo!="N;" && $ret === null){ //Error case } Sie wissen also, dass die Quellvariable nicht null war, also wurde null als Fehler zurückgegeben.

    – Mike

    22. Juni 2020 um 0:18 Uhr


Benutzeravatar von Mihai Iorga
Mihai Iorga

Nein, du kannst es nicht fangen, unserialize() löst keine Exception aus.

Falls der übergebene String nicht deserialisierbar ist, wird FALSE zurückgegeben und E_NOTICE ausgegeben.

Sie können einen benutzerdefinierten Ausnahmehandler festlegen, um alle Fehler zu behandeln:

function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");

Konvertieren Sie alle PHP-Fehler (Warnhinweise usw.) in Ausnahmen. Beispiel ist hier.

Eine vollständige Lösung würde wie folgt aussehen:

<?php
// As mentioned in the top answer, we need to set up 
// some general error handling
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");


// Note, there are two types of way it could fail, 
// the fail2 fail is when try to unserialise just 
// false, it should fail. Also note, what you 
// do when something fails is up to your app. 
// So replace var_dump("fail...") with your 
// own app logic for error handling
function unserializeSensible($value) {
    $caught = false;
    try {
        $unserialised = unserialize($value);
    } catch(ErrorException $e) {
        var_dump("fail");
        $caught = true;
    }
    // PHP doesn't have a try .. else block like Python
    if(!$caught) {
        if($unserialised === false && $value !== serialize(false)) {
            var_dump("fail2");
        } else {
            var_dump("pass");
            return $unserialised;
        }
    }
}

unserializeSensible('b:0;'); // Should pass
unserializeSensible('b:1;'); // Should pass
unserializeSensible('a:2:{s:1:"a";b:0;s:1:"b";s:3:"foo";}'); // Should pass
unserializeSensible('a:2:{s:1:"a";b:0;s:1:"b";s:3:1111111111111111;}'); // Should fail
unserializeSensible(123); // Should fail
unserializeSensible("Gday"); // Should fail
unserializeSensible(false); // Should fail2
unserializeSensible(true); // Should fail

Wie Mihai Iorga erklärte, unserialize wirft nichts. Sie können nach Fehlern suchen, indem Sie den Rückgabewert mit vergleichen falseaber es schlägt fehl, wenn der serialisierte Wert a ist false boolescher Wert. Die folgende Lösung löst dieses Problem, ohne auf langsame und umständliche Techniken zurückzugreifen (z. B. das Festlegen benutzerdefinierter Fehlerhandler).

Der folgende Code wirft a InvalidArgumentException wenn der serialisierte Wert $v ist ungültig, andernfalls $x enthält den deserialisierten Wert.

Auf die Unterscheidung wird besonders geachtet:

  • unserialize() Rückkehr false um einen ungültigen serialisierten Wert zu signalisieren
  • der ursprüngliche Wert ist tatsächlich ein boolescher Wert false.
$x = @unserialize ($v);
if ($x === false && $v != 'b:0;')
  throw new InvalidArgumentException;

  • Jeder kennt die @ Charakter, aber manchmal vergessen wir die kleinen Kenntnisse. @ Charakter verhindert die Benachrichtigung,- b:0; ist der serialisierte Wert von false. Ihre Antwort ist wie ein Blitz in meinem Gehirn eingeschlagen 🙂

    – kodmanyagha

    12. Mai um 19:27 Uhr

Benutzeravatar von Maxim Rysevets
Maxim Rysevets

Sie können diese einfache Funktion aus meinem CMS EFFCORE verwenden:

  function data_is_serialized($data) {
    if ($data === 'b:0;') return true;
    if (is_string($data) && @unserialize($data, ['allowed_classes' => ['stdClass']]) !== false) return true;
    return false;
  }

Prüfen:

var_dump( data_is_serialized(0)     === false );
var_dump( data_is_serialized(1)     === false );
var_dump( data_is_serialized('')    === false );
var_dump( data_is_serialized('0')   === false );
var_dump( data_is_serialized('1')   === false );
var_dump( data_is_serialized(true)  === false );
var_dump( data_is_serialized(false) === false );
var_dump( data_is_serialized([])    === false );

var_dump( data_is_serialized(serialize(0))     === true );
var_dump( data_is_serialized(serialize(1))     === true );
var_dump( data_is_serialized(serialize(''))    === true );
var_dump( data_is_serialized(serialize('0'))   === true );
var_dump( data_is_serialized(serialize('1'))   === true );
var_dump( data_is_serialized(serialize(true))  === true );
var_dump( data_is_serialized(serialize(false)) === true );
var_dump( data_is_serialized(serialize([]))    === true );

  • Jeder kennt die @ Charakter, aber manchmal vergessen wir die kleinen Kenntnisse. @ Charakter verhindert die Benachrichtigung,- b:0; ist der serialisierte Wert von false. Ihre Antwort ist wie ein Blitz in meinem Gehirn eingeschlagen 🙂

    – kodmanyagha

    12. Mai um 19:27 Uhr

Benutzeravatar von RedDragonWebDesign
RedDragonWebDesign

In meinem Fall gab unserialize leer zurück, wenn es fehlschlug, nicht null.

$ret = @unserialize($foo);
if ( ! $ret ) {
   //Error case
}

1430250cookie-checkWie kann man eine Deserialisierungsausnahme abfangen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy