¿Cómo reparar una cadena serializada que ha sido dañada por una longitud de recuento de bytes incorrecta?


96

Estoy usando Hotaru CMS con el complemento Image Upload, obtengo este error si intento adjuntar una imagen a una publicación, de lo contrario no hay error:

unserialize () [function.unserialize]: Error en el desplazamiento

El código infractor (el error apunta a la línea 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; }** 
        }
    }

Datos de la tabla, observe que el bit final tiene la información de la imagen, no soy un experto en PHP, así que me preguntaba qué pensarían ustedes.

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

Editar: creo que encontré el bit de serialización ...

/**
     * 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
Para mí, la solución rápida para esto fue usar base64_encode / decode antes de serializar / unserializar. davidwalsh.name/php-serialize-unserialize-issues
Valentin Despa

1
No sé por qué, pero el mío se resolvió con agregado @,@unserialize($product->des_txtmopscol);
Bhavin Rana

2
Agregar @BhavinRana @no es resolver errores, es silenciar errores - nada en realidad "se arregla" con esa técnica.
mickmackusa

Respuestas:


219

unserialize() [function.unserialize]: Error at offsetfue invalid serialization datadebido a una longitud no válida

Arreglo rapido

Lo que puede hacer es recalculating the lengthde los elementos en una matriz serializada

Sus datos serializados actuales

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

Ejemplo sin recálculo

var_dump(unserialize($data));

Salida

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

Recalcular

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

Salida

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)

Recomendación ... I

En lugar de utilizar este tipo de solución rápida ... le aconsejaré que actualice la pregunta con

  • Cómo está serializando sus datos

  • Cómo lo está guardando ...

================================ EDITAR 1 ================ ===============

El error

El error se generó debido al uso de comillas dobles en "lugar de comillas simples, 'por lo que C:\fakepath\100.pngse convirtió aC:fakepath100.jpg

Para corregir el error

Necesitas cambiar de $h->vars['submitted_data'](nota el chamuscado bastante ')

Reemplazar

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

Con

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

Filtro adicional

También puede agregar este filtro simple antes de llamar a serialize

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

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

Si tiene caracteres UTF, también puede ejecutar

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

Cómo detectar el problema en futuros datos serializados

  findSerializeError ( $data1 ) ;

Salida

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 Función

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

    }

}

Una mejor forma de guardar en la base de datos

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

1
Baba, utilicé tu increíble findSerializeErrorfunción y encontré muchos errores. Por favor, eche un vistazo a mi tema
Max Koretskyi

1
usar base64en el artículo antes de agregarlo a la base de datos ... conservaría el carácter nulo
Baba

1
Esa no es una mejor manera de guardar en la base de datos. Lo es, a menos que desee descuidar por completo el propósito de la base de datos. ¿Cómo va a realizar una búsqueda en un grupo de valores cifrados? Por no hablar de la hinchazón, uf. La codificación adecuada es la respuesta adecuada.
Deji

4
Si usa PHP 5.5, consulte la respuesta de @ r00tAcc3ss. stackoverflow.com/a/21389439/1003020
Vinicius Garcia

5
Si recibe este error "preg_replace (): el modificador / e ya no es compatible, use preg_replace_callback en su lugar" en php7 - esta respuesta funciona stackoverflow.com/a/21389439/2011434
BenB

81

No tengo suficiente reputación para comentar, así que espero que las personas que usan la respuesta "correcta" anterior lo vean:

Desde php 5.5, el modificador / e en preg_replace () ha quedado obsoleto por completo y el preg_match anterior generará un error. La documentación de php recomienda usar preg_match_callback en su lugar.

Encuentre la siguiente solución como alternativa al preg_match propuesto anteriormente.

$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
Esta parece ser la única respuesta en la página que realmente hace un buen uso del primer grupo de captura. Si bien la programación es sensata para realizar solo reemplazos donde el recuento de bytes es realmente incorrecto, esta solución no almacena en caché strlen()y, por lo tanto, realiza llamadas de función redundantes. Personalmente, considero que la adición de una condición en línea es demasiado detallada, pero este fragmento está haciendo cosas buenas por buenas razones.
mickmackusa

3
Me funcionó con la siguiente expresión regular '!s:(\d+):"(.*?)";!s'(con una terminación 's' para tomar nuevas líneas también). Gracias al comentario de adilbo a continuación.
ArnoHolo

13

Hay otra razón por la que unserialize()falló porque colocó incorrectamente datos serializados en la base de datos, consulte la Explicación oficial aquí. Dado que serialize()devuelve datos binarios y variables php no les importa los métodos de codificación, por lo que ponerlos en TEXT, VARCHAR () causará este error.

Solución: almacene los datos serializados en BLOB en su tabla.


Esto resolvió mi problema en Laravel 5. Cambié la definición de columna de string () a binary ().
WNRosenberg

La pregunta del OP no parece tener un problema de tipo de columna mysql. Aparentemente, está dañado por un cálculo incorrecto de bytes en el imagevalor. Su respuesta no corresponde a la pregunta específica del OP. Es posible que desee trasladar su consejo a: stackoverflow.com/q/5544749/2943403
mickmackusa

11

Arreglo rapido

Recalcular la longitud de los elementos en una matriz serializada, pero no use (preg_replace) está en desuso, mejor use preg_replace_callback:

Editar: La nueva versión ahora no solo tiene una longitud incorrecta, sino que también corrige los saltos de línea y cuenta los caracteres correctos con un acento (gracias a mickmackusa )

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

1
¿Cómo esta solución incorrecta tiene 8 votos a favor? Me cierro para pensar cuántas personas habrían copiado y pegado sin saberlo esta frase. [cara triste] Aquí hay una prueba de dos formas en las que este fragmento fallará: 3v4l.org/Cf6Nh Vea mi patrón refinado y reemplazo personalizado @ stackoverflow.com/a/55074706/2943403
mickmackusa

1
Mi solución ya no está en la otra página porque era una solución incorrecta para la cadena serializada dañada catastróficamente. Agregué mi fragmento a esta página y proporcioné una explicación y demostraciones. stackoverflow.com/a/55566407/2943403
mickmackusa

5

Este error se debe a que su juego de caracteres es incorrecto.

Establecer juego de caracteres después de la etiqueta abierta:

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

Y establezca charset utf8 en su base de datos:

mysql_query("SET NAMES 'utf8'");

No veo ninguna indicación en la pregunta publicada del OP que sugiera que la corrupción se debe al juego de caracteres. Gratis para defender su reclamo, pero hasta donde yo sé, alguien actualizó manualmente el imagevalor y no pudo actualizar el recuento de bytes. A menos que se me informe lo contrario, debo asumir que esta respuesta es incorrecta para la pregunta del OP.
mickmackusa

4

Puede reparar la cadena de serialización rota usando la siguiente función, con manejo de caracteres multibyte .

function repairSerializeString($value)
{

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

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

El núcleo de lo que recomienda esta respuesta es simplemente incorrecto y potencialmente dañará cadenas serializadas perfectamente válidas. Este fragmento no se debe usar / confiar.
mickmackusa

@mickmackusa No entiendo tu punto, ¿podrías sugerir la mejor manera de hacerlo? o sugerir editar esta respuesta ..
Rajesh Meniya

Proporcioné una solución correcta aquí: stackoverflow.com/a/55566407/2943403 y expliqué que mb_strlen()es inapropiado porque serialize()almacena el recuento de bytes, no el recuento de caracteres. Editar su respuesta para que sea correcta solo crearía consejos redundantes en la página.
mickmackusa

4

función pública 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
Pardeep Goyal

Esta solución no es adecuada para muchos casos. Supone que todos querrán mutar los valores en la cadena serializada para convertir 2 o más caracteres de espacio en blanco en un espacio literal Y trim()cada subcadena coincidente. Ese solo punto hace que esta solución sea imposible de recomendar. Además, se ahogará con los caracteres de nueva línea y capturará innecesariamente el recuento de bytes preexistente que simplemente se sobrescribirá de todos modos. Finalmente, esta es una "respuesta de solo código" y este tipo de respuestas son de bajo valor, ya que hacen poco para educar / empoderar a los futuros investigadores.
mickmackusa

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

No puede arreglar una cadena de serialización rota usando las expresiones regulares propuestas:

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

Puede reparar la cadena de serialización rota usando la siguiente expresión regular:

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

var_dump(@unserialize($data));

Salida

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 Gracias. Se corrigió un problema con las codificaciones multibyte.
Даниил Путилин

2

los documentos oficiales dicen que debería devolver falso y establecer E_NOTICE

pero como tiene un error, el informe de errores está configurado para ser activado por E_NOTICE

aquí hay una solución para permitirle detectar falso devuelto por unserialize

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

es posible que desee considerar el uso de codificación / decodificación base64

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

base64_encodehizo el truco para mí. En mi caso, estamos pasando serialized datos a través de la línea de comando y parece que algunos caracteres extraños impiden que funcione correctamente.
quickshiftin

base64_encode()no es la solución a la pregunta formulada por el OP. La pregunta / problema del OP trata específicamente del hecho de que (probablemente suceda con un reemplazo inapropiado de subcadena en el "elemento de matriz final" de la cadena serializada) hay un recuento incorrecto de bytes en la cadena serializada. Por favor, solo publique respuestas que traten directamente la pregunta formulada.
mickmackusa

2

La corrupción en esta pregunta se aísla a una sola subcadena al final de la cadena serializada y probablemente fue reemplazada manualmente por alguien que perezosamente quería actualizar el imagenombre del archivo. Este hecho será evidente en mi enlace de demostración a continuación utilizando los datos publicados del OP; en resumen, C:fakepath100.jpgno tiene una longitud de 19, debería ser 17.

Dado que la corrupción de la cadena serializada se limita a un número de recuento de bytes / caracteres incorrecto, lo siguiente hará un buen trabajo al actualizar la cadena dañada con el valor de recuento de bytes correcto.

El siguiente reemplazo basado en expresiones regulares solo será efectivo para remediar los recuentos de bytes, nada más.

Parece que muchas de las publicaciones anteriores solo están copiando y pegando un patrón de expresiones regulares de otra persona. No hay razón para capturar el número de recuento de bytes potencialmente dañado si no se va a utilizar en el reemplazo. Además, agregar el smodificador de patrón es una inclusión razonable en caso de que un valor de cadena contenga nuevas líneas / retornos de línea.

* Para aquellos que no están al tanto del tratamiento de caracteres multibyte con serialización, no deben usar mb_strlen()en la devolución de llamada personalizada porque es el recuento de bytes lo que se almacena, no el recuento de caracteres , vea mi salida ...

Código: ( Demo con datos de OP ) ( Demo con datos de muestra arbitrarios ) ( Demo con reemplazo de condición )

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

Salida:

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 pierna por la madriguera del conejo ... Lo anterior funciona bien incluso si aparecen comillas dobles en un valor de cadena, pero si un valor de cadena contiene ";o algún otro sbustring desgarrador, tendrá que ir un poco más allá e implementar "alternativas". Mi nuevo patrón

comprueba que el líder ses:

  • el comienzo de toda la cadena de entrada o
  • precedido por ;

y comprueba que ";es:

  • al final de toda la cadena de entrada o
  • seguido de }o
  • seguido de una cadena o declaración entera s:oi:

No he probado todas y cada una de las posibilidades; de hecho, no estoy relativamente familiarizado con todas las posibilidades en una cadena serializada porque nunca elijo trabajar con datos serializados, siempre json en aplicaciones modernas. Si hay otros posibles caracteres iniciales o finales, deje un comentario y ampliaré las revisiones.

Fragmento extendido: ( demostración )

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

Salida:

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

Tendrá que modificar el tipo de clasificación ay se utf8_unicode_cisolucionará el problema.


¿Qué carácter específico en los datos de muestra del OP cree que se modificará al cambiar la intercalación a utf8_unicode_ci? Tengo mis dudas sobre este.
mickmackusa

Esto también funcionó para mí (aparte de la respuesta de r00tAcc3ss) ¿alguna palabra de alguien que aclare por qué? Como fondo, tomo datos de una llamada API a una aplicación ResourceSpace, los guardo en una matriz, los serializo y los guardo. Los datos serializados tenían problemas para guardarse, así que tuve que codificarlos manualmente en UTF-8, estaba jugando con la intercalación y el conjunto de caracteres en la base de datos, y finalmente me quedé con la intercalación utf8_general_ci, cuando lo cambié a utf8_unicode_ci, funcionó .
Roberto Becerra

1

En mi caso, estaba almacenando datos serializados en el BLOBcampo de MySQL DB que aparentemente no era lo suficientemente grande como para contener el valor completo y lo truncó. Obviamente, una cadena de este tipo no puede ser anulada.
Una vez convertido ese campo en MEDIUMBLOBel problema se disipó. También puede ser necesario cambiar las opciones de tabla ROW_FORMATa DYNAMICo COMPRESSED.


Yo a, aunque el mío era un TEXTcampo y, como tal, se truncó en 65kb.
Antony

Esta pregunta no sufre truncamiento. La pregunta / problema del OP trata específicamente del hecho de que (probablemente suceda con un reemplazo inapropiado de subcadena en el "elemento de matriz final" de la cadena serializada) hay un recuento incorrecto de bytes en la cadena serializada. Por favor, solo publique respuestas que traten directamente la pregunta formulada.
mickmackusa

1

Después de haber intentado algunas cosas en esta página sin éxito, eché un vistazo a la fuente de la página y comenté que todas las citas en la cadena serializada han sido reemplazadas por entidades html. Decodificar estas entidades ayuda a evitar muchos dolores de cabeza:

$myVar = html_entity_decode($myVar);

Esta pregunta no sufre de entidades codificadas en html en la cadena serializada. La pregunta / problema del OP trata específicamente del hecho de que (probablemente suceda con un reemplazo inapropiado de subcadena en el "elemento de matriz final" de la cadena serializada) hay un recuento incorrecto de bytes en la cadena serializada. Por favor, solo publique respuestas que traten directamente la pregunta formulada.
mickmackusa

@mickmackusa Esta pregunta tiene casi 7 años y mi respuesta ~ 1,5. ¡Sin embargo, es bueno que te involucres tanto!
David

Me encantan las páginas de SO, jóvenes y mayores. Estoy buscando investigadores que no conozcan la diferencia entre una buena respuesta y una no tan buena. Esta página, desafortunadamente, está llena de consejos fuera de tema.
mickmackusa

¡Excelente! Ya hay control de calidad y votación, pero no tengo ninguna razón para detenerte ;-)
David

Oh no, échale un vistazo. Hay respuestas votadas a favor que deben votarse en contra. Demasiadas personas no pueden diferenciar. En esta página, el recuento de votos no es absolutamente ninguna indicación de calidad / idoneidad. No voy a perder el tiempo votando en contra porque mi voto en contra no hará mella en la cuenta. Lo mejor que puedo hacer es dejar comentarios para explicar qué es bueno / malo / feo.
mickmackusa

1

Aquí hay una herramienta en línea para reparar una cadena serializada dañada.

Me gustaría añadir que esto sucede sobre todo debido a una búsqueda y reemplazo realiza sobre la serialización de los datos (DB y especialmente la key length) no se actualiza según el reemplazar y que hace que la "corrupción".

No obstante, la herramienta anterior utiliza la siguiente lógica para corregir los datos de serialización ( copiados desde aquí ).

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

Otra razón de este problema puede ser el tipo de columna de la tabla de sesiones de "carga útil". Si tiene una gran cantidad de datos sobre la sesión, una columna de texto no sería suficiente. Necesitará MEDIUMTEXT o incluso LONGTEXT.


Esta pregunta no sufre truncamiento. La pregunta / problema del OP trata específicamente del hecho de que (probablemente suceda con un reemplazo inapropiado de subcadena en el "elemento de matriz final" de la cadena serializada) hay un recuento incorrecto de bytes en la cadena serializada. Por favor, solo publique respuestas que traten directamente la pregunta formulada.
mickmackusa
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.