How to repair a serialized string which has been corrupted by an incorrect byte count length?

The Solution to How to repair a serialized string which has been corrupted by an incorrect byte count length? is


unserialize() [function.unserialize]: Error at offset was dues to invalid serialization data due to invalid length

Quick Fix

What you can do is is recalculating the length of the elements in serialized array

You current serialized data

$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";}';

Example without recalculation

var_dump(unserialize($data));

Output

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

Recalculating

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

Output

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)

Recommendation .. I

Instead of using this kind of quick fix ... i"ll advice you update the question with

  • How you are serializing your data

  • How you are Saving it ..

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

The Error

The Error was generated because of use of double quote " instead single quote ' that is why C:\fakepath\100.png was converted to C:fakepath100.jpg

To fix the error

You need to change $h->vars['submitted_data'] From (Note the singe quite ' )

Replace

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

With

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

Additional Filter

You can also add this simple filter before you call serialize

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

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

If you have UTF Characters you can also run

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

How to detect the problem in future serialized data

  findSerializeError ( $data1 ) ;

Output

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 Function

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;
        }

    }

}

A better way to save to Database

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

~ Answered on 2012-04-14 10:48:12


Most Viewed Questions: