Як відновити серіалізований рядок, пошкоджений неправильною довжиною підрахунку байтів?


96

Я використовую Hotaru CMS із плагіном Image Upload, я отримую цю помилку, якщо намагаюся вкласти зображення до публікації, інакше помилки не буде:

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-isissue
Валентин

1
Я не знаю, чому, але моє вирішено з додаванням @,@unserialize($product->des_txtmopscol);
Бхавін Рана

2
@BhavinRana додавання @- це не вирішення помилок, це мовчання помилок - насправді нічого не "виправляється" з цією технікою.
mickmackusa

Відповіді:


219

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

Замість використання такого роду швидкого виправлення ... я порадую вам оновити питання

  • Як ви серіалізуєте свої дані

  • Як ти економиш ..

================================= EDIT 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 = 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
Вініцій Гарсія

5
Якщо ви отримаєте цю помилку "preg_replace (): модифікатор / e більше не підтримується, використовуйте замість preg_replace_callback" у php7 - ця відповідь працює stackoverflow.com/a/21389439/2011434
BenB

81

У мене недостатньо репутації, щоб коментувати, тому сподіваюся, це бачать люди, які використовують вищезазначену "правильну" відповідь:

Оскільки модифікатор php 5.5 a / 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

3
Це спрацювало для мене з наступним регулярним виразом '!s:(\d+):"(.*?)";!s'(із закінченням 's', щоб взяти також нові рядки). Завдяки коментарю adilbo нижче.
ArnoHolo

13

Є ще одна причина, яка unserialize()не вдалася, оскільки ви неправильно розмістили серіалізовані дані в базі даних. Див. Офіційне пояснення тут. Оскільки serialize()повертає двійкові дані та змінні php не хвилюються методи кодування, тож розміщення їх у ТЕКСТІ, VARCHAR () спричинить цю помилку.

Рішення: зберігайте серіалізовані дані у BLOB у вашій таблиці.


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

Здається, запитання OP не має проблем із типом стовпця mysql. Це, мабуть, пошкоджено неправильним байтовим розрахунком imageзначення. Ваша відповідь не стосується конкретного питання ОП. Ви можете перемістити рада: stackoverflow.com/q/5544749/2943403
mickmackusa

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

5

Ця помилка викликана тим, що ваш гарнітур неправильний.

Встановити діаграму після відкритого тегу:

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

І встановіть charset utf8 у своїй базі даних:

mysql_query("SET NAMES 'utf8'");

Я не бачу жодних ознак у розміщеному питанні ОП, які б припускали, що корупція пов'язана з колом. Безкоштовно захистити свою претензію, але, наскільки я можу сказати, хтось оновив imageзначення вручну та не зміг оновити кількість байтів. Якщо інше не повідомлено, я маю припустити, що ця відповідь не відповідає питанню ОП.
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 ($ рядок) {

    $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
Pardeep Goyal

Це рішення не підходить для багатьох випадків. Це передбачає, що всі хочуть мутувати значення в серіалізованій рядку для перетворення 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

ось виправлення, яке дозволяє виявити помилкове повернення 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зробив трюк для мене. У моєму випадку ми передаємо serialized дані через командний рядок, і, здавалося, деякі дивні символи заважають йому працювати належним чином.
quickshiftin

base64_encode()не є вирішенням питання, яке задає ОП. Питання / питання ОП конкретно стосується того факту, що (ймовірно, для невідповідної заміни підрядки на "остаточному елементі масиву" серіалізованого рядка) є неправильний підрахунок байтів у серіалізованому рядку. Будь ласка, публікуйте лише відповіді, які безпосередньо стосуються поставленого питання.
mickmackusa

2

Пошкодження у цьому питанні виділено в один підрядок у кінці серіалізованого рядка, імовірно, замінено вручну тим, хто ліниво хотів оновити imageім'я файлу. Цей факт буде очевидним у моєму демонстраційному посиланні нижче, використовуючи розміщені дані ОП - словом, C:fakepath100.jpgвін не має довжини 19, він повинен бути 17.

Оскільки пошкодження серіалізованого рядка обмежено невірним числом байтів / символів, наступне допоможе оновити пошкоджений рядок правильним значенням байтів.

Наступна заміна на основі регулярних виразів буде ефективною лише для виправлення кількості байтів, не більше того.

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

* Для тих, хто не знає обробку мультибайтових символів серіалізацією, ви не повинні використовувати mb_strlen()в користувальницькому зворотному дзвінку, оскільки це кількість байтів зберігається не кількість символів , дивіться мій вихід ...

Код: ( Демо з даними ОП ) ( Демо з умовними даними вибірки ) ( Демо з умовою, що замінює )

$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',
)

Однією ногою в кролячій норі ... Вищезазначене працює добре, навіть якщо подвійні лапки містяться у ";рядковому значенні, але якщо значення рядка містить або якийсь інший мавповий штрих, потрібно буде піти трохи далі та здійснити "lookarounds". Мій новий зразок

перевіряє, що провідним 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і проблема буде вирішена.


Як ви вважаєте, який конкретний символ у зразкових даних ОП буде змінено шляхом зміни порівняння на utf8_unicode_ci? У мене є сумніви щодо цього.
mickmackusa

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

1

У моєму випадку я зберігав серіалізовані дані у BLOBполі MySQL DB, що, очевидно, не було достатньо великим, щоб містити ціле значення і усікало його. Такий рядок, очевидно, не міг бути несеріалізованим.
Після перетворення цього поля MEDIUMBLOBв проблему розсіяне. Також може знадобитися перемкнути параметри таблиці ROW_FORMATна DYNAMICабо COMPRESSED.


Мені - хоча моя була TEXTполем і як така усічена на 65 кб.
Антоній

Це питання не страждає від усікання. Питання / питання ОП конкретно стосується того факту, що (ймовірно, для невідповідної заміни підрядки на "остаточному елементі масиву" серіалізованого рядка) є неправильний підрахунок байтів у серіалізованому рядку. Будь ласка, публікуйте лише відповіді, які безпосередньо стосуються поставленого питання.
mickmackusa

1

Спробувавши деякі речі на цій сторінці без успіху, я заглянув у джерело сторінки і зазначив, що всі лапки в серіалізованому рядку замінені html-сутностями. Розшифровка цих об'єктів допомагає уникнути сильного головного болю:

$myVar = html_entity_decode($myVar);

Це питання не страждає від HTML-кодованих сутностей у серіалізованому рядку. Питання / питання ОП конкретно стосується того факту, що (ймовірно, для невідповідної заміни підрядки на "остаточному елементі масиву" серіалізованого рядка) є неправильний підрахунок байтів у серіалізованому рядку. Будь ласка, публікуйте лише відповіді, які безпосередньо стосуються поставленого питання.
mickmackusa

@mickmackusa Цьому питанню майже 7 років, і моя відповідь ~ 1,5. Тим не менше приємно, що ти так багато займаєшся!
Девід

Я люблю сторінки SO - молоді та старі. Я шукаю дослідників, які не знають різниці між хорошою та не дуже хорошою відповіддю. Ця сторінка, на жаль, сповнена поза тематичними порадами.
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

Іншою причиною цієї проблеми може бути тип стовпця таблиці сесій "корисне навантаження". Якщо у вас є величезні дані про сеанс, текстового стовпця буде недостатньо. Вам знадобиться СЕРЕДНІЙ ТЕКСТ або навіть ЛОНГТЕКСТ.


Це питання не страждає від усікання. Питання / питання ОП конкретно стосується того факту, що (ймовірно, для невідповідної заміни підрядки на "остаточному елементі масиву" серіалізованого рядка) є неправильний підрахунок байтів у серіалізованому рядку. Будь ласка, публікуйте лише відповіді, які безпосередньо стосуються поставленого питання.
mickmackusa
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.