From f4fc158b534a3a0e97c2423505668fbcb259be77 Mon Sep 17 00:00:00 2001 From: Reini Urban Date: Fri, 15 Feb 2019 11:52:03 +0100 Subject: [PATCH] Cpanel-JSON-XS 4.09 Silence Gconvert -Wunused-result. Add unblessed_bool property (PR #118 by Pali) Add seperate allow_dupkeys property, in relaxed (#122), Fixed allow_dupkeys for the XS slow path, Silence 2 -Wunused-value warnings, Fix ->unblessed_bool to produce modifiable perl structures (PR #121 by Pali). --- .git-rr-cache | 2 +- META.json | 2 +- Porting/Maintainers.pl | 2 +- cpan/Cpanel-JSON-XS/XS.pm | 35 +++++++++++++++++++-- cpan/Cpanel-JSON-XS/XS.xs | 28 +++++++++++------ cpan/Cpanel-JSON-XS/t/25_boolean.t | 35 ++++++++++++++++++++- cpan/Cpanel-JSON-XS/t/26_duplicate.t | 33 ++++++++++++++++--- dist/Module-CoreList/lib/Module/CoreList.pm | 4 +-- pod/perlcdelta.pod | 9 +++++- 9 files changed, 127 insertions(+), 23 deletions(-) diff --git a/.git-rr-cache b/.git-rr-cache index 78c2b5fde62..5eff5791750 160000 --- a/.git-rr-cache +++ b/.git-rr-cache @@ -1 +1 @@ -Subproject commit 78c2b5fde626112e5e40e5ca717f60f16181bbea +Subproject commit 5eff57917506ebf7e4a0da22d5003ee4ab234420 diff --git a/META.json b/META.json index 992d1ee3dc4..8623b001f14 100644 --- a/META.json +++ b/META.json @@ -143,5 +143,5 @@ } }, "version" : "5.029001c", - "x_serialization_backend" : "Cpanel::JSON::XS version 4.07" + "x_serialization_backend" : "Cpanel::JSON::XS version 4.09" } diff --git a/Porting/Maintainers.pl b/Porting/Maintainers.pl index cad38642395..20f3c1b528c 100755 --- a/Porting/Maintainers.pl +++ b/Porting/Maintainers.pl @@ -432,7 +432,7 @@ package Maintainers; }, 'Cpanel::JSON::XS' => { - 'DISTRIBUTION' => 'RURBAN/Cpanel-JSON-XS-4.07.tar.gz', + 'DISTRIBUTION' => 'RURBAN/Cpanel-JSON-XS-4.09.tar.gz', 'FILES' => q[cpan/Cpanel-JSON-XS], 'EXCLUDED' => [ '.appveyor.yml', diff --git a/cpan/Cpanel-JSON-XS/XS.pm b/cpan/Cpanel-JSON-XS/XS.pm index c8d0d9d329b..6154f649ff8 100644 --- a/cpan/Cpanel-JSON-XS/XS.pm +++ b/cpan/Cpanel-JSON-XS/XS.pm @@ -1,5 +1,5 @@ package Cpanel::JSON::XS; -our $VERSION = '4.07'; +our $VERSION = '4.09'; our $XS_VERSION = $VERSION; # $VERSION = eval $VERSION; @@ -645,11 +645,12 @@ L option. { foo:"bar" } -=item * duplicate keys +=item * allow_dupkeys -With relaxed decoding of duplicate keys does not error and are silently accepted. +Allow decoding of duplicate keys in hashes. By default duplicate keys are forbidden. See L: RFC 7159 section 4: "The names within an object should be unique." +See the L option. =back @@ -701,6 +702,18 @@ C<"\/">. This setting has no effect when decoding JSON texts. +=item $json = $json->unblessed_bool ([$enable]) + +=item $enabled = $json->get_unblessed_bool + + $json = $json->unblessed_bool([$enable]) + +If C<$enable> is true (or missing), then C will return +Perl non-object boolean variables (1 and 0) for JSON booleans +(C and C). If C<$enable> is false, then C +will return C objects for JSON booleans. + + =item $json = $json->allow_singlequote ([$enable]) =item $enabled = $json->get_allow_singlequote @@ -812,6 +825,22 @@ This option does not affect C in any way. This option is special to this module, it is not supported by other encoders. So it is not recommended to use it. +=item $json = $json->allow_dupkeys ([$enable]) + +=item $enabled = $json->get_allow_dupkeys + +If C<$enable> is true (or missing), then the C method will not +die when it encounters duplicate keys in a hash. +C is also enabled in the C mode. + +The JSON spec allows duplicate name in objects but recommends to +disable it, however with Perl hashes they are impossible, parsing +JSON in Perl silently ignores duplicate names, using the last value +found. + +See L: +RFC 7159 section 4: "The names within an object should be unique." + =item $json = $json->allow_blessed ([$enable]) =item $enabled = $json->get_allow_blessed diff --git a/cpan/Cpanel-JSON-XS/XS.xs b/cpan/Cpanel-JSON-XS/XS.xs index 73d03c5a78d..13d61eed17e 100644 --- a/cpan/Cpanel-JSON-XS/XS.xs +++ b/cpan/Cpanel-JSON-XS/XS.xs @@ -276,10 +276,12 @@ mingw_modfl(long double x, long double *ip) #define F_ESCAPE_SLASH 0x00080000UL #define F_SORT_BY 0x00100000UL #define F_ALLOW_STRINGIFY 0x00200000UL +#define F_UNBLESSED_BOOL 0x00400000UL +#define F_ALLOW_DUPKEYS 0x00800000UL #define F_HOOK 0x80000000UL /* some hooks exist, so slow-path processing */ #define F_PRETTY F_INDENT | F_SPACE_BEFORE | F_SPACE_AFTER -#define SET_RELAXED (F_RELAXED | F_ALLOW_BAREKEY | F_ALLOW_SQUOTE) +#define SET_RELAXED (F_RELAXED | F_ALLOW_BAREKEY | F_ALLOW_SQUOTE | F_ALLOW_DUPKEYS) #define INIT_SIZE 32 /* initial scalar size to be allocated */ #define INDENT_STEP 3 /* default spaces per indentation level */ @@ -3253,7 +3255,7 @@ decode_hv (pTHX_ dec_t *dec, SV *typesv) SV *typerv; int allow_squote = dec->json.flags & F_ALLOW_SQUOTE; int allow_barekey = dec->json.flags & F_ALLOW_BAREKEY; - int relaxed = dec->json.flags & F_RELAXED; + int allow_dupkeys = dec->json.flags & F_ALLOW_DUPKEYS; char endstr = '"'; DEC_INC_DEPTH; @@ -3313,14 +3315,16 @@ decode_hv (pTHX_ dec_t *dec, SV *typesv) if (!key) goto fail; + if (!allow_dupkeys && UNLIKELY(hv_exists_ent (hv, key, 0))) { + ERR ("Duplicate keys not allowed"); + } decode_ws (dec); EXPECT_CH (':'); - decode_ws (dec); if (typesv) { value_typesv = newSV (0); - hv_store_ent (typehv, key, value_typesv, 0); + (void)hv_store_ent (typehv, key, value_typesv, 0); } value = decode_sv (aTHX_ dec, value_typesv); @@ -3330,7 +3334,7 @@ decode_hv (pTHX_ dec_t *dec, SV *typesv) goto fail; } - hv_store_ent (hv, key, value, 0); + (void)hv_store_ent (hv, key, value, 0); SvREFCNT_dec (key); break; @@ -3350,14 +3354,12 @@ decode_hv (pTHX_ dec_t *dec, SV *typesv) if (UNLIKELY(p - key > I32_MAX)) ERR ("Hash key too large"); #endif - if (!relaxed && UNLIKELY(hv_exists (hv, key, len))) { + if (!allow_dupkeys && UNLIKELY(hv_exists (hv, key, len))) { ERR ("Duplicate keys not allowed"); } dec->cur = p + 1; - decode_ws (dec); if (*p != ':') EXPECT_CH (':'); - decode_ws (dec); if (typesv) @@ -3600,6 +3602,8 @@ decode_sv (pTHX_ dec_t *dec, SV *typesv) dec->cur += 4; if (typesv) sv_setiv_mg (typesv, JSON_TYPE_BOOL); + if (dec->json.flags & F_UNBLESSED_BOOL) + return newSVsv (&PL_sv_yes); return newSVsv(MY_CXT.json_true); } else @@ -3614,6 +3618,8 @@ decode_sv (pTHX_ dec_t *dec, SV *typesv) dec->cur += 5; if (typesv) sv_setiv_mg (typesv, JSON_TYPE_BOOL); + if (dec->json.flags & F_UNBLESSED_BOOL) + return newSVsv (&PL_sv_no); return newSVsv(MY_CXT.json_false); } else @@ -4103,6 +4109,8 @@ void ascii (JSON *self, int enable = 1) allow_bignum = F_ALLOW_BIGNUM escape_slash = F_ESCAPE_SLASH allow_stringify = F_ALLOW_STRINGIFY + unblessed_bool = F_UNBLESSED_BOOL + allow_dupkeys = F_ALLOW_DUPKEYS PPCODE: if (enable) self->flags |= ix; @@ -4131,7 +4139,9 @@ void get_ascii (JSON *self) get_allow_singlequote = F_ALLOW_SQUOTE get_allow_bignum = F_ALLOW_BIGNUM get_escape_slash = F_ESCAPE_SLASH - get_allow_stringify = F_ALLOW_STRINGIFY + get_allow_stringify = F_ALLOW_STRINGIFY + get_unblessed_bool = F_UNBLESSED_BOOL + get_allow_dupkeys = F_ALLOW_DUPKEYS PPCODE: XPUSHs (boolSV (self->flags & ix)); diff --git a/cpan/Cpanel-JSON-XS/t/25_boolean.t b/cpan/Cpanel-JSON-XS/t/25_boolean.t index 2ee96d38ffb..9fcd81cd99f 100644 --- a/cpan/Cpanel-JSON-XS/t/25_boolean.t +++ b/cpan/Cpanel-JSON-XS/t/25_boolean.t @@ -1,8 +1,16 @@ use strict; -use Test::More tests => 32; +use Test::More tests => 42; use Cpanel::JSON::XS (); use Config; +my $have_blessed; +BEGIN { + if (eval { require Scalar::Util }) { + Scalar::Util->import('blessed'); + $have_blessed = 1; + } +} + my $booltrue = q({"is_true":true}); my $boolfalse = q({"is_false":false}); my $truefalse = "[true,false]"; @@ -11,6 +19,7 @@ my $true = Cpanel::JSON::XS::true; my $false = Cpanel::JSON::XS::false; my $nonref_cjson = Cpanel::JSON::XS->new->allow_nonref; +my $unblessed_bool_cjson = Cpanel::JSON::XS->new->unblessed_bool; # from JSON::MaybeXS my $data = $cjson->decode('{"foo": true, "bar": false, "baz": 1}'); @@ -86,3 +95,27 @@ ok( Cpanel::JSON::XS::is_bool($js->[1]), "false is_bool"); # GH #53 ok( !Cpanel::JSON::XS::is_bool( [] ), "[] !is_bool"); + + +$js = $unblessed_bool_cjson->decode($booltrue); +SKIP: { + skip "no Scalar::Util in $]", 1 unless $have_blessed; + ok(!blessed($js->{is_true}), "->unblessed_bool for JSON true does not return blessed object"); +} +cmp_ok($js->{is_true}, "==", 1, "->unblessed_bool for JSON true returns correct Perl bool value"); +cmp_ok($js->{is_true}, "eq", "1", "->unblessed_bool for JSON true returns correct Perl bool value"); + +$js = $unblessed_bool_cjson->decode($boolfalse); +SKIP: { + skip "no Scalar::Util in $]", 1 unless $have_blessed; + ok(!blessed($js->{is_false}), "->unblessed_bool for JSON false does not return blessed object"); +} +cmp_ok($js->{is_false}, "==", 0, "->unblessed_bool for JSON false returns correct Perl bool value"); +cmp_ok($js->{is_false}, "eq", "", "->unblessed_bool for JSON false returns correct Perl bool value"); + +is($unblessed_bool_cjson->encode(do { my $struct = $unblessed_bool_cjson->decode($truefalse, my $types); ($struct, $types) }), $truefalse, "encode(decode(boolean)) is identity with ->unblessed_bool"); +is($cjson->encode(do { my $struct = $unblessed_bool_cjson->decode($truefalse, my $types); ($struct, $types) }), $truefalse, "booleans decoded by ->unblessed_bool(1) are encoded by ->unblessed_bool(0) in the same way"); + +$js = $unblessed_bool_cjson->decode($truefalse); +ok eval { $js->[0] = "new value 0" }, "decoded 'true' is modifiable" or diag($@); +ok eval { $js->[1] = "new value 1" }, "decoded 'false' is modifiable" or diag($@); diff --git a/cpan/Cpanel-JSON-XS/t/26_duplicate.t b/cpan/Cpanel-JSON-XS/t/26_duplicate.t index ec3c87e4a87..c004145512d 100644 --- a/cpan/Cpanel-JSON-XS/t/26_duplicate.t +++ b/cpan/Cpanel-JSON-XS/t/26_duplicate.t @@ -1,13 +1,38 @@ -use Test::More tests => 4; +use strict; +use Test::More tests => 9; use Cpanel::JSON::XS; my $json = Cpanel::JSON::XS->new; -# disallow dupkeys: +# disallow dupkeys ok (!eval { $json->decode ('{"a":"b","a":"c"}') }); # y_object_duplicated_key.json ok (!eval { $json->decode ('{"a":"b","a":"b"}') }); # y_object_duplicated_key_and_value.json +# relaxed allows dupkeys $json->relaxed; -is (encode_json ($json->decode ('{"a":"b","a":"c"}')), '{"a":"c"}'); # y_object_duplicated_key.json -is (encode_json ($json->decode ('{"a":"b","a":"b"}')), '{"a":"b"}'); # y_object_duplicated_key_and_value.json +# y_object_duplicated_key.json +is (encode_json ($json->decode ('{"a":"b","a":"c"}')), '{"a":"c"}', 'relaxed'); +# y_object_duplicated_key_and_value.json +is (encode_json ($json->decode ('{"a":"b","a":"b"}')), '{"a":"b"}', 'relaxed'); +# turning off relaxed disallows dupkeys +$json->relaxed(0); +$json->allow_dupkeys; # but turn it on +is (encode_json ($json->decode ('{"a":"b","a":"c"}')), '{"a":"c"}', 'allow_dupkeys'); +is (encode_json ($json->decode ('{"a":"b","a":"b"}')), '{"a":"b"}', 'allow_dupkeys'); + +# disallow dupkeys explicitly +$json->allow_dupkeys(0); +eval { $json->decode ('{"a":"b","a":"c"}') }; +like ($@, qr/^Duplicate keys not allowed/, 'allow_dupkeys(0)'); + +# disallow dupkeys explicitly with relaxed +$json->relaxed; +$json->allow_dupkeys(0); +eval { $json->decode ('{"a":"b","a":"c"}') }; # the XS slow path +like ($@, qr/^Duplicate keys not allowed/, 'relaxed and allow_dupkeys(0)'); + +$json->allow_dupkeys; +$json->relaxed(0); # tuning off relaxed needs to turn off dupkeys +eval { $json->decode ('{"a":"b","a":"c"}') }; +like ($@, qr/^Duplicate keys not allowed/, 'relaxed(0)'); diff --git a/dist/Module-CoreList/lib/Module/CoreList.pm b/dist/Module-CoreList/lib/Module/CoreList.pm index b4aa9851fec..e2ad2e80005 100644 --- a/dist/Module-CoreList/lib/Module/CoreList.pm +++ b/dist/Module-CoreList/lib/Module/CoreList.pm @@ -359,7 +359,7 @@ our %released :const = ( 5.029002 => '2018-08-20', 5.029003 => '2018-09-20', 5.029004 => '2018-10-20', - '5.029001c' => '2018-11-27', + '5.029001c' => '????', ); sub version_sort { @@ -17949,7 +17949,7 @@ our %delta :const = ( 'Module::CoreList' => '5.20181019c', 'Module::CoreList::Utils'=> '5.20181019c', 'B::C' => '1.55_10', - 'Cpanel::JSON::XS' => '4.07', + 'Cpanel::JSON::XS' => '4.09', 'ExtUtils::Embed' => '1.36', 'ExtUtils::MakeMaker' => '8.35_07', 'ExtUtils::MM_Unix' => '8.35_07', diff --git a/pod/perlcdelta.pod b/pod/perlcdelta.pod index 1127a5e67ca..1a096874938 100644 --- a/pod/perlcdelta.pod +++ b/pod/perlcdelta.pod @@ -149,10 +149,17 @@ under 10min. Added a C test detection. -=item L 4.07 +=item L 4.09 Silence Gconvert -Wunused-result. +Add unblessed_bool property (PR #118 by Pali) + +Add seperate allow_dupkeys property, in relaxed (#122), +Fixed allow_dupkeys for the XS slow path, +Silence 2 -Wunused-value warnings, +Fix ->unblessed_bool to produce modifiable perl structures (PR #121 by Pali). + =item L 1.36 Added optimize to ccopts, required for C<-flto>.