diff options
author | Kenichi Ishigaki <ishigaki@cpan.org> | 2022-06-27 14:33:15 +0000 |
---|---|---|
committer | James E Keenan <jkeenan@cpan.org> | 2022-06-27 14:33:15 +0000 |
commit | 602e63aa36686ad5cfa326a1b2f20721af9b1ce0 (patch) | |
tree | 905095e58c83adf59922f2c6dc779e772debfa62 | |
parent | 36540e72e5ebd2d98e8833f34b1b25b20553e7cd (diff) | |
download | perl-602e63aa36686ad5cfa326a1b2f20721af9b1ce0.tar.gz |
JSON-PP: Sync with CPAN version 4.10
From Changes:
4.10 2022-06-24
- fix a regression of decode_error introduced at 4.08 (GH#75, reported by andk++)
- convert all tests to use Test::More (GH#70, haarg++)
4.09 2022-05-22
- reverted core boolean support for now (GH#72)
- incr_parse() Hangs on Certain Inputs (GH#67, DabeDotCom++)
- silence warnings about non-characters on older perls (GH#68, haarg++)
4.08 2022-04-10
- remove unneeded utf8::upgrade and downgrade (GH#59, FGasper++)
- core boolean support (GH#62, 63, haarg++)
- EBCDIC support (GH#64, khwilliamson++)
- shorten a test name (GH#65, khwilliamson)
-rw-r--r-- | MANIFEST | 3 | ||||
-rw-r--r-- | META.json | 2 | ||||
-rwxr-xr-x | Porting/Maintainers.pl | 2 | ||||
-rw-r--r-- | cpan/JSON-PP/lib/JSON/PP.pm | 148 | ||||
-rw-r--r-- | cpan/JSON-PP/lib/JSON/PP/Boolean.pm | 2 | ||||
-rw-r--r-- | cpan/JSON-PP/t/001_utf8.t | 28 | ||||
-rw-r--r-- | cpan/JSON-PP/t/004_dwiw_encode.t | 4 | ||||
-rw-r--r-- | cpan/JSON-PP/t/005_dwiw_decode.t | 4 | ||||
-rw-r--r-- | cpan/JSON-PP/t/008_pc_base.t | 2 | ||||
-rw-r--r-- | cpan/JSON-PP/t/014_latin1.t | 8 | ||||
-rw-r--r-- | cpan/JSON-PP/t/105_esc_slash.t | 2 | ||||
-rw-r--r-- | cpan/JSON-PP/t/106_allow_barekey.t | 2 | ||||
-rw-r--r-- | cpan/JSON-PP/t/107_allow_singlequote.t | 2 | ||||
-rw-r--r-- | cpan/JSON-PP/t/108_decode.t | 17 | ||||
-rw-r--r-- | cpan/JSON-PP/t/109_encode.t | 36 | ||||
-rw-r--r-- | cpan/JSON-PP/t/112_upgrade.t | 8 | ||||
-rw-r--r-- | cpan/JSON-PP/t/119_incr_parse_utf8.t | 75 | ||||
-rw-r--r-- | cpan/JSON-PP/t/120_incr_parse_truncated.t | 218 | ||||
-rw-r--r-- | cpan/JSON-PP/t/rt_122270_old_xs_boolean.t | 33 |
19 files changed, 495 insertions, 101 deletions
@@ -1302,9 +1302,12 @@ cpan/JSON-PP/t/115_tie_ixhash.t cpan/JSON-PP/t/116_incr_parse_fixed.t cpan/JSON-PP/t/117_numbers.t cpan/JSON-PP/t/118_boolean_values.t +cpan/JSON-PP/t/119_incr_parse_utf8.t +cpan/JSON-PP/t/120_incr_parse_truncated.t cpan/JSON-PP/t/gh_28_json_test_suite.t cpan/JSON-PP/t/gh_29_trailing_false_value.t cpan/JSON-PP/t/rt_116998_wrong_character_offset.t +cpan/JSON-PP/t/rt_122270_old_xs_boolean.t cpan/JSON-PP/t/rt_90071_incr_parse.t cpan/JSON-PP/t/zero-mojibake.t cpan/libnet/lib/Net/Cmd.pm @@ -119,5 +119,5 @@ } }, "version" : "5.037002", - "x_serialization_backend" : "JSON::PP version 4.07" + "x_serialization_backend" : "JSON::PP version 4.10" } diff --git a/Porting/Maintainers.pl b/Porting/Maintainers.pl index 5460ef6884..ca869eadb8 100755 --- a/Porting/Maintainers.pl +++ b/Porting/Maintainers.pl @@ -680,7 +680,7 @@ use File::Glob qw(:case); }, 'JSON::PP' => { - 'DISTRIBUTION' => 'ISHIGAKI/JSON-PP-4.07.tar.gz', + 'DISTRIBUTION' => 'ISHIGAKI/JSON-PP-4.10.tar.gz', 'FILES' => q[cpan/JSON-PP], }, diff --git a/cpan/JSON-PP/lib/JSON/PP.pm b/cpan/JSON-PP/lib/JSON/PP.pm index ff23fc7c0f..e34b927898 100644 --- a/cpan/JSON-PP/lib/JSON/PP.pm +++ b/cpan/JSON-PP/lib/JSON/PP.pm @@ -14,7 +14,7 @@ use JSON::PP::Boolean; use Carp (); #use Devel::Peek; -$JSON::PP::VERSION = '4.07'; +$JSON::PP::VERSION = '4.10'; @JSON::PP::EXPORT = qw(encode_json decode_json from_json to_json); @@ -47,6 +47,17 @@ use constant P_ALLOW_TAGS => 19; use constant OLD_PERL => $] < 5.008 ? 1 : 0; use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0; +my $invalid_char_re; + +BEGIN { + $invalid_char_re = "["; + for my $i (0 .. 0x01F, 0x22, 0x5c) { # '/' is ok + $invalid_char_re .= quotemeta chr utf8::unicode_to_native($i); + } + + $invalid_char_re = qr/$invalid_char_re]/; +} + BEGIN { if (USE_B) { require B; @@ -326,14 +337,6 @@ sub allow_bigint { $str .= "\n" if ( $indent ); # JSON::XS 2.26 compatible - unless ($ascii or $latin1 or $utf8) { - utf8::upgrade($str); - } - - if ($props->[ P_SHRINK ]) { - utf8::downgrade($str, 1); - } - return $str; } @@ -527,9 +530,11 @@ sub allow_bigint { sub string_to_json { my ($self, $arg) = @_; - $arg =~ s/([\x22\x5c\n\r\t\f\b])/$esc{$1}/g; + $arg =~ s/(["\\\n\r\t\f\b])/$esc{$1}/g; $arg =~ s/\//\\\//g if ($escape_slash); - $arg =~ s/([\x00-\x08\x0b\x0e-\x1f])/'\\u00' . unpack('H2', $1)/eg; + + # On ASCII platforms, matches [\x00-\x08\x0b\x0e-\x1f] + $arg =~ s/([^\n\t\c?[:^cntrl:][:^ascii:]])/'\\u00' . unpack('H2', $1)/eg; if ($ascii) { $arg = JSON_PP_encode_ascii($arg); @@ -604,7 +609,7 @@ sub allow_bigint { sub _encode_ascii { join('', map { - $_ <= 127 ? + chr($_) =~ /[[:ascii:]]/ ? chr($_) : $_ <= 65535 ? sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_)); @@ -658,11 +663,11 @@ BEGIN { { # PARSE my %escapes = ( # by Jeremy Muhlich <jmuhlich [at] bitflood.org> - b => "\x8", - t => "\x9", - n => "\xA", - f => "\xC", - r => "\xD", + b => "\b", + t => "\t", + n => "\n", + f => "\f", + r => "\r", '\\' => '\\', '"' => '"', '/' => '/', @@ -736,7 +741,6 @@ BEGIN { } } else { - utf8::upgrade( $text ); utf8::encode( $text ); } @@ -853,7 +857,8 @@ BEGIN { decode_error("surrogate pair expected"); } - if ( ( my $hex = hex( $u ) ) > 127 ) { + my $hex = hex( $u ); + if ( chr $u =~ /[[:^ascii:]]/ ) { $is_utf8 = 1; $s .= JSON_PP_decode_unicode($u) || next; } @@ -873,7 +878,7 @@ BEGIN { } else{ - if ( ord $ch > 127 ) { + if ( $ch =~ /[[:^ascii:]]/ ) { unless( $ch = is_valid_utf8($ch) ) { $at -= 1; decode_error("malformed UTF-8 character in JSON string"); @@ -886,10 +891,12 @@ BEGIN { } if (!$loose) { - if ($ch =~ /[\x00-\x1f\x22\x5c]/) { # '/' ok + if ($ch =~ $invalid_char_re) { # '/' ok if (!$relaxed or $ch ne "\t") { $at--; - decode_error('invalid character encountered while parsing JSON string'); + decode_error(sprintf "invalid character 0x%X" + . " encountered while parsing JSON string", + ord $ch); } } } @@ -1102,7 +1109,7 @@ BEGIN { sub bareKey { # doesn't strictly follow Standard ECMA-262 3rd Edition my $key; - while($ch =~ /[^\x00-\x23\x25-\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]/){ + while($ch =~ /[\$\w[:^ascii:]]/){ $key .= $ch; next_chr(); } @@ -1235,31 +1242,55 @@ BEGIN { return $is_dec ? $v/1.0 : 0+$v; } + # Compute how many bytes are in the longest legal official Unicode + # character + my $max_unicode_length = do { + BEGIN { $] >= 5.006 and require warnings and warnings->unimport('utf8') } + chr 0x10FFFF; + }; + utf8::encode($max_unicode_length); + $max_unicode_length = length $max_unicode_length; sub is_valid_utf8 { - $utf8_len = $_[0] =~ /[\x00-\x7F]/ ? 1 - : $_[0] =~ /[\xC2-\xDF]/ ? 2 - : $_[0] =~ /[\xE0-\xEF]/ ? 3 - : $_[0] =~ /[\xF0-\xF4]/ ? 4 - : 0 - ; - - return unless $utf8_len; - - my $is_valid_utf8 = substr($text, $at - 1, $utf8_len); - - return ( $is_valid_utf8 =~ /^(?: - [\x00-\x7F] - |[\xC2-\xDF][\x80-\xBF] - |[\xE0][\xA0-\xBF][\x80-\xBF] - |[\xE1-\xEC][\x80-\xBF][\x80-\xBF] - |[\xED][\x80-\x9F][\x80-\xBF] - |[\xEE-\xEF][\x80-\xBF][\x80-\xBF] - |[\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF] - |[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF] - |[\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF] - )$/x ) ? $is_valid_utf8 : ''; + # Returns undef (setting $utf8_len to 0) unless the next bytes in $text + # comprise a well-formed UTF-8 encoded character, in which case, + # return those bytes, setting $utf8_len to their count. + + my $start_point = substr($text, $at - 1); + + # Look no further than the maximum number of bytes in a single + # character + my $limit = $max_unicode_length; + $limit = length($start_point) if $limit > length($start_point); + + # Find the number of bytes comprising the first character in $text + # (without having to know the details of its internal representation). + # This loop will iterate just once on well-formed input. + while ($limit > 0) { # Until we succeed or exhaust the input + my $copy = substr($start_point, 0, $limit); + + # decode() will return true if all bytes are valid; false + # if any aren't. + if (utf8::decode($copy)) { + + # Is valid: get the first character, convert back to bytes, + # and return those bytes. + $copy = substr($copy, 0, 1); + utf8::encode($copy); + $utf8_len = length $copy; + return substr($start_point, 0, $utf8_len); + } + + # If it didn't work, it could be that there is a full legal character + # followed by a partial or malformed one. Narrow the window and + # try again. + $limit--; + } + + # Failed to find a legal UTF-8 character. + $utf8_len = 0; + return; } @@ -1278,14 +1309,14 @@ BEGIN { } for my $c ( unpack( $type, $str ) ) { # emulate pv_uni_display() ? - $mess .= $c == 0x07 ? '\a' - : $c == 0x09 ? '\t' - : $c == 0x0a ? '\n' - : $c == 0x0d ? '\r' - : $c == 0x0c ? '\f' - : $c < 0x20 ? sprintf('\x{%x}', $c) - : $c == 0x5c ? '\\\\' - : $c < 0x80 ? chr($c) + my $chr_c = chr($c); + $mess .= $chr_c eq '\\' ? '\\\\' + : $chr_c =~ /[[:print:]]/ ? $chr_c + : $chr_c eq '\a' ? '\a' + : $chr_c eq '\t' ? '\t' + : $chr_c eq '\n' ? '\n' + : $chr_c eq '\r' ? '\r' + : $chr_c eq '\f' ? '\f' : sprintf('\x{%x}', $c) ; if ( length $mess >= 20 ) { @@ -1534,10 +1565,6 @@ sub incr_parse { $self->{incr_text} = '' unless ( defined $self->{incr_text} ); if ( defined $text ) { - if ( utf8::is_utf8( $text ) and !utf8::is_utf8( $self->{incr_text} ) ) { - utf8::upgrade( $self->{incr_text} ) ; - utf8::decode( $self->{incr_text} ) ; - } $self->{incr_text} .= $text; } @@ -1564,7 +1591,6 @@ sub incr_parse { } unless ( $coder->get_utf8 ) { - utf8::upgrade( $self->{incr_text} ); utf8::decode( $self->{incr_text} ); } @@ -1605,7 +1631,7 @@ INCR_PARSE: while ( $len > $p ) { $s = substr( $text, $p, 1 ); last INCR_PARSE unless defined $s; - if ( ord($s) > 0x20 ) { + if ( ord($s) > ord " " ) { if ( $s eq '#' ) { $self->{incr_mode} = INCR_M_C0; redo INCR_PARSE; @@ -1632,6 +1658,7 @@ INCR_PARSE: } next; } elsif ( $mode == INCR_M_TFN ) { + last INCR_PARSE if $p >= $len && $self->{incr_nest}; while ( $len > $p ) { $s = substr( $text, $p++, 1 ); next if defined $s and $s =~ /[rueals]/; @@ -1643,6 +1670,7 @@ INCR_PARSE: last INCR_PARSE unless $self->{incr_nest}; redo INCR_PARSE; } elsif ( $mode == INCR_M_NUM ) { + last INCR_PARSE if $p >= $len && $self->{incr_nest}; while ( $len > $p ) { $s = substr( $text, $p++, 1 ); next if defined $s and $s =~ /[0-9eE.+\-]/; @@ -1679,7 +1707,7 @@ INCR_PARSE: if ( $s eq "\x00" ) { $p--; last INCR_PARSE; - } elsif ( $s eq "\x09" or $s eq "\x0a" or $s eq "\x0d" or $s eq "\x20" ) { + } elsif ( $s =~ /^[\t\n\r ]$/) { if ( !$self->{incr_nest} ) { $p--; # do not eat the whitespace, let the next round do it last INCR_PARSE; diff --git a/cpan/JSON-PP/lib/JSON/PP/Boolean.pm b/cpan/JSON-PP/lib/JSON/PP/Boolean.pm index d1ee0a477c..23e71d6e41 100644 --- a/cpan/JSON-PP/lib/JSON/PP/Boolean.pm +++ b/cpan/JSON-PP/lib/JSON/PP/Boolean.pm @@ -10,7 +10,7 @@ overload::import('overload', fallback => 1, ); -$JSON::PP::Boolean::VERSION = '4.07'; +$JSON::PP::Boolean::VERSION = '4.10'; 1; diff --git a/cpan/JSON-PP/t/001_utf8.t b/cpan/JSON-PP/t/001_utf8.t index e160f82416..4044e44690 100644 --- a/cpan/JSON-PP/t/001_utf8.t +++ b/cpan/JSON-PP/t/001_utf8.t @@ -10,17 +10,23 @@ BEGIN { $ENV{PERL_JSON_BACKEND} = 0; } use utf8; use JSON::PP; - -ok (JSON::PP->new->allow_nonref (1)->utf8 (1)->encode ("ü") eq "\"\xc3\xbc\""); -ok (JSON::PP->new->allow_nonref (1)->encode ("ü") eq "\"ü\""); -ok (JSON::PP->new->allow_nonref (1)->ascii (1)->utf8 (1)->encode (chr 0x8000) eq '"\u8000"'); -ok (JSON::PP->new->allow_nonref (1)->ascii (1)->utf8 (1)->pretty (1)->encode (chr 0x10402) eq "\"\\ud801\\udc02\"\n"); - -eval { JSON::PP->new->allow_nonref (1)->utf8 (1)->decode ('"ü"') }; +my $pilcrow_utf8 = (ord "^" == 0x5E) ? "\xc2\xb6" # 8859-1 + : (ord "^" == 0x5F) ? "\x80\x65" # CP 1024 + : "\x78\x64"; # assume CP 037 +is (JSON::PP->new->allow_nonref (1)->utf8 (1)->encode ("¶"), "\"$pilcrow_utf8\""); +is (JSON::PP->new->allow_nonref (1)->encode ("¶"), "\"¶\""); +is (JSON::PP->new->allow_nonref (1)->ascii (1)->utf8 (1)->encode (chr 0x8000), '"\u8000"'); +is (JSON::PP->new->allow_nonref (1)->ascii (1)->utf8 (1)->pretty (1)->encode (chr 0x10402), "\"\\ud801\\udc02\"\n"); + +eval { JSON::PP->new->allow_nonref (1)->utf8 (1)->decode ('"¶"') }; ok $@ =~ /malformed UTF-8/; -ok (JSON::PP->new->allow_nonref (1)->decode ('"ü"') eq "ü"); -ok (JSON::PP->new->allow_nonref (1)->decode ('"\u00fc"') eq "ü"); -ok (JSON::PP->new->allow_nonref (1)->decode ('"\ud801\udc02' . "\x{10204}\"") eq "\x{10402}\x{10204}"); -ok (JSON::PP->new->allow_nonref (1)->decode ('"\"\n\\\\\r\t\f\b"') eq "\"\012\\\015\011\014\010"); +is (JSON::PP->new->allow_nonref (1)->decode ('"¶"'), "¶"); +is (JSON::PP->new->allow_nonref (1)->decode ('"\u00b6"'), "¶"); +is (JSON::PP->new->allow_nonref (1)->decode ('"\ud801\udc02' . "\x{10204}\""), "\x{10402}\x{10204}"); + +my $controls = (ord "^" == 0x5E) ? "\012\\\015\011\014\010" + : (ord "^" == 0x5F) ? "\025\\\015\005\014\026" # CP 1024 + : "\045\\\015\005\014\026"; # assume CP 037 +is (JSON::PP->new->allow_nonref (1)->decode ('"\"\n\\\\\r\t\f\b"'), "\"$controls"); diff --git a/cpan/JSON-PP/t/004_dwiw_encode.t b/cpan/JSON-PP/t/004_dwiw_encode.t index 32e4500fee..f413e87650 100644 --- a/cpan/JSON-PP/t/004_dwiw_encode.t +++ b/cpan/JSON-PP/t/004_dwiw_encode.t @@ -7,12 +7,10 @@ use strict; use warnings; -use Test; +use Test::More tests => 5; # main { - BEGIN { plan tests => 5 } - BEGIN { $ENV{PERL_JSON_BACKEND} = 0; } use JSON::PP; diff --git a/cpan/JSON-PP/t/005_dwiw_decode.t b/cpan/JSON-PP/t/005_dwiw_decode.t index 9bfe2fd07e..ab195ad425 100644 --- a/cpan/JSON-PP/t/005_dwiw_decode.t +++ b/cpan/JSON-PP/t/005_dwiw_decode.t @@ -7,12 +7,10 @@ use strict; use warnings; -use Test; +use Test::More tests => 7; # main { - BEGIN { plan tests => 7 } - BEGIN { $ENV{PERL_JSON_BACKEND} = 0; } use JSON::PP; diff --git a/cpan/JSON-PP/t/008_pc_base.t b/cpan/JSON-PP/t/008_pc_base.t index 762edfd965..e717baefbe 100644 --- a/cpan/JSON-PP/t/008_pc_base.t +++ b/cpan/JSON-PP/t/008_pc_base.t @@ -77,7 +77,7 @@ $obj = $pc->decode($js); is($obj->[0],"\x01"); $obj = ["\e"]; -is($js = $pc->encode($obj),'["\\u001b"]'); +is($js = $pc->encode($obj), (ord("A") == 65) ? '["\\u001b"]' : '["\\u0027"]'); $obj = $pc->decode($js); is($obj->[0],"\e"); diff --git a/cpan/JSON-PP/t/014_latin1.t b/cpan/JSON-PP/t/014_latin1.t index 7030db8637..cef90580f1 100644 --- a/cpan/JSON-PP/t/014_latin1.t +++ b/cpan/JSON-PP/t/014_latin1.t @@ -11,9 +11,9 @@ use JSON::PP; my $pp = JSON::PP->new->latin1->allow_nonref; -ok ($pp->encode ("\x{12}\x{89} ") eq "\"\\u0012\x{89} \""); -ok ($pp->encode ("\x{12}\x{89}\x{abc}") eq "\"\\u0012\x{89}\\u0abc\""); +ok ($pp->encode ("\x{12}\x{b6} ") eq "\"\\u0012\x{b6} \""); +ok ($pp->encode ("\x{12}\x{b6}\x{abc}") eq "\"\\u0012\x{b6}\\u0abc\""); -ok ($pp->decode ("\"\\u0012\x{89}\"" ) eq "\x{12}\x{89}"); -ok ($pp->decode ("\"\\u0012\x{89}\\u0abc\"") eq "\x{12}\x{89}\x{abc}"); +ok ($pp->decode ("\"\\u0012\x{b6}\"" ) eq "\x{12}\x{b6}"); +ok ($pp->decode ("\"\\u0012\x{b6}\\u0abc\"") eq "\x{12}\x{b6}\x{abc}"); diff --git a/cpan/JSON-PP/t/105_esc_slash.t b/cpan/JSON-PP/t/105_esc_slash.t index ae2d7d207b..56f415cf02 100644 --- a/cpan/JSON-PP/t/105_esc_slash.t +++ b/cpan/JSON-PP/t/105_esc_slash.t @@ -1,6 +1,6 @@ use Test::More;
-use strict;
+use strict; use warnings;
BEGIN { plan tests => 2 };
BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
diff --git a/cpan/JSON-PP/t/106_allow_barekey.t b/cpan/JSON-PP/t/106_allow_barekey.t index f5c9189346..20918bbdc2 100644 --- a/cpan/JSON-PP/t/106_allow_barekey.t +++ b/cpan/JSON-PP/t/106_allow_barekey.t @@ -1,6 +1,6 @@ use Test::More;
-use strict;
+use strict; use warnings;
BEGIN { plan tests => 2 };
BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
diff --git a/cpan/JSON-PP/t/107_allow_singlequote.t b/cpan/JSON-PP/t/107_allow_singlequote.t index 5948f41841..b3462f9775 100644 --- a/cpan/JSON-PP/t/107_allow_singlequote.t +++ b/cpan/JSON-PP/t/107_allow_singlequote.t @@ -1,6 +1,6 @@ use Test::More;
-use strict;
+use strict; use warnings;
BEGIN { plan tests => 4 };
BEGIN { $ENV{PERL_JSON_BACKEND} = 0; }
diff --git a/cpan/JSON-PP/t/108_decode.t b/cpan/JSON-PP/t/108_decode.t index e0cec29015..3282c853ad 100644 --- a/cpan/JSON-PP/t/108_decode.t +++ b/cpan/JSON-PP/t/108_decode.t @@ -5,10 +5,12 @@ use strict; use warnings; use Test::More; -BEGIN { plan tests => 6 }; +BEGIN { plan tests => 7 }; BEGIN { $ENV{PERL_JSON_BACKEND} = 0; } +my $isASCII = ord "A" == 65; + use JSON::PP; no utf8; @@ -22,16 +24,23 @@ is($json->decode(q|"\u00c3\u00bc"|), "\xc3\xbc"); # utf8 my $str = 'あ'; # Japanese 'a' in utf8 -is($json->decode(q|"\u00e3\u0081\u0082"|), $str); +is($json->decode(($isASCII) ? q|"\u00e3\u0081\u0082"| + : q|"\u00ce\u0043\u0043"|), + $str); utf8::decode($str); # usually UTF-8 flagged on, but no-op for 5.005. is($json->decode(q|"\u3042"|), $str); -my $utf8 = $json->decode(q|"\ud808\udf45"|); # chr 12345 +# chr 0x12400, which was chosen because it has the same representation in +# both EBCDIC 1047 and 037 +my $utf8 = $json->decode(q|"\ud809\udc00"|); utf8::encode($utf8); # UTF-8 flagged off -is($utf8, "\xf0\x92\x8d\x85"); +is($utf8, ($isASCII) ? "\xf0\x92\x90\x80" : "\xDE\x4A\x41\x41"); +eval { $json->decode(q|{"action":"foo" "method":"bar","tid":1}|) }; +my $error = $@; +like $error => qr!""method":"bar","tid"..."!; diff --git a/cpan/JSON-PP/t/109_encode.t b/cpan/JSON-PP/t/109_encode.t index 95f7764ff2..322425ff7d 100644 --- a/cpan/JSON-PP/t/109_encode.t +++ b/cpan/JSON-PP/t/109_encode.t @@ -9,20 +9,46 @@ BEGIN { plan tests => 7 }; BEGIN { $ENV{PERL_JSON_BACKEND} = 0; } +my $isASCII = ord "A" == 65; + use JSON::PP; no utf8; my $json = JSON::PP->new->allow_nonref; -is($json->encode("ü"), q|"ü"|); # as is +# U+00B6 chosen because it works on both ASCII and EBCDIC +is($json->encode("¶"), q|"¶"|); # as is $json->ascii; -is($json->encode("\xfc"), q|"\u00fc"|); # latin1 -is($json->encode("\xc3\xbc"), q|"\u00c3\u00bc"|); # utf8 -is($json->encode("ü"), q|"\u00c3\u00bc"|); # utf8 -is($json->encode('あ'), q|"\u00e3\u0081\u0082"|); +if ($] < 5.008) { + is($json->encode("\xb6"), q|"\u00b6"|); # latin1 + is($json->encode("\xc2\xb6"), q|"\u00c2\u00b6"|); # utf8 + is($json->encode("¶"), q|"\u00c2\u00b6"|); # utf8 + is($json->encode('あ'), q|"\u00e3\u0081\u0082"|); +} +else { + is($json->encode("\xb6"), q|"\u00b6"|); # latin1 + + if (ord "A" == 65) { + is($json->encode("\xc2\xb6"), q|"\u00c2\u00b6"|); # utf8 + is($json->encode("¶"), q|"\u00c2\u00b6"|); # utf8 + is($json->encode('あ'), q|"\u00e3\u0081\u0082"|); + } + else { + if (ord '^' == 95) { # EBCDIC 1047 + is($json->encode("\x80\x65"), q|"\u0080\u0065"|); # utf8 + is($json->encode("¶"), q|"\u0080\u0065"|); # utf8 + } + else { # Assume EBCDIC 037 + is($json->encode("\x78\x64"), q|"\u0078\u0064"|); # utf8 + is($json->encode("¶"), q|"\u0078\u0064"|); # utf8 + } + + is($json->encode('あ'), (q|"\u00ce\u0043\u0043"|)); + } +} if ($] >= 5.006) { is($json->encode(chr hex 3042 ), q|"\u3042"|); diff --git a/cpan/JSON-PP/t/112_upgrade.t b/cpan/JSON-PP/t/112_upgrade.t index 853439a174..681ce67f65 100644 --- a/cpan/JSON-PP/t/112_upgrade.t +++ b/cpan/JSON-PP/t/112_upgrade.t @@ -9,17 +9,17 @@ BEGIN { $ENV{PERL_JSON_BACKEND} = 0; } use JSON::PP; my $json = JSON::PP->new->allow_nonref->utf8; -my $str = '\\u00c8'; +my $str = '\\u00b6'; -my $value = $json->decode( '"\\u00c8"' ); +my $value = $json->decode( '"\\u00b6"' ); #use Devel::Peek; #Dump( $value ); -is( $value, chr 0xc8 ); +is( $value, chr 0xb6 ); ok( utf8::is_utf8( $value ) ); -eval { $json->decode( '"' . chr(0xc8) . '"' ) }; +eval { $json->decode( '"' . chr(0xb6) . '"' ) }; ok( $@ =~ /malformed UTF-8 character in JSON string/ ); diff --git a/cpan/JSON-PP/t/119_incr_parse_utf8.t b/cpan/JSON-PP/t/119_incr_parse_utf8.t new file mode 100644 index 0000000000..90916fbbe2 --- /dev/null +++ b/cpan/JSON-PP/t/119_incr_parse_utf8.t @@ -0,0 +1,75 @@ +use strict; +use warnings; +use Test::More tests => 24; + +use utf8; +use JSON::PP; +use Encode; +use charnames qw< :full >; + +use vars qw< @vs >; + +############################################################ +### These first tests mimic the ones in `t/001_utf8.t` ### +############################################################ + +scalar eval { JSON::PP->new->allow_nonref (1)->utf8 (1)->incr_parse ('"ü"') }; +like $@, qr/malformed UTF-8/; + +ok (JSON::PP->new->allow_nonref (1)->incr_parse ('"ü"') eq "ü"); +ok (JSON::PP->new->allow_nonref (1)->incr_parse ('"\u00fc"') eq "ü"); +ok (JSON::PP->new->allow_nonref (1)->incr_parse ('"\ud801\udc02' . "\x{10204}\"") eq "\x{10402}\x{10204}"); +ok (JSON::PP->new->allow_nonref (1)->incr_parse ('"\"\n\\\\\r\t\f\b"') eq "\"\012\\\015\011\014\010"); + + +my $JSON_TXT = <<JSON_TXT; +{ "a": "1" } +{ "b": "\N{BULLET}" } +{ "c": "3" } +JSON_TXT + +####################### +### With '->utf8' ### +####################### + +@vs = eval { JSON::PP->new->utf8->incr_parse( $JSON_TXT ) }; +like $@, qr/Wide character in subroutine entry/; + + +@vs = eval { JSON::PP->new->utf8->incr_parse( encode 'UTF-8' => $JSON_TXT ) }; + +ok( !$@ ); +ok( scalar @vs == 3 ); + +is_deeply( \@vs, [ { a => "1" }, { b => "\N{BULLET}" }, { c => "3" } ] ); +is_deeply( $vs[0], { a => "1" } ); +is_deeply( $vs[1], { b => "\N{BULLET}" } ); +is_deeply( $vs[2], { c => "3" } ); + + +# Double-Encoded => "You Get What You Ask For" + +@vs = eval { JSON::PP->new->utf8->incr_parse( encode 'UTF-8' => ( encode 'UTF-8' => $JSON_TXT ) ) }; + +ok( !$@ ); +ok( scalar @vs == 3 ); + +is_deeply( \@vs, [ { a => "1" }, { b => "\x{E2}\x{80}\x{A2}" }, { c => "3" } ] ); +is_deeply( $vs[0], { a => "1" } ); +is_deeply( $vs[1], { b => "\x{E2}\x{80}\x{A2}" } ); +is_deeply( $vs[2], { c => "3" } ); + + +########################## +### Without '->utf8' ### +########################## + +@vs = eval { JSON::PP->new->incr_parse( $JSON_TXT ) }; + +ok( !$@ ); +ok( scalar @vs == 3 ); + +is_deeply( \@vs, [ { a => "1" }, { b => "\N{BULLET}" }, { c => "3" } ] ); +is_deeply( $vs[0], { a => "1" } ); +is_deeply( $vs[1], { b => "\N{BULLET}" } ); +is_deeply( $vs[2], { c => "3" } ); diff --git a/cpan/JSON-PP/t/120_incr_parse_truncated.t b/cpan/JSON-PP/t/120_incr_parse_truncated.t new file mode 100644 index 0000000000..ea37ee46c2 --- /dev/null +++ b/cpan/JSON-PP/t/120_incr_parse_truncated.t @@ -0,0 +1,218 @@ +use strict; +use warnings; +use Test::More; +use JSON::PP; + +plan tests => 19 * 3 + 1 * 6; + +sub run_test { + my ($input, $sub) = @_; + $sub->($input); +} + +run_test('{"one": 1}', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok ($res, "curly braces okay -- '$input'"); + ok (!$e, "no error -- '$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error"); +}); + +run_test('{"one": 1]', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "unbalanced curly braces -- '$input'"); + ok ($e, "got error -- '$input'"); + like ($e, qr/, or \} expected while parsing object\/hash/, "'} expected' json string error"); +}); + +run_test('"', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); +}); + +run_test('{', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); +}); + +run_test('[', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); +}); + +run_test('}', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok ($e, "no error for input='$input'"); + like ($e, qr/malformed JSON string/, "'malformed JSON string' json string error for input='$input'"); +}); + +run_test(']', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok ($e, "no error for input='$input'"); + like ($e, qr/malformed JSON string/, "'malformed JSON string' json string error for input='$input'"); +}); + +run_test('1', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok ($res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/malformed JSON string/, "'malformed JSON string' json string error for input='$input'"); +}); + +run_test('1', sub { + my $input = shift; + my $coder = JSON::PP->new->allow_nonref(0); + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok ($e, "no error for input='$input'"); + like ($e, qr/JSON text must be an object or array/, "'JSON text must be an object or array' json string error for input='$input'"); +}); + +run_test('"1', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/malformed JSON string/, "'malformed JSON string' json string error for input='$input'"); +}); + +run_test('\\', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok ($e, "no error for input='$input'"); + like ($e, qr/malformed JSON string/, "'malformed JSON string' json string error for input='$input'"); +}); + +run_test('{"one": "', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); +}); + +run_test('{"one": {', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); +}); + +run_test('{"one": [', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); +}); + +run_test('{"one": t', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); +}); + +run_test('{"one": \\', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); +}); + +run_test('{"one": ', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); +}); + +run_test('{"one": 1', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); +}); + +run_test('{"one": {"two": 2', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated '$input'"); + ok (!$e, "no error -- '$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error -- $input"); +}); + +# Test Appending Closing '}' Curly Bracket +run_test('{"one": 1', sub { + my $input = shift; + my $coder = JSON::PP->new; + my $res = eval { $coder->incr_parse($input) }; + my $e = $@; # test more clobbers $@, we need it twice + ok (!$res, "truncated input='$input'"); + ok (!$e, "no error for input='$input'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input'"); + + $res = eval { $coder->incr_parse('}') }; + $e = $@; # test more clobbers $@, we need it twice + ok ($res, "truncated input='$input' . '}'"); + ok (!$e, "no error for input='$input' . '}'"); + unlike ($e, qr/, or \} expected while parsing object\/hash/, "No '} expected' json string error for input='$input' . '}'"); +}); diff --git a/cpan/JSON-PP/t/rt_122270_old_xs_boolean.t b/cpan/JSON-PP/t/rt_122270_old_xs_boolean.t new file mode 100644 index 0000000000..a3deb48787 --- /dev/null +++ b/cpan/JSON-PP/t/rt_122270_old_xs_boolean.t @@ -0,0 +1,33 @@ +# copied over from JSON::XS and modified to use JSON::PP + +use strict; +use warnings; +use Test::More; +BEGIN { plan tests => 10 }; + +BEGIN { $ENV{PERL_JSON_BACKEND} = 0; } + +use utf8; +use JSON::PP; + +SKIP: { + skip "no JSON::XS < 3", 5 unless eval { require JSON::XS; JSON::XS->VERSION < 3 }; + + my $false = JSON::XS::false(); + ok (JSON::PP::is_bool $false); + ok (++$false == 1); + ok (!JSON::PP::is_bool $false); + ok (!JSON::PP::is_bool "JSON::PP::Boolean"); + ok (!JSON::PP::is_bool {}); # GH-34 +} + +SKIP: { + skip "no Types::Serialiser 0.01", 5 unless eval { require JSON::XS; JSON::XS->VERSION(3.00); require Types::Serialiser; Types::Serialiser->VERSION == 0.01 }; + + my $false = JSON::XS::false(); + ok (JSON::PP::is_bool $false); + ok (++$false == 1); + ok (!JSON::PP::is_bool $false); + ok (!JSON::PP::is_bool "JSON::PP::Boolean"); + ok (!JSON::PP::is_bool {}); # GH-34 +} |