[Moscow.pm] Баг в JSON::XS?
Eugene Ponizovsky
ponizovsky на gmail.com
Пт Янв 30 04:46:47 PST 2015
Приветствую.
Вот еще столкнулся со странным поведением JSON::XS (3.01).
Пытаюсь сериализовать объект, содержащий объекты, используя функцию FREEZE. Один из объектов содержит большое число аргументов (61 пара ключ-значение). При сериализации такого объекта скрипт падает с ошибкой "Segmentation fault" или метод encode() возвращает undef.
Иногда скрипт работает корректно. В этом случае незначительное увеличение кол-ва аргументов или уровня вложенности объектов снова приводит к выше описанному результату.
Cpanel::JSON::XS ведет себя также. Ошибка проявляется на разных машинах и OS (Linux, FreeBSD, OS X).
Пример:
#!/usr/bin/env perl
use 5.010000;
use strict;
use warnings;
use JSON::XS;
my $json_szr = JSON::XS->new();
$json_szr->allow_tags( 1 );
my @foo_params;
for ( 1 .. 61 ) {
push ( @foo_params, "coo$_" => 1 );
}
my $foo1 = Foo->new( @foo_params );
my $foo2 = Foo->new( @foo_params );
my $bar1 = Bar->new(
foo => $foo1,
);
my $bar2 = Bar->new(
foo => $foo2,
bar => $bar1
);
my $bar_json = $json_szr->encode( $bar2 );
if ( defined $bar_json ) {
say $bar_json;
}
package Foo;
####
sub new {
my $class = shift;
my %params = @_;
return bless \%params, $class;
}
####
sub FREEZE {
my $self = shift;
return %{$self};
}
####
sub THAW {
my $class = shift;
my $szr = shift;
return $class->new( @_ );
}
package Bar;
####
sub new {
my $class = shift;
my %params = @_;
return bless \%params, $class;
}
####
sub FREEZE {
my $self = shift;
return %{$self};
}
> 29 нояб. 2014 г., в 10:42, TheAthlete <theathlet на yandex.ru> написал(а):
>
> Согласен, что перекрывает, но здесь JSON::XS создан с методом
> convert_blessed, который говорит, что переданный обхект должен иметь метод
> TO_JSON. Объект модуля boolean имеет данный метод.
>
> $ perl -MData::Printer -MCpanel::JSON::XS -Mboolean=-truth -E '$j =
> Cpanel::JSON::XS->new->convert_blessed; $b = (0 == 1); say
> $j->encode({false => $b}); p$b'
> {"false":false}
> boolean {
> Parents Exporter
> public methods (9) : boolean, false, import, isBoolean, isFalse,
> isTrue, TO_JSON, true, truth
> private methods (1) : __ANON__
> internals: 0
> }
>
> $ perl -MData::Printer -MJSON::XS -Mboolean=-truth -E '$j =
> JSON::XS->new->convert_blessed; $b = (0 == 1); say $j->encode({false =>
> $b}); p $b'
> Modification of a read-only value attempted at -e line 1.
>
> Насколько я понял, эта ошибка связана с приведением к строке булевых
> значений (Boolean stringify) в модуле boolean.
>
> Данная ошибка была скорее всего исправлена в Cpanel::JSON::XS начиная с версии 2.3311 -
> https://github.com/rurban/Cpanel-JSON-XS/commit/a42d7b7ec05c9aad18ba9b0ef12c721c31a47317 <https://github.com/rurban/Cpanel-JSON-XS/commit/a42d7b7ec05c9aad18ba9b0ef12c721c31a47317>
>
> Victor Efimov <victor на vsespb.ru <mailto:victor на vsespb.ru>> писал(а) в своём письме Fri, 28 Nov 2014
> 20:44:50 +0300:
>
>> 28 ноября 2014 г., 18:41 пользователь TheAthlete <theathlet на yandex.ru> написал:
>>> Неделя багов в JSON::XS! :)
>>
>> Почему это баг JSON::XS ?
>>
>> use strict; use warnings;
>> use Test::More tests => 3;
>> use boolean -truth;
>> use JSON::XS;
>> my $json = JSON::XS->new;
>> is($json->encode({"hey" => !!0}), 'abc', 'JSON false works');
>>
>> тоже фейлится. если
>>
>> use boolean -truth;
>>
>> закоментировать, то работает норм.
>>
>> Это потому что опция
>>
>> -truth
>>
>> You can specify the -truth option to override truth operators to
>> return boolean values.
>>
>> use boolean -truth;
>> print ref("hello" eq "world"), "\n";
>>
>>
>> перекрывает операторы Perl, чтобы они возвращали объект. Почему
>> считается что JSON::XS должен с этим работать ? Почему это не баг в
>> "boolean" ?
>>
>>
>>> Тоже столкнулся с багом в JSON::XS - при установке модуля boolean, который
>>> в зависимостях у Test::DBIx::Class, не был пройден тест json.t.
>>> Заглянув в issue данного модуля на github, нашел такой тикет:
>>>
>>> json.t fails on many Linux systems -
>>> https://github.com/ingydotnet/boolean-pm/issues/5
>>>
>>> Там некоторые советуют установить Cpanel::JSON::XS - установил и все
>>> заработало, хотя не у всех падает при установленном JSON::XS.
>>>
>>> Если модифицировать тест:
>>>
>>> use strict; use warnings;
>>> use Test::More tests => 3;
>>> use boolean -truth;
>>> my $HAVE_JSON = eval { require JSON::MaybeXS };
>>> SKIP: {
>>> skip "JSON is missing", 3 unless $HAVE_JSON;
>>> eval{
>>> my $json = JSON::MaybeXS->new->convert_blessed();
>>> is($json->encode({false => (0 == 1)}), '{"false":false}',
>>> 'JSON false works');
>>> is($json->encode({true => (1 == 1)}), '{"true":true}',
>>> 'JSON true works');
>>> is(ref(boolean::TO_JSON(true)), 'SCALAR',
>>> 'Make sure we can call boolean::TO_JSON($b)');
>>> }
>>> };
>>>
>>> в следующий:
>>>
>>> use strict; use warnings;
>>> use Test::More tests => 3;
>>> use boolean -truth;
>>> my $HAVE_JSON = eval { require JSON::XS };
>>> SKIP: {
>>> skip "JSON is missing", 3 unless $HAVE_JSON;
>>> my $json = JSON::XS->new->convert_blessed();
>>> is($json->encode({false => (0 == 1)}), '{"false":false}',
>>> 'JSON false works');
>>> is($json->encode({true => (1 == 1)}), '{"true":true}',
>>> 'JSON true works');
>>> is(ref(boolean::TO_JSON(true)), 'SCALAR',
>>> 'Make sure we can call boolean::TO_JSON($b)');
>>> };
>>>
>>> и запустить, то тест сваливается с ошибкой "Modification of a read-only
>>> value attempted at test/json.t line 9"
>>>
>>> Если заменить на Cpanel::JSON::XS или JSON::PP, то все ок
>>>
>>> Вадим Власов <scripter.vrn на gmail.com> писал(а) в своём письме Wed, 26 Nov
>>> 2014 20:01:33 +0300:
>>>
>>>> Исследуя новый сериализатор в JSON::XS наткнулся:
>>>>
>>>> $ echo 'use strict;
>>>> use warnings;
>>>> use feature "say";
>>>>
>>>> use JSON::XS;
>>>> my $j=JSON::XS->new->allow_tags;
>>>>
>>>> say "JSON::XS: $JSON::XS::VERSION";
>>>> say "Types::Serialiser: $Types::Serialiser::VERSION";
>>>>
>>>> my $t = $j->encode( Foo->new );
>>>> say $t;
>>>>
>>>> my @t = $j->encode( Foo->new );
>>>>
>>>> package Foo;
>>>> sub new { bless {}, $_[0]; }
>>>> sub FREEZE { ( 123, 456 ); }' | perl
>>>> *JSON::XS: 3.01*
>>>> *Types::Serialiser: 1.0*
>>>> *("Foo")[123,456]*
>>>> *panic: attempt to copy freed scalar c37a18 to c37a00 at - line 14.*
>>>>
>>>> $ perl -MJSON::XS -wE 'say JSON::XS->new->allow_tags->encode( bless {},
>>>> Foo
>>>> ); package Foo; sub FREEZE{ return 123 }'
>>>> *Use of uninitialized value in say at -e line 1.*
>>>> *("Foo")[123]*
>>>>
>>>> $ perl -MJSON::XS -wE 'say scalar( JSON::XS->new->allow_tags->encode(
>>>> bless
>>>> {}, Foo )); package Foo; sub FREEZE{ return 123 }'
>>>> *("Foo")[123]*
>>>>
>>>> Проверили на разных машинах и на разных версиях perl-а - одно и то же.
>>>>
>>>
>>>
>>> --
>>> Написано в почтовом клиенте браузера Opera: http://www.opera.com/mail/
>>>
>>> --
>>> Moscow.pm mailing list
>>> moscow-pm на pm.org | http://moscow.pm.org
>
>
> --
> Написано в почтовом клиенте браузера Opera: http://www.opera.com/mail/ <http://www.opera.com/mail/>
> --
> Moscow.pm mailing list
> moscow-pm на pm.org <mailto:moscow-pm на pm.org> | http://moscow.pm.org <http://moscow.pm.org/>
----------- следущая часть -----------
Вложение в формате HTML было извлечено…
URL: <http://mail.pm.org/pipermail/moscow-pm/attachments/20150130/44bb720e/attachment-0001.html>
Подробная информация о списке рассылки Moscow-pm