Frage unserialize () [function.unserialize]: Fehler beim Offset


Ich benutze Hotaru CMS mit dem Image-Upload-Plugin, ich erhalte diesen Fehler, wenn ich versuche, ein Bild an einen Post anzuhängen, sonst gibt es keinen Fehler.

Der Fehlercode (Fehler zeigt auf Zeile mit **):

/**
     * Retrieve submission step data
     *
     * @param $key - empty when setting
     * @return bool
     */
    public function loadSubmitData($h, $key = '')
    {
        // delete everything in this table older than 30 minutes:
        $this->deleteTempData($h->db);

        if (!$key) { return false; }

        $cleanKey = preg_replace('/[^a-z0-9]+/','',$key);
        if (strcmp($key,$cleanKey) != 0) {
            return false;
        } else {
            $sql = "SELECT tempdata_value FROM " . TABLE_TEMPDATA . " WHERE tempdata_key = %s ORDER BY tempdata_updatedts DESC LIMIT 1";
            $submitted_data = $h->db->get_var($h->db->prepare($sql, $key));
            **if ($submitted_data) { return unserialize($submitted_data); } else { return false; }** 
        }
    }

Daten aus der Tabelle, beachten Sie, dass das Ende-Bit die Bild-Information hat, ich bin kein Experte in PHP, also habe ich mich gefragt, was Sie / Mädels denken könnten?

tempdata_value:

a:10:{s:16:"submit_editorial";b:0;s:15:"submit_orig_url";s:13:"www.bbc.co.uk";s:12:"submit_title";s:14:"No title found";s:14:"submit_content";s:12:"dnfsdkfjdfdf";s:15:"submit_category";i:2;s:11:"submit_tags";s:3:"bbc";s:9:"submit_id";b:0;s:16:"submit_subscribe";i:0;s:15:"submit_comments";s:4:"open";s:5:"image";s:19:"C:fakepath100.jpg";}

Edit: Ich glaube, ich habe das Serialisierungsbit gefunden ...

/**
     * Save submission step data
     *
     * @return bool
     */
    public function saveSubmitData($h)
    {
        // delete everything in this table older than 30 minutes:
        $this->deleteTempData($h->db);

        $sid = preg_replace('/[^a-z0-9]+/i', '', session_id());
        $key = md5(microtime() . $sid . rand());
        $sql = "INSERT INTO " . TABLE_TEMPDATA . " (tempdata_key, tempdata_value, tempdata_updateby) VALUES (%s,%s, %d)";
        $h->db->query($h->db->prepare($sql, $key, serialize($h->vars['submitted_data']), $h->currentUser->id));
        return $key;
    }

74
2018-04-14 10:34


Ursprung


Antworten:


unserialize() [function.unserialize]: Error at offset war zu tun invalid serialization data wegen ungültiger Länge

Schnelle Lösung 

Was Sie tun können, ist recalculating the length der Elemente in serialisierten Array

Sie aktuelle serialisierte Daten 

$data = 'a:10:{s:16:"submit_editorial";b:0;s:15:"submit_orig_url";s:13:"www.bbc.co.uk";s:12:"submit_title";s:14:"No title found";s:14:"submit_content";s:12:"dnfsdkfjdfdf";s:15:"submit_category";i:2;s:11:"submit_tags";s:3:"bbc";s:9:"submit_id";b:0;s:16:"submit_subscribe";i:0;s:15:"submit_comments";s:4:"open";s:5:"image";s:19:"C:fakepath100.jpg";}';

Beispiel ohne Neuberechnung 

var_dump(unserialize($data));

Ausgabe

Notice: unserialize() [function.unserialize]: Error at offset 337 of 338 bytes

Neuberechnung 

$data = preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'", $data);
var_dump(unserialize($data));

Ausgabe

array
  'submit_editorial' => boolean false
  'submit_orig_url' => string 'www.bbc.co.uk' (length=13)
  'submit_title' => string 'No title found' (length=14)
  'submit_content' => string 'dnfsdkfjdfdf' (length=12)
  'submit_category' => int 2
  'submit_tags' => string 'bbc' (length=3)
  'submit_id' => boolean false
  'submit_subscribe' => int 0
  'submit_comments' => string 'open' (length=4)
  'image' => string 'C:fakepath100.jpg' (length=17)

Empfehlung .. ICH

Anstatt diese Art von Quickfix zu verwenden, rate ich Ihnen, die Frage mit zu aktualisieren

  • Wie Sie Ihre Daten serialisieren

  • Wie du es speicherst ..

============================= EDIT 1 ================ ================== 

Der Fehler 

Der Fehler wurde aufgrund der Verwendung von Anführungszeichen generiert " stattdessen einfaches Zitat ' deswegen C:\fakepath\100.png wurde umgewandelt in C:fakepath100.jpg 

Um den Fehler zu beheben 

Du musst dich ändern $h->vars['submitted_data'] Von (Beachten Sie die Singe ziemlich ' )

Ersetzen

 $h->vars['submitted_data']['image'] = "C:\fakepath\100.png" ;

Mit

 $h->vars['submitted_data']['image'] = 'C:\fakepath\100.png' ;

Zusätzlicher Filter 

Sie können diesen einfachen Filter auch vor dem Aufruf von serialize hinzufügen

function satitize(&$value, $key)
{
    $value = addslashes($value);
}

array_walk($h->vars['submitted_data'], "satitize");

Wenn Sie UTF-Zeichen haben, können Sie auch ausführen

 $h->vars['submitted_data'] = array_map("utf8_encode",$h->vars['submitted_data']);

Wie erkennt man das Problem in zukünftigen serialisierten Daten? 

  findSerializeError ( $data1 ) ;

Ausgabe

Diffrence 9 != 7
    -> ORD number 57 != 55
    -> Line Number = 315
    -> Section Data1  = pen";s:5:"image";s:19:"C:fakepath100.jpg
    -> Section Data2  = pen";s:5:"image";s:17:"C:fakepath100.jpg
                                            ^------- The Error (Element Length)

findSerializeError Funktion

function findSerializeError($data1) {
    echo "<pre>";
    $data2 = preg_replace ( '!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'",$data1 );
    $max = (strlen ( $data1 ) > strlen ( $data2 )) ? strlen ( $data1 ) : strlen ( $data2 );

    echo $data1 . PHP_EOL;
    echo $data2 . PHP_EOL;

    for($i = 0; $i < $max; $i ++) {

        if (@$data1 {$i} !== @$data2 {$i}) {

            echo "Diffrence ", @$data1 {$i}, " != ", @$data2 {$i}, PHP_EOL;
            echo "\t-> ORD number ", ord ( @$data1 {$i} ), " != ", ord ( @$data2 {$i} ), PHP_EOL;
            echo "\t-> Line Number = $i" . PHP_EOL;

            $start = ($i - 20);
            $start = ($start < 0) ? 0 : $start;
            $length = 40;

            $point = $max - $i;
            if ($point < 20) {
                $rlength = 1;
                $rpoint = - $point;
            } else {
                $rpoint = $length - 20;
                $rlength = 1;
            }

            echo "\t-> Section Data1  = ", substr_replace ( substr ( $data1, $start, $length ), "<b style=\"color:green\">{$data1 {$i}}</b>", $rpoint, $rlength ), PHP_EOL;
            echo "\t-> Section Data2  = ", substr_replace ( substr ( $data2, $start, $length ), "<b style=\"color:red\">{$data2 {$i}}</b>", $rpoint, $rlength ), PHP_EOL;
        }

    }

}

Eine bessere Möglichkeit zum Speichern in der Datenbank 

$toDatabse = base64_encode(serialize($data));  // Save to database
$fromDatabase = unserialize(base64_decode($data)); //Getting Save Format 

183
2018-04-14 10:48



Ich habe nicht genug Reputation, um zu kommentieren, also hoffe ich, dass dies von Leuten gesehen wird, die die obige "richtige" Antwort verwenden:

Seit PHP 5.5 ist der Modifikator / e in preg_replace () vollständig veraltet und der obige preg_match wird fehlgeschlagen. Die php-Dokumentation empfiehlt stattdessen preg_match_callback zu verwenden.

Als Alternative zu dem oben vorgeschlagenen preg_match finden Sie die folgende Lösung.

$fixed_data = preg_replace_callback ( '!s:(\d+):"(.*?)";!', function($match) {      
    return ($match[1] == strlen($match[2])) ? $match[0] : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
},$bad_data );

47
2018-01-27 19:05



Es gibt noch einen anderen Grund unserialize() fehlgeschlagen, weil Sie serialisierte Daten falsch in die Datenbank eingefügt haben Offizielle Erklärung Hier. Schon seit serialize() returns binary data und php variables kümmern sich nicht um Kodierungsmethoden, so dass das Einfügen in TEXT, VARCHAR () diesen Fehler verursacht.

Lösung: Speichern Sie serialisierte Daten in BLOB in Ihrer Tabelle.


12
2017-12-27 08:54



Schnelle Lösung

Neuberechnung der Länge der Elemente in serialisierten Array - aber nicht verwenden (preg_replace) es ist veraltet - besser verwenden Sie preg_replace_callback:

$data = preg_replace_callback('!s:(\d+):"(.*?)";!', function($m) { return 's:'.mb_strlen($m[2]).':"'.$m[2].'";'; }, $data);

7
2017-08-08 08:54



Dieser Fehler wird verursacht, weil Ihr Zeichensatz falsch ist.

Zeichensatz nach offenem Tag setzen:

header('Content-Type: text/html; charset=utf-8');

Und setze den Zeichensatz utf8 in deiner Datenbank:

mysql_query("SET NAMES 'utf8'");

4
2018-04-24 14:56



Öffentliche Funktion unserializeKeySkills ($ string) {

    $output = array();
    $string = trim(preg_replace('/\s\s+/', ' ',$string));
    $string = preg_replace_callback('!s:(\d+):"(.*?)";!', function($m) { return 's:'.strlen($m[2]).':"'.$m[2].'";'; }, utf8_encode( trim(preg_replace('/\s\s+/', ' ',$string)) ));
    try {
        $output =  unserialize($string);
    } catch (\Exception $e) {
        \Log::error("unserialize Data : " .print_r($string,true));
    }
    return $output;
}

4
2018-02-28 09:09



Sie können die unterbrochene Serialisierungszeichenfolge mit der folgenden Funktion reparieren, mit Multibyte-Charakter Handhabung.

function repairSerializeString($value)
{

    $regex = '/s:([0-9]+):"(.*?)"/';

    return preg_replace_callback(
        $regex, function($match) {
            return "s:".mb_strlen($match[2]).":\"".$match[2]."\""; 
        },
        $value
    );
}

3
2018-06-23 12:23



$badData = 'a:2:{i:0;s:16:"as:45:"d";
Is \n";i:1;s:19:"as:45:"d";
Is \r\n";}';

Sie können eine unterbrochene Serialisierungszeichenfolge nicht mithilfe der vorgeschlagenen Regexes beheben:

$data = preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'", $badData);
var_dump(@unserialize($data)); // Output: bool(false)

// or

$data = preg_replace_callback(
    '/s:(\d+):"(.*?)";/',
    function($m){
        return 's:' . mb_strlen($m[2]) . ':"' . $m[2] . '";';
    },
    $badData
);
var_dump(@unserialize($data)); // Output: bool(false)

Sie können die unterbrochene Serialisierungszeichenfolge mit folgendem Regex reparieren:

$data = preg_replace_callback(
    '/(?<=^|\{|;)s:(\d+):\"(.*?)\";(?=[asbdiO]\:\d|N;|\}|$)/s',
    function($m){
        return 's:' . mb_strlen($m[2]) . ':"' . $m[2] . '";';
    },
    $badData
);

var_dump(@unserialize($data));

Ausgabe

array(2) {
  [0] =>
  string(17) "as:45:"d";
Is \n"
  [1] =>
  string(19) "as:45:"d";
Is \r\n"
}

oder

array(2) {
  [0] =>
  string(16) "as:45:"d";
Is \n"
  [1] =>
  string(18) "as:45:"d";
Is \r\n"
}

3
2017-12-29 12:27