Как восстановить сериализованную строку, которая была повреждена из-за неправильной длины счетчика байтов?


97

Я использую Hotaru CMS с плагином загрузки изображений, я получаю эту ошибку, если пытаюсь прикрепить изображение к сообщению, в противном случае ошибки нет:

unserialize () [function.unserialize]: ошибка смещения

Код нарушения (ошибка указывает на строку с **):

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

Данные из таблицы, обратите внимание, что конечный бит содержит информацию об изображении, я не эксперт в PHP, поэтому мне было интересно, что вы, ребята, можете подумать?

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

Изменить: я думаю, что нашел бит сериализации ...

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

3
Для меня быстрое решение этой проблемы заключалось в использовании base64_encode / decode перед сериализацией / десериализацией. davidwalsh.name/php-serialize-unserialize-issues
Валентин Деспа

1
я не знаю почему, но мой решил с добавленным @,@unserialize($product->des_txtmopscol);
Бхавин Рана

2
Добавление @BhavinRana @- это не устранение ошибок, а их подавление - ничто не "исправляется" с помощью этой техники.
mickmackusa 08

Ответы:


218

unserialize() [function.unserialize]: Error at offsetбыл оброк invalid serialization dataиз - за некорректную длину

Быстрая починка

Что вы можете сделать, это recalculating the lengthэлементы в сериализованном массиве

Вы текущие сериализованные данные

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

Пример без пересчета

var_dump(unserialize($data));

Вывод

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

Пересчет

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

Вывод

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)

Рекомендация .. I

Вместо того, чтобы использовать такое быстрое исправление ... я советую вам обновить вопрос с помощью

  • Как вы сериализуете свои данные

  • Как вы это сохраняете ..

================================ РЕДАКТИРОВАТЬ 1 ================ ===============

Ошибка

Ошибка возникла из-за использования двойной кавычки "вместо одинарной ', поэтому C:\fakepath\100.pngбыла преобразована вC:fakepath100.jpg

Чтобы исправить ошибку

Вам нужно изменить $h->vars['submitted_data']From (обратите внимание на один ')

Заменить

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

С участием

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

Дополнительный фильтр

Вы также можете добавить этот простой фильтр перед вызовом сериализации

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

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

Если у вас есть символы UTF, вы также можете запустить

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

Как обнаружить проблему в будущих сериализованных данных

  findSerializeError ( $data1 ) ;

Вывод

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

    }

}

Лучший способ сохранить в базе данных

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

1
Баба, я воспользовался твоей удивительной findSerializeErrorфункцией и нашел много ошибок. Пожалуйста, посмотрите мою тему
Макс Корецкий

1
используйте base64в статье перед добавлением его в базу данных ... он сохранит нулевой символ
Баба

1
Это не лучший способ сохранить в базе данных. Это так, если вы не хотите полностью игнорировать назначение базы данных. Как вы собираетесь выполнять поиск по кучке зашифрованных значений? Не говоря уже о навороте, тьфу. Правильное кодирование - правильный ответ.
Deji

4
Если вы используете PHP 5.5, см. Ответ @ r00tAcc3ss! stackoverflow.com/a/21389439/1003020
Винисиус Гарсия

6
Если вы получаете эту ошибку «preg_replace (): модификатор / e больше не поддерживается, используйте вместо этого preg_replace_callback» в php7 - этот ответ работает stackoverflow.com/a/21389439/2011434
BenB

82

У меня недостаточно репутации, чтобы комментировать, поэтому я надеюсь, что это увидят люди, использующие приведенный выше «правильный» ответ:

Начиная с php 5.5, модификатор / e в preg_replace () полностью устарел, и предыдущий preg_match выдает ошибку. Документация php рекомендует использовать вместо него preg_match_callback.

Найдите следующее решение в качестве альтернативы предложенному выше preg_match.

$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 );

3
Похоже, что это единственный ответ на странице, который действительно дает хорошее применение первой группе захвата. В то время как разумное программирование заключается в замене только там, где количество байтов на самом деле неверно, это решение не кэширует strlen()и, следовательно, делает избыточные вызовы функций. Лично я считаю добавление встроенного условия слишком подробным, но этот фрагмент дает хорошие результаты по уважительным причинам.
mickmackusa

4
У меня это сработало со следующим регулярным выражением '!s:(\d+):"(.*?)";!s'(с окончанием s, чтобы также вводить новые строки). Спасибо за комментарий Адильбо ниже.
ArnoHolo

13

Есть еще одна причина unserialize()неудачной, потому что вы неправильно поместили сериализованные данные в базу данных, см. Официальное объяснение здесь. Поскольку serialize()возвращаемые двоичные данные и переменные php не заботятся о методах кодирования, поэтому, помещая их в TEXT, VARCHAR () вызовет эту ошибку.

Решение: сохраните сериализованные данные в BLOB в вашей таблице.


Это решило мою проблему в Laravel 5. Я изменил определение столбца со string () на binary ().
WNRosenberg

Вопрос OP, похоже, не имеет проблемы с типом столбца mysql. Очевидно, он поврежден из-за неправильного вычисления байта для imageзначения. Ваш ответ не имеет отношения к конкретному вопросу ОП. Вы можете переместить свой совет по
адресу

11

Быстрая починка

Пересчет длины элементов в сериализованном массиве - но не используйте (preg_replace), он устарел - лучше используйте preg_replace_callback:

Изменить: новая версия теперь не только неправильной длины, но также исправляет разрывы строк и подсчитывает правильные символы с акцентом (благодаря mickmackusa )

// New Version
$data = preg_replace_callback('!s:\d+:"(.*?)";!s', function($m) { return "s:" . strlen($m[1]) . ':"'.$m[1].'";'; }, $data);

1
Как это неправильное решение набрало 8 голосов? Я заткнулся, чтобы подумать, сколько людей невольно скопировало бы этот однострочный текст. [грустное лицо] Вот доказательство двух причин, по которым этот фрагмент не сработает : 3v4l.org/Cf6Nh См. мой усовершенствованный шаблон и пользовательскую замену @ stackoverflow.com/a/55074706/2943403
mickmackusa

1
Моего решения больше нет на другой странице, потому что это было неправильное решение для катастрофически поврежденной сериализованной строки. Я добавил свой фрагмент на эту страницу и предоставил объяснения и демонстрации. stackoverflow.com/a/55566407/2943403
mickmackusa 08

5

Эта ошибка вызвана неправильной кодировкой.

Установить кодировку после открытого тега:

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

И установите кодировку utf8 в своей базе данных:

mysql_query("SET NAMES 'utf8'");

Я не вижу никаких указаний в опубликованном вопросе OP, чтобы предположить, что повреждение связано с кодировкой. Вы можете бесплатно защищать свое требование, но, насколько я могу судить, кто-то вручную обновил imageзначение и не смог обновить счетчик байтов. Если не указано иное, я должен предположить, что этот ответ неверен для вопроса OP.
mickmackusa

4

Вы можете исправить сломанную строку сериализации, используя следующую функцию с обработкой многобайтовых символов .

function repairSerializeString($value)
{

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

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

Суть того, что рекомендует этот ответ, просто неверна и потенциально может повредить совершенно допустимые сериализованные строки. Этот фрагмент нельзя использовать / доверять.
mickmackusa

@mickmackusa Я не понимаю вашей точки зрения. Не могли бы вы предложить лучший способ сделать это? или предложите отредактировать этот ответ ..
Раджеш Мения

Я представил здесь правильное решение: stackoverflow.com/a/55566407/2943403 и объяснил, что mb_strlen()это неуместно, потому что serialize()хранит количество байтов, а не количество символов. Если вы исправите свой ответ, это приведет к появлению на странице лишних советов.
mickmackusa

4

публичная функция 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;
}

php unserialize
Пардип Гоял

Это решение не подходит для многих случаев. Предполагается, что каждый захочет изменить значения в сериализованной строке, чтобы преобразовать 2 или более символов пробела в буквальное пространство И trim()каждую совпавшую подстроку. Одно только это делает невозможным рекомендовать это решение. Кроме того, он задыхается от символов новой строки и излишне захватывает уже существующее количество байтов, которое в любом случае будет перезаписано. Наконец, это «ответ, состоящий только из кода», и эти типы ответов не имеют большого значения, поскольку они мало что делают для обучения / расширения возможностей будущих исследователей.
mickmackusa

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

Вы не можете исправить сломанную строку сериализации с помощью предлагаемых регулярных выражений:

$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:' . strlen($m[2]) . ':"' . $m[2] . '";';
    },
    $badData
);
var_dump(@unserialize($data)); // Output: bool(false)

Вы можете исправить сломанную строку сериализации, используя следующее регулярное выражение:

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

var_dump(@unserialize($data));

Вывод

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

или

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

1
@mickmackusa Спасибо. Исправлена ​​проблема с многобайтовыми кодировками.
Даниил Путилин

2

что официальные документы говорят , что должно возвращать ложное и множество E_NOTICE

но поскольку вы получили ошибку, отчет об ошибке должен запускаться E_NOTICE

вот исправление, позволяющее обнаруживать false, возвращаемое unserialize

$old_err=error_reporting(); 
error_reporting($old_err & ~E_NOTICE);
$object = unserialize($serialized_data);
error_reporting($old_err);

вы можете захотеть использовать кодирование / декодирование base64

$string=base64_encode(serialize($obj));
unserialize(base64_decode($string));

base64_encodeсделал трюк для меня. В моем случае мы передаем serializeданные d через командную строку, и похоже, что какие-то странные символы мешают ей работать правильно.
quickshiftin

base64_encode()не является решением вопроса, заданного ОП. Вопрос / проблема OP конкретно касается того факта, что (вероятно, связано с несоответствующей заменой подстроки в «последнем элементе массива» сериализованной строки) в сериализованной строке есть неправильное количество байтов. Пожалуйста, публикуйте только ответы, которые напрямую связаны с заданным вопросом.
mickmackusa

2

Повреждение в этом вопросе изолировано от единственной подстроки в конце сериализованной строки, которая, вероятно, была вручную заменена кем-то, кто лениво хотел обновить imageимя файла. Этот факт будет очевиден в моей демонстрационной ссылке ниже с использованием опубликованных данных OP - короче говоря, C:fakepath100.jpgне имеет длины 19, она должна быть 17.

Поскольку повреждение сериализованной строки ограничено неправильным числом счетчика байтов / символов, следующее будет выполнять прекрасную работу по обновлению поврежденной строки с правильным значением счетчика байтов.

Следующая замена на основе регулярных выражений будет эффективна только для исправления количества байтов, не более того.

Похоже, что многие из предыдущих сообщений просто копируют шаблон регулярного выражения от кого-то другого. Нет причин фиксировать потенциально поврежденный счетчик байтов, если он не будет использоваться при замене. Кроме того, добавление sмодификатора шаблона является разумным включением в случае, если строковое значение содержит символы новой строки / возврат строки.

* Для тех, кто не осведомлен об обработке многобайтовых символов с помощью сериализации, вы не должны использовать mb_strlen()в настраиваемом обратном вызове, потому что это счетчик байтов, который сохраняется, а не количество символов , см. Мой вывод ...

Код: ( Демо с данными OP ) ( Демо с произвольными выборочными данными ) ( Демо с заменой условий )

$corrupted = <<<STRING
a:4:{i:0;s:3:"three";i:1;s:5:"five";i:2;s:2:"newline1
newline2";i:3;s:6:"garçon";}
STRING;

$repaired = preg_replace_callback(
        '/s:\d+:"(.*?)";/s',
        //  ^^^- matched/consumed but not captured because not used in replacement
        function ($m) {
            return "s:" . strlen($m[1]) . ":\"{$m[1]}\";";
        },
        $corrupted
    );

echo $corrupted , "\n" , $repaired;
echo "\n---\n";
var_export(unserialize($repaired));

Вывод:

a:4:{i:0;s:3:"three";i:1;s:5:"five";i:2;s:2:"newline1
Newline2";i:3;s:6:"garçon";}
a:4:{i:0;s:5:"three";i:1;s:4:"five";i:2;s:17:"newline1
Newline2";i:3;s:7:"garçon";}
---
array (
  0 => 'three',
  1 => 'five',
  2 => 'newline1
Newline2',
  3 => 'garçon',
)

Одна нога в кроличьей норе ... Вышеупомянутое отлично работает, даже если в строковом значении встречаются двойные кавычки, но если строковое значение содержит ";или какой-то другой sbustring, вам нужно пойти немного дальше и реализовать «поисковые обходы». Моя новая выкройка

проверяет, что ведущий s:

  • начало всей входной строки или
  • предшествует ;

и проверяет, что ";:

  • в конце всей входной строки или
  • за которым следует }или
  • за которым следует строковое или целочисленное объявление, s:илиi:

Я не проверял каждую возможность; Фактически, я относительно незнаком со всеми возможностями сериализованной строки, потому что я никогда не выбираю работу с сериализованными данными - всегда json в современных приложениях. Если есть дополнительные возможные начальные или конечные символы, оставьте комментарий, и я расширю поиск.

Расширенный фрагмент: ( Демо )

$corrupted_byte_counts = <<<STRING
a:12:{i:0;s:3:"three";i:1;s:5:"five";i:2;s:2:"newline1
newline2";i:3;s:6:"garçon";i:4;s:111:"double " quote \"escaped";i:5;s:1:"a,comma";i:6;s:9:"a:colon";i:7;s:0:"single 'quote";i:8;s:999:"semi;colon";s:5:"assoc";s:3:"yes";i:9;s:1:"monkey";wrenching doublequote-semicolon";s:3:"s:";s:9:"val s: val";}
STRING;

$repaired = preg_replace_callback(
        '/(?<=^|;)s:\d+:"(.*?)";(?=$|}|[si]:)/s',
        //^^^^^^^^--------------^^^^^^^^^^^^^-- some additional validation
        function ($m) {
            return 's:' . strlen($m[1]) . ":\"{$m[1]}\";";
        },
        $corrupted_byte_counts
    );

echo "corrupted serialized array:\n$corrupted_byte_counts";
echo "\n---\n";
echo "repaired serialized array:\n$repaired";
echo "\n---\n";
print_r(unserialize($repaired));

Вывод:

corrupted serialized array:
a:12:{i:0;s:3:"three";i:1;s:5:"five";i:2;s:2:"newline1
newline2";i:3;s:6:"garçon";i:4;s:111:"double " quote \"escaped";i:5;s:1:"a,comma";i:6;s:9:"a:colon";i:7;s:0:"single 'quote";i:8;s:999:"semi;colon";s:5:"assoc";s:3:"yes";i:9;s:1:"monkey";wrenching doublequote-semicolon";s:3:"s:";s:9:"val s: val";}
---
repaired serialized array:
a:12:{i:0;s:5:"three";i:1;s:4:"five";i:2;s:17:"newline1
newline2";i:3;s:7:"garçon";i:4;s:24:"double " quote \"escaped";i:5;s:7:"a,comma";i:6;s:7:"a:colon";i:7;s:13:"single 'quote";i:8;s:10:"semi;colon";s:5:"assoc";s:3:"yes";i:9;s:39:"monkey";wrenching doublequote-semicolon";s:2:"s:";s:10:"val s: val";}
---
Array
(
    [0] => three
    [1] => five
    [2] => newline1
newline2
    [3] => garçon
    [4] => double " quote \"escaped
    [5] => a,comma
    [6] => a:colon
    [7] => single 'quote
    [8] => semi;colon
    [assoc] => yes
    [9] => monkey";wrenching doublequote-semicolon
    [s:] => val s: val
)

1

Вам нужно будет изменить тип сопоставления на, utf8_unicode_ciи проблема будет устранена.


Как вы думаете, какой конкретный символ в выборочных данных OP будет изменен при изменении сопоставления на utf8_unicode_ci? У меня есть сомнения по этому поводу.
mickmackusa

Это также действительно сработало для меня (кроме ответа r00tAcc3ss) любое слово от кого-то, разъясняющее, почему? В качестве фона я беру данные из вызова API к приложению ResourceSpace, сохраняю их в массиве, сериализирую и сохраняю. У сериализованных данных были проблемы с сохранением, поэтому мне пришлось вручную закодировать их в UTF-8, я играл с сопоставлением и набором символов в БД, и, наконец, остался с сопоставлением utf8_general_ci, когда я изменил его на utf8_unicode_ci, это сработало .
Роберто Бесерра

1

В моем случае я хранил сериализованные данные в BLOBполе базы данных MySQL, которое, по-видимому, не было достаточно большим, чтобы содержать все значение, и урезал его. Очевидно, что такую ​​строку нельзя десериализовать.
Однажды преобразовав это поле, MEDIUMBLOBпроблема рассеялась. Также может потребоваться переключить параметры таблицы ROW_FORMATна DYNAMICили COMPRESSED.


Мне - хотя у меня было TEXTполе и поэтому было обрезано до 65kb.
Энтони

Этот вопрос не страдает усечением. Вопрос / проблема OP конкретно касается того факта, что (вероятно, связано с несоответствующей заменой подстроки в «последнем элементе массива» сериализованной строки) в сериализованной строке есть неправильное количество байтов. Пожалуйста, публикуйте только ответы, которые напрямую связаны с заданным вопросом.
mickmackusa 08

1

Попробовав некоторые вещи на этой странице без успеха, я заглянул в источник страницы и заметил, что все кавычки в сериализованной строке были заменены на html-объекты. Расшифровка этих сущностей помогает избежать большой головной боли:

$myVar = html_entity_decode($myVar);

Этот вопрос не страдает от сущностей в кодировке html в сериализованной строке. Вопрос / проблема OP конкретно касается того факта, что (вероятно, связано с несоответствующей заменой подстроки в «последнем элементе массива» сериализованной строки) в сериализованной строке есть неправильное количество байтов. Пожалуйста, публикуйте только ответы, которые напрямую связаны с заданным вопросом.
mickmackusa

@mickmackusa Этому вопросу почти 7 лет, и мой ответ ~ 1,5. Тем не менее приятно, что вы так много занимаетесь!
Дэвид

Я люблю ТАК страницы - молодые и старые. Я ищу исследователей, которые не знают разницы между хорошим и не очень хорошим ответом. Эта страница, к сожалению, полна советов не по теме.
mickmackusa

Большой! Уже есть качественный контроль и голосование, но у меня нет причин останавливать вас ;-)
Дэвид

О нет, посмотрите. Есть ответы, за которые проголосовали, но за которые нужно проголосовать против. Слишком много людей не могут различить. На этой странице подсчет голосов не является показателем качества / соответствия. Я не собираюсь тратить свое время на голосование против, потому что мое голосование против не повлияет на результат. Лучшее, что я могу сделать, это оставить комментарии, чтобы объяснить, что хорошо / плохо / некрасиво.
mickmackusa

1

Вот онлайн-инструмент для исправления поврежденной сериализованной строки.

Я хотел бы добавить , что это в основном происходит из - за поиск и замены делается на БД и данных сериализации ( специальноkey length ) не обновляются в соответствии с ЗАМЕНИТЬ и что вызывает «коррупцию».

Тем не менее, вышеуказанный инструмент использует следующую логику для исправления данных сериализации ( скопировано отсюда ).

function error_correction_serialise($string){
    // at first, check if "fixing" is really needed at all. After that, security checkup.
    if ( unserialize($string) !== true &&  preg_match('/^[aOs]:/', $string) ) {
         $string = preg_replace_callback( '/s\:(\d+)\:\"(.*?)\";/s',    function($matches){return 's:'.strlen($matches[2]).':"'.$matches[2].'";'; },   $string );
    }
    return $string;
} 

0

Другой причиной этой проблемы может быть тип столбца таблицы сеансов полезной нагрузки. Если у вас есть огромные данные о сеансе, текстового столбца будет недостаточно. Вам понадобится MEDIUMTEXT или даже LONGTEXT.


Этот вопрос не страдает усечением. Вопрос / проблема OP конкретно касается того факта, что (вероятно, связано с несоответствующей заменой подстроки в «последнем элементе массива» сериализованной строки) в сериализованной строке есть неправильное количество байтов. Пожалуйста, публикуйте только ответы, которые напрямую связаны с заданным вопросом.
mickmackusa
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.