如何修复因字节计数长度不正确而损坏的序列化字符串? [英] How to repair a serialized string which has been corrupted by an incorrect byte count length?
问题描述
我正在使用 Hotaru CMS 和图像上传插件,如果我尝试将图像附加到帖子,我会收到此错误,否则没有错误:
<块引用>unserialize() [function.unserialize]:偏移量错误
违规代码(错误指向带有**的行):
/*** 检索提交步骤数据** @param $key - 设置时为空* @return 布尔值*/公共函数 loadSubmitData($h, $key = ''){//删除该表中超过 30 分钟的所有内容:$this->deleteTempData($h->db);if (!$key) { 返回假;}$cleanKey = preg_replace('/[^a-z0-9]+/','',$key);如果(strcmp($key,$cleanKey)!= 0){返回假;} 别的 {$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 { 返回假;}**}}
表格中的数据,注意末尾有图像信息,我不是 PHP 专家,所以我想知道你们/女孩会怎么想?
临时数据值:
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:"图像";s:19:"C:fakepath100.jpg";}
我想我已经找到了序列化位...
/*** 保存提交步骤数据** @return 布尔值*/公共函数 saveSubmitData($h){//删除该表中超过 30 分钟的所有内容:$this->deleteTempData($h->db);$sid = preg_replace('/[^a-z0-9]+/i', '', session_id());$key = md5(microtime() . $sid . rand());$sql = "插入".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));返回 $key;}
unserialize() [function.unserialize]: Error at offset
was due to invalid serialization data
due到无效长度
快速修复
你可以做的是重新计算序列化数组中元素的长度
您当前的序列化数据
$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:"未找到标题";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:"图像";s:19:"C:fakepath100.jpg";}';
没有重新计算的例子
var_dump(unserialize($data));
输出
注意:unserialize() [function.unserialize]:338 字节的偏移量 337 处出错
重新计算
$data = preg_replace('!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'", $data);var_dump(unserialize($data));
输出
数组'提交编辑' =>布尔假'submit_orig_url' =>字符串www.bbc.co.uk"(长度=13)'submit_title' =>字符串未找到标题"(长度 = 14)'submit_content' =>字符串dnfsdkfjdfdf"(长度=12)'submit_category' =>输入 2'submit_tags' =>字符串 'bbc'(长度 = 3)'submit_id' =>布尔假'submit_subscribe' =>整数 0'submit_comments' =>字符串打开"(长度=4)'图像' =>字符串'C:fakepath100.jpg'(长度=17)
推荐..我
不要使用这种快速修复......我建议你用
更新问题您如何序列化数据
你是如何保存它的..
================================ 编辑 1 ================================
错误
错误是由于使用双引号 "
而不是单引号 '
而产生的,这就是为什么 C:\fakepath\100.png
被转换为C:fakepath100.jpg
修复错误
你需要把 $h->vars['submitted_data']
改成(注意很'
)
替换
$h->vars['submitted_data']['image'] = "C:\fakepath\100.png" ;
与
$h->vars['submitted_data']['image'] = 'C:\fakepath\100.png' ;
附加过滤器
你也可以在调用序列化之前添加这个简单的过滤器
function satitize(&$value, $key){$value = addlashes($value);}array_walk($h->vars['submitted_data'], "satitize");
如果你有 UTF 字符,你也可以运行
$h->vars['submitted_data'] = array_map("utf8_encode",$h->vars['submitted_data']);
如何检测未来序列化数据中的问题
findSerializeError ( $data1 ) ;
输出
差异 9 != 7->ORD 编号 57 != 55->行号 = 315->Section Data1 = pen";s:5:"image";s:19:"C:fakepath100.jpg->Section Data2 = pen";s:5:"image";s:17:"C:fakepath100.jpg^------- 错误(元素长度)
findSerializeError
函数
function findSerializeError($data1) {echo "";$data2 = preg_replace ( '!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'",$数据1);$max = (strlen ( $data1 ) > strlen ( $data2 )) ?strlen ( $data1 ) : strlen ( $data2 );回声 $data1 .PHP_EOL;回声 $data2 .PHP_EOL;for($i = 0; $i < $max; $i ++) {如果 (@$data1 {$i} !== @$data2 {$i}) {echo "差异", @$data1 {$i}, " != ", @$data2 {$i}, PHP_EOL;echo "\t-> ORD number ", ord ( @$data1 {$i} ), " != ", ord ( @$data2 {$i} ), PHP_EOL;echo "\t-> 行号 = $i" .PHP_EOL;$start = ($i - 20);$start = ($start <0) ?0:$开始;$length = 40;$point = $max - $i;如果 ($point <20) {$rlength = 1;$rpoint = - $point;} 别的 {$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;}}}
保存到数据库的更好方法
$toDatabse = base64_encode(serialize($data));//保存到数据库$fromDatabase = 反序列化(base64_decode($data));//获取保存格式
I am using Hotaru CMS with the Image Upload plugin, I get this error if I try to attach an image to a post, otherwise there is no error:
unserialize() [function.unserialize]: Error at offset
The offending code (error points to line with **):
/**
* 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; }**
}
}
Data from the table, notice the end bit has the image info, I am not an expert in PHP so I was wondering what you guys/gals might think?
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: I think I've found the serialize bit...
/**
* 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;
}
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
这篇关于如何修复因字节计数长度不正确而损坏的序列化字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!