PHP unserialize fails with non-encoded characters?
The reason why unserialize()
fails with:
$ser = 'a:2:{i:0;s:5:"héllö";i:1;s:5:"wörld";}';
Is because the length for héllö
and wörld
are wrong, since PHP doesn't correctly handle multi-byte strings natively:
echo strlen('héllö'); // 7
echo strlen('wörld'); // 6
However if you try to unserialize()
the following correct string:
$ser = 'a:2:{i:0;s:7:"héllö";i:1;s:6:"wörld";}';
echo '<pre>';
print_r(unserialize($ser));
echo '</pre>';
It works:
Array
(
[0] => héllö
[1] => wörld
)
If you use PHP serialize()
it should correctly compute the lengths of multi-byte string indexes.
On the other hand, if you want to work with serialized data in multiple (programming) languages you should forget it and move to something like JSON, which is way more standardized.
PHP unserialize fails with non-encoded characters?
The reason why unserialize()
fails with:
$ser = 'a:2:{i:0;s:5:"héllö";i:1;s:5:"wörld";}';
Is because the length for héllö
and wörld
are wrong, since PHP doesn't correctly handle multi-byte strings natively:
echo strlen('héllö'); // 7
echo strlen('wörld'); // 6
However if you try to unserialize()
the following correct string:
$ser = 'a:2:{i:0;s:7:"héllö";i:1;s:6:"wörld";}';
echo '<pre>';
print_r(unserialize($ser));
echo '</pre>';
It works:
Array
(
[0] => héllö
[1] => wörld
)
If you use PHP serialize()
it should correctly compute the lengths of multi-byte string indexes.
On the other hand, if you want to work with serialized data in multiple (programming) languages you should forget it and move to something like JSON, which is way more standardized.
PHP function unserialize stop working after charset change (from latin1 to UTF-8)
I found that the length of the serialized string was wrong after change from latin1 to UTF-8.
I fix the problem using this PHP:
$content = preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'", $content);
I'm going to update the data base with the new string.
PHP unserialize problem
Is it possible $item['response']
contains some whitespace before or after it?
Check strlen($item['response'])
gives you 61.
Edit: It seems to work with whitespace at the end, but whitespace at the start will make it fail to unserialize.
Edit: that error message means either you have a LOT of whitespace (almost 2kb of it), or $item['response']
is being changed between the echo
and the unserialize
PHP: serializing and unserializing string containing escaped characters
Your test cases don't match, you're wrapping the string in double quotes in your first example and single quotes in the second, causing the escape character to be taken literally in the latter.
$out = '\'test\'';
is different from
$data = "\'test\'";
if you do
$data = "\'test\'";
$out= serialize($data);
print_r($out); // -> s:8:"\'test\'";
$data = unserialize($out);
print_r($data); // -> \'test\'
it will work.
How to repair a serialized string which has been corrupted by an incorrect byte count length?
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
Related Topics
Uncompress Gzip Compressed Http Response
Can PHP Namespaces Contain Variables
How to Set the Env Variable for PHP
How to Concatenate Multiple Ternary Operator in PHP
What Is Pdo & Why Should I Use It
What Is the Most Efficient Way to Count All the Occurrences of a Specific Character in a PHP String
Parse Xml Namespaces with PHP Simplexml
How to Run Array_Filter Recursively in a PHP Array
Use Strings to Access (Potentially Large) Multidimensional Arrays
The Advantage/Disadvantage Between Global Variables and Function Parameters in PHP
What Does This Mean in Documentation: Square Bracket Followed by Comma ( [, )
Populate Another Select Dropdown from Database Based on Dropdown Selection
Unexpected Character in Input: '\' (Ascii=92) State=1
Casting an Array with Numeric Keys as an Object
PHP Recursion to Get All Possibilities of Strings