PHP несериализованное целое число от 64-битного до 32-битного - PullRequest
1 голос
/ 26 октября 2011

Я пытался десериализовать на 32-битном сервере объект, который был сериализован на 64-битном сервере.Я выделил мою проблему целым числом в объекте.Вот небольшое воспроизведение проблемы.

На 64-разрядной машине:

$i = serialize('20110510134021'); //i:20110510134021;

На 32-разрядной машине:

$i = unserialize('i:20110510134021;');

Выдает ошибку

Notice: unserialize(): Error at offset 0 of 16 bytes

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

Я думаю, что это может быть связано с целочисленным переполнением, но даже на 32-разрядном сервере я могу сделать что-то вроде

$i = 20110510134021;
echo $i;

отлично работаетЯ предполагаю, что целочисленные типы PHP масштабируются до некоторого двойного типа или чего-то в этом роде.Но почему он этого не делает, когда не десериализуется?

Как я могу десериализовать эти объекты?Если я не могу, есть ли способ преобразовать их во что-то еще?Наконец, кто-нибудь написал метод десериализации в самом PHP?Или есть подробности о протоколе?Я мог бы использовать это и иметь специальный регистр для этих целых чисел.

Спасибо.

Примечание: У меня нет доступа к исходным данным, только сериализованный результат.

Ответы [ 3 ]

2 голосов
/ 26 октября 2011

Максимальное целое число в 32-битной системе: 4294967296;$i = 20110510134021; работает, потому что PHP преобразует переменную в удвоенную.

Поэтому замените i на d

$i = unserialize('d:20110510134021;');

Если вы запустите этот скрипт, вы увидите правильное представлениепеременная в вашей системе (d: в 32-битной системе, i: в 64-битной системе):

$int = 20110510134021;
var_dump(serialize($int));
1 голос
/ 26 октября 2011

Как насчет:

$serialized = 'i:20110510134021';

if (preg_match('/i\:([\d]+)/', $serialized, $match))
{
    $unserialized = $match[1];
}
1 голос
/ 26 октября 2011

Простое решение, если вы знаете, что существует вероятность того, что данные, сериализованные на 64-битной системе, будут не сериализованы на 32-битной машине, - это привести их к (удвоению) до сериализации.как двойной, что дает вам больше битов на целое число, чем стандартный 4 байта на целое число (32 бита)

После несериализации просто работайте с этим числом как двойной.В 99% случаев это хорошее решение.Все еще существует вероятность того, что для очень большого числа число битов, выделенных для «реальной» части числа с двойным числом на 32-битной машине, будет недостаточно.Я думаю, что это 56 бит, поэтому максимальное целое число все еще значительно больше, чем 32 бита для типа int.

...