Come riparare una stringa serializzata che è stata danneggiata da una lunghezza di conteggio byte errata?


96

Sto utilizzando Hotaru CMS con il plug-in di caricamento delle immagini, ottengo questo errore se provo ad allegare un'immagine a un post, altrimenti non ci sono errori:

unserialize () [function.unserialize]: errore all'offset

Il codice offensivo (l'errore punta alla linea con **):

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

Dati dalla tabella, notate che la parte finale ha le informazioni sull'immagine, non sono un esperto di PHP, quindi mi chiedevo cosa potreste pensare voi ragazzi?

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

Modifica: penso di aver trovato il bit di serializzazione ...

/**
     * 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
Per me la soluzione rapida per questo è stata l'utilizzo di base64_encode / decode prima di serializzare / deserializzare. davidwalsh.name/php-serialize-unserialize-issues
Valentin Despa

1
Non so perché, ma il mio è stato risolto con @,@unserialize($product->des_txtmopscol);
Bhavin Rana

2
@BhavinRana l'aggiunta @non è la risoluzione degli errori, è il silenziamento degli errori - nulla in realtà "viene risolto" con quella tecnica.
mickmackusa

Risposte:


219

unserialize() [function.unserialize]: Error at offsetera invalid serialization datadovuto a causa di lunghezza non valida

Soluzione rapida

Quello che puoi fare è recalculating the lengthdegli elementi nell'array serializzato

Dati serializzati correnti

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

Esempio senza ricalcolo

var_dump(unserialize($data));

Produzione

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

Ricalcolo

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

Produzione

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)

Raccomandazione .. I

Invece di usare questo tipo di soluzione rapida ... ti consiglio di aggiornare la domanda con

  • Come stai serializzando i tuoi dati

  • Come lo stai salvando ..

================================ MODIFICA 1 ================ ===============

L'errore

L'errore è stato generato a causa dell'uso di virgolette doppie "anziché virgolette singole, 'motivo C:\fakepath\100.pngper cui è stato convertito inC:fakepath100.jpg

Per correggere l'errore

Devi cambiare $h->vars['submitted_data']Da (nota abbastanza il singe ')

Sostituire

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

Con

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

Filtro aggiuntivo

Puoi anche aggiungere questo semplice filtro prima di chiamare serializzare

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

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

Se hai caratteri UTF puoi anche eseguire

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

Come rilevare il problema nei dati serializzati futuri

  findSerializeError ( $data1 ) ;

Produzione

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 Funzione

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

    }

}

Un modo migliore per salvare nel database

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

1
Baba, ho usato la tua straordinaria findSerializeErrorfunzione e ho trovato molti errori. Si prega di dare un'occhiata al mio argomento
Max Koretskyi

1
utilizzare base64sull'articolo prima di aggiungerlo al database ... manterrebbe il carattere nullo
Baba

1
Questo non è quindi un modo migliore per salvare nel database. Lo è, a meno che tu non voglia trascurare completamente lo scopo del database. Come intendi eseguire una ricerca in un gruppo di valori crittografati? Per non parlare del gonfio, ugh. La corretta codifica è la risposta corretta.
Deji

4
Se si utilizza PHP 5.5, vedere la risposta @ r00tAcc3ss! stackoverflow.com/a/21389439/1003020
Vinicius Garcia

5
Se si ottiene questo errore "preg_replace (): Il modificatore / e non è più supportato, utilizzo preg_replace_callback invece" in php7 - questa risposta funziona stackoverflow.com/a/21389439/2011434
BenB

81

Non ho abbastanza reputazione per commentare, quindi spero che questo venga visto dalle persone che usano la risposta "corretta" sopra:

A partire da php 5.5 il modificatore / e in preg_replace () è stato completamente deprecato e il preg_match sopra verrà eliminato. La documentazione di php consiglia di utilizzare preg_match_callback al suo posto.

Si prega di trovare la seguente soluzione in alternativa al preg_match proposto sopra.

$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
Questa sembra l'unica risposta sulla pagina che mette effettivamente a frutto il primo gruppo di acquisizione. Sebbene una programmazione ragionevole per effettuare solo sostituzioni in cui il conteggio dei byte è effettivamente sbagliato, questa soluzione non memorizza nella cache strlen()e quindi effettua chiamate di funzione ridondanti. Personalmente, trovo che l'aggiunta di una condizione inline sia troppo prolissa, ma questo frammento fa cose buone per buone ragioni.
mickmackusa

3
Ha funzionato per me con la seguente regex '!s:(\d+):"(.*?)";!s'(con una fine 's' per prendere anche nuove linee). Grazie al commento di adilbo qui sotto.
ArnoHolo

13

C'è un altro motivo unserialize()non riuscito perché hai inserito in modo improprio i dati serializzati nel database, vedi la spiegazione ufficiale qui. Poiché serialize()restituisce dati binari e variabili php non si preoccupano dei metodi di codifica, quindi inserirli in TEXT, VARCHAR () causerà questo errore.

Soluzione: archivia i dati serializzati in BLOB nella tua tabella.


Questo ha risolto il mio problema in Laravel 5. Ho cambiato la definizione della colonna da string () a binary ().
WN Rosenberg,

La domanda dell'OP non sembra avere un problema di tipo di colonna mysql. Apparentemente è danneggiato da un calcolo errato dei byte sul imagevalore. La tua risposta non riguarda la domanda specifica del PO. Si potrebbe desiderare di spostare il vostro consiglio per: stackoverflow.com/q/5544749/2943403
mickmackusa

11

Soluzione rapida

Ricalcolare la lunghezza degli elementi nell'array serializzato - ma non usare (preg_replace) è deprecato - meglio usare preg_replace_callback:

Modifica: la nuova versione ora non solo ha una lunghezza sbagliata, ma corregge anche le interruzioni di riga e conta i caratteri corretti con aczent (grazie a mickmackusa )

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

1
In che modo questa soluzione errata ha 8 voti positivi? Scatto per pensare a quante persone avrebbero inconsapevolmente copiato e incollato questa battuta. [faccia triste] Ecco la prova di due modi in cui questo frammento fallirà: 3v4l.org/Cf6Nh Vedere il mio modello di raffinata e sostituzione personalizzati @ stackoverflow.com/a/55074706/2943403
mickmackusa

1
La mia soluzione non è più nell'altra pagina perché era una soluzione errata per la stringa serializzata danneggiata in modo catastrofico. Ho aggiunto il mio snippet a questa pagina e fornito spiegazioni e dimostrazioni. stackoverflow.com/a/55566407/2943403
mickmackusa

5

Questo errore è causato dal fatto che il tuo set di caratteri è sbagliato.

Imposta set di caratteri dopo il tag aperto:

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

E imposta charset utf8 nel tuo database:

mysql_query("SET NAMES 'utf8'");

Non vedo alcuna indicazione nella domanda pubblicata dall'OP che suggerisca che la corruzione sia dovuta al set di caratteri. Nessuna commissione per difendere la tua richiesta, ma per quanto ne so, qualcuno ha aggiornato manualmente il imagevalore e non è riuscito ad aggiornare il conteggio dei byte. Salvo diversa indicazione, devo presumere che questa risposta non sia corretta per la domanda del PO.
mickmackusa

4

È possibile correggere la stringa serializzata danneggiata utilizzando la seguente funzione, con gestione dei caratteri multibyte .

function repairSerializeString($value)
{

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

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

Il nucleo di ciò che questa risposta consiglia è semplicemente sbagliato e potenzialmente danneggerà stringhe serializzate perfettamente valide. Questo snippet non deve essere utilizzato / attendibile.
mickmackusa

@mickmackusa Non capisco il tuo punto, puoi suggerirmi il modo migliore per farlo? o suggerisci di modificare questa risposta ..
Rajesh Meniya

Ho fornito una soluzione corretta qui: stackoverflow.com/a/55566407/2943403 e ho spiegato che mb_strlen()è inappropriato perché serialize()memorizza il conteggio dei byte, non il conteggio dei caratteri. Modificare la risposta per renderla corretta creerebbe solo consigli ridondanti sulla pagina.
mickmackusa

4

funzione pubblica 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

Questa soluzione non è adatta a molti casi. Presuppone che tutti vorranno modificare i valori nella stringa serializzata per convertire 2 o più caratteri di spazi bianchi in uno spazio letterale E trim()ogni sottostringa corrispondente. Questo punto da solo rende impossibile consigliare questa soluzione. Inoltre, si strozzerà con i caratteri di nuova riga e acquisirà inutilmente il conteggio dei byte preesistente che verrà comunque sovrascritto. Infine, questa è una "risposta solo in codice" e questi tipi di risposte sono di scarso valore poiché fanno poco per istruire / responsabilizzare i futuri ricercatori.
mickmackusa

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

Non è possibile correggere una stringa di serializzazione interrotta utilizzando le espressioni regolari proposte:

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

Puoi correggere la stringa serializzata danneggiata usando la seguente regex:

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

var_dump(@unserialize($data));

Produzione

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

o

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

1
@mickmackusa Thanks. Risolto un problema con le codifiche multibyte.
Даниил Путилин

2

i documenti ufficiali dicono che dovrebbe restituire false e impostare E_NOTICE

ma poiché hai ricevuto un errore, la segnalazione degli errori è impostata per essere attivata da E_NOTICE

ecco una correzione per consentire di rilevare il falso restituito da unserialize

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

potresti prendere in considerazione l'uso di base64 encode / decode

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

base64_encodeha fatto il trucco per me. Nel mio caso stiamo passando i serializedati d tramite la riga di comando e sembrava che alcuni caratteri strani gli impedissero di funzionare correttamente.
cambio rapido:

base64_encode()non è la soluzione alla domanda posta dal PO. La domanda / problema dell'OP riguarda specificamente il fatto che (probabilmente a causa di una sostituzione di sottostringa inappropriata sull '"elemento dell'array finale" della stringa serializzata) c'è un conteggio di byte errato nella stringa serializzata. Pubblica solo risposte che trattano direttamente la domanda posta.
mickmackusa

2

Il danneggiamento in questa domanda è isolato su una singola sottostringa alla fine della stringa serializzata con probabilmente è stato sostituito manualmente da qualcuno che voleva pigramente aggiornare il imagenome del file. Questo fatto sarà evidente nel mio link dimostrativo di seguito utilizzando i dati pubblicati dall'OP - in breve, C:fakepath100.jpgnon ha una lunghezza di 19, dovrebbe essere 17.

Poiché il danneggiamento della stringa serializzata è limitato a un numero di conteggio byte / caratteri errato, quanto segue farà un ottimo lavoro di aggiornamento della stringa danneggiata con il valore di conteggio byte corretto.

La seguente sostituzione basata su regex sarà efficace solo per rimediare al conteggio dei byte, niente di più.

Sembra che molti dei post precedenti stiano semplicemente copiando e incollando un pattern regex da qualcun altro. Non vi è alcun motivo per acquisire il numero di conteggio byte potenzialmente danneggiato se non verrà utilizzato nella sostituzione. Inoltre, l'aggiunta del smodificatore di pattern è un'inclusione ragionevole nel caso in cui un valore di stringa contenga ritorni a capo / riga.

* Per coloro che non sono a conoscenza del trattamento dei caratteri multibyte con la serializzazione, non è necessario utilizzare mb_strlen()nel callback personalizzato perché è il conteggio dei byte che viene memorizzato non il conteggio dei caratteri , vedere il mio output ...

Codice: ( Demo con dati OP ) ( Demo con dati campione arbitrari ) ( Demo con sostituzione condizione )

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

Produzione:

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

Una gamba nella tana del coniglio ... Quanto sopra funziona bene anche se le virgolette doppie sono presenti in un valore di stringa, ma se un valore di stringa contiene ";o qualche altro strabiliante sbustring, dovrai andare un po 'oltre e implementare "lookaround". Il mio nuovo modello

verifica che l'interlinea ssia:

  • l'inizio dell'intera stringa di input o
  • preceduto da ;

e verifica che ";sia:

  • alla fine dell'intera stringa di input o
  • seguito da }o
  • seguito da una stringa o da una dichiarazione intera s:oi:

Non ho testato tutte le possibilità; in effetti, non ho familiarità con tutte le possibilità in una stringa serializzata perché non scelgo mai di lavorare con dati serializzati - sempre json nelle applicazioni moderne. Se sono presenti ulteriori caratteri iniziali o finali possibili, lascia un commento e estenderò la ricerca.

Snippet esteso: ( Demo )

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

Produzione:

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

Dovrai modificare il tipo di confronto in utf8_unicode_cie il problema verrà risolto.


Quale carattere specifico nei dati campione dell'OP credi verrà modificato cambiando la collation in utf8_unicode_ci? Ho i miei dubbi su questo.
mickmackusa

Questo in realtà ha funzionato anche per me (a parte la risposta di r00tAcc3ss) qualsiasi parola di qualcuno che ha chiarito il motivo? Come sfondo, prendo i dati da una chiamata API a un'applicazione ResourceSpace, li memorizzo in un array, li serializzo e li salvo. I dati serializzati avevano problemi a essere salvati, quindi ho dovuto codificarli manualmente in UTF-8, stavo giocando con le regole di confronto e il set di caratteri nel DB, e alla fine è rimasto con il confronto utf8_general_ci, quando l'ho cambiato in utf8_unicode_ci, ha funzionato .
Roberto Becerra

1

Nel mio caso stavo memorizzando i dati serializzati nel BLOBcampo del DB MySQL che apparentemente non era abbastanza grande da contenere l'intero valore e lo ha troncato. Ovviamente una stringa del genere non può essere annullata.
Una volta convertito quel campo MEDIUMBLOBnel problema dissipato. Inoltre potrebbe essere necessario passare dalle opzioni della tabella ROW_FORMATa DYNAMICo COMPRESSED.


Io a - sebbene il mio fosse un TEXTcampo e come tale troncato a 65kb.
Antony

Questa domanda non soffre di troncamento. La domanda / problema dell'OP riguarda specificamente il fatto che (probabilmente a causa di una sostituzione di sottostringa inappropriata sull '"elemento dell'array finale" della stringa serializzata) c'è un conteggio di byte errato nella stringa serializzata. Pubblica solo risposte che trattano direttamente la domanda posta.
mickmackusa

1

Dopo aver provato alcune cose su questa pagina senza successo, ho dato un'occhiata al page-source e ho notato che tutte le virgolette nella stringa serializzata sono state sostituite da entità html. Decodificare queste entità aiuta a evitare molto mal di testa:

$myVar = html_entity_decode($myVar);

Questa domanda non soffre di entità codificate html nella stringa serializzata. La domanda / problema dell'OP riguarda specificamente il fatto che (probabilmente a causa di una sostituzione di sottostringa inappropriata sull '"elemento dell'array finale" della stringa serializzata) c'è un conteggio di byte errato nella stringa serializzata. Pubblica solo risposte che trattano direttamente la domanda posta.
mickmackusa

@mickmackusa Questa domanda ha quasi 7 anni e la mia risposta ~ 1,5. Comunque bello che ti impegni così tanto!
David

Adoro le pagine SO - giovani e meno giovani. Sto cercando ricercatori che non conoscano la differenza tra una buona risposta e una non così buona. Questa pagina, sfortunatamente, è piena di consigli fuori tema.
mickmackusa

Grande! C'è già il controllo della qualità e il voto, ma non ho motivo di fermarti ;-)
David

Oh no, dai un'occhiata. Ci sono risposte votate che dovrebbero essere sottovalutate. Troppe persone non possono distinguere. In questa pagina, il conteggio dei voti non è assolutamente indice di qualità / adeguatezza. Non sprecherò il mio tempo a votare negativamente perché il mio voto negativo non inciderà sul conteggio. Il meglio che posso fare è lasciare commenti per spiegare cosa è buono / cattivo / brutto.
mickmackusa

1

Ecco uno strumento online per correggere una stringa serializzata danneggiata.

Vorrei aggiungere che questo accade principalmente a causa di una ricerca e sostituzione eseguita sul DB e i dati di serializzazione ( specialmente il key length) non vengono aggiornati come per la sostituzione e questo causa il "danneggiamento".

Tuttavia, lo strumento precedente utilizza la seguente logica per correggere i dati di serializzazione ( Copiato da qui ).

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

Un altro motivo di questo problema può essere il tipo di colonna della tabella delle sessioni "payload". Se hai dati enormi sulla sessione, una colonna di testo non sarebbe sufficiente. Avrai bisogno di MEDIUMTEXT o anche LONGTEXT.


Questa domanda non soffre di troncamento. La domanda / problema dell'OP riguarda specificamente il fatto che (probabilmente a causa di una sostituzione di sottostringa inappropriata sull '"elemento dell'array finale" della stringa serializzata) c'è un conteggio di byte errato nella stringa serializzata. Pubblica solo risposte che trattano direttamente la domanda posta.
mickmackusa
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.