Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package perl-Cpanel-JSON-XS for
openSUSE:Factory checked in at 2026-06-03 20:28:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Cpanel-JSON-XS (Old)
and /work/SRC/openSUSE:Factory/.perl-Cpanel-JSON-XS.new.1937 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Cpanel-JSON-XS"
Wed Jun 3 20:28:20 2026 rev:42 rq:1356949 version:4.410.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Cpanel-JSON-XS/perl-Cpanel-JSON-XS.changes
2025-09-09 20:30:48.526651628 +0200
+++
/work/SRC/openSUSE:Factory/.perl-Cpanel-JSON-XS.new.1937/perl-Cpanel-JSON-XS.changes
2026-06-03 20:30:26.073142935 +0200
@@ -1,0 +2,14 @@
+Thu May 28 08:53:35 UTC 2026 - Tina Müller <[email protected]>
+
+- updated to 4.410.0 (4.41)
+ see /usr/share/doc/packages/perl-Cpanel-JSON-XS/Changes
+
+ 4.41 2026-05-27 (rurban)
+ - Fix BOM-shift PV-corruption SIGABRT (CVE-2026-9516) (patch by Paul
Johnson)
+ - Fix dupkeys_as_arrayref type confusion (CVE-2026-9334) (patch by
Paul Johnson)
+ - Fix incr_parse single-quote string delimiter (GH #245, reported by
+ Paul Johnson)
+ - Fix a one-byte out-of-bounds heap read reachable via allow_barekey
on
+ truncated input (GH #244, reported by Paul Johnson)
+
+-------------------------------------------------------------------
Old:
----
Cpanel-JSON-XS-4.40.tar.gz
New:
----
Cpanel-JSON-XS-4.41.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ perl-Cpanel-JSON-XS.spec ++++++
--- /var/tmp/diff_new_pack.Axe8ku/_old 2026-06-03 20:30:26.857175405 +0200
+++ /var/tmp/diff_new_pack.Axe8ku/_new 2026-06-03 20:30:26.861175571 +0200
@@ -1,7 +1,7 @@
#
# spec file for package perl-Cpanel-JSON-XS
#
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,10 +18,10 @@
%define cpan_name Cpanel-JSON-XS
Name: perl-Cpanel-JSON-XS
-Version: 4.400.0
+Version: 4.410.0
Release: 0
-# 4.40 -> normalize -> 4.400.0
-%define cpan_version 4.40
+# 4.41 -> normalize -> 4.410.0
+%define cpan_version 4.41
License: Artistic-1.0 OR GPL-1.0-or-later
Summary: CPanel fork of JSON::XS, fast and correct serializing
URL: https://metacpan.org/release/%{cpan_name}
@@ -32,6 +32,7 @@
BuildRequires: perl-macros
BuildRequires: perl(Time::Piece)
Provides: perl(Cpanel::JSON::XS) = %{version}
+Provides: perl(Cpanel::JSON::XS::Type)
%undefine __perllib_provides
%{perl_requires}
++++++ Cpanel-JSON-XS-4.40.tar.gz -> Cpanel-JSON-XS-4.41.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/.github/workflows/testsuite.yml
new/Cpanel-JSON-XS-4.41/.github/workflows/testsuite.yml
--- old/Cpanel-JSON-XS-4.40/.github/workflows/testsuite.yml 2025-09-08
13:53:39.000000000 +0200
+++ new/Cpanel-JSON-XS-4.41/.github/workflows/testsuite.yml 2026-05-27
20:00:10.000000000 +0200
@@ -19,10 +19,10 @@
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #
v5.0.0
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #
v6.0.2
- run: perl -V
- name: install cpan deps
- uses:
perl-actions/install-with-cpm@8b1a9840b26cc3885ae2889749a48629be2501b0 # v1.9
+ uses:
perl-actions/install-with-cpm@b7eeb5ea204d9c9bd434e01162ae97629cf7fa36 # v2.4
with:
install: |
Data::Dumper
@@ -85,13 +85,13 @@
]
steps:
- - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #
v5.0.0
- - uses:
shogo82148/actions-setup-perl@5796a908661aa68fc0a5b8f55c6791af2376d72e # v1.35.0
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #
v6.0.2
+ - uses:
shogo82148/actions-setup-perl@a198315ec4e9244f206879ea7b63078003aec8a6 # v1.41.1
with:
perl-version: ${{ matrix.perl-version }}
- run: perl -V
- name: install cpan deps
- uses:
perl-actions/install-with-cpm@8b1a9840b26cc3885ae2889749a48629be2501b0 # v1.9
+ uses:
perl-actions/install-with-cpm@b7eeb5ea204d9c9bd434e01162ae97629cf7fa36 # v2.4
with:
sudo: false
install: |
@@ -118,7 +118,7 @@
perl-version: [latest]
steps:
- - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #
v5.0.0
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #
v6.0.2
- run: perl -V
- run: perl Makefile.PL
- run: make test
@@ -140,7 +140,7 @@
perl-version: [latest]
steps:
- - uses: actions/checkout@master
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #
v6.0.2
- run: perl -V
- run: perl Makefile.PL
#- run: prove -vb t/*.t
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/Changes
new/Cpanel-JSON-XS-4.41/Changes
--- old/Cpanel-JSON-XS-4.40/Changes 2025-09-08 13:53:39.000000000 +0200
+++ new/Cpanel-JSON-XS-4.41/Changes 2026-05-27 20:00:10.000000000 +0200
@@ -2,6 +2,14 @@
TODO: http://stevehanov.ca/blog/index.php?id=104 compression
+4.41 2026-05-27 (rurban)
+ - Fix BOM-shift PV-corruption SIGABRT (CVE-2026-9516) (patch by Paul
Johnson)
+ - Fix dupkeys_as_arrayref type confusion (CVE-2026-9334) (patch by
Paul Johnson)
+ - Fix incr_parse single-quote string delimiter (GH #245, reported by
+ Paul Johnson)
+ - Fix a one-byte out-of-bounds heap read reachable via allow_barekey on
+ truncated input (GH #244, reported by Paul Johnson)
+
4.40 2025-09-07 (rurban)
- Fix CVE-2025-40929 overflow with overlong numbers, fuzzing only.
- Detect more malformed numbers, with two decimal points.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/META.json
new/Cpanel-JSON-XS-4.41/META.json
--- old/Cpanel-JSON-XS-4.40/META.json 2025-09-08 16:00:51.000000000 +0200
+++ new/Cpanel-JSON-XS-4.41/META.json 2026-05-27 20:00:40.000000000 +0200
@@ -100,7 +100,7 @@
"url" : "https://github.com/rurban/Cpanel-JSON-XS"
}
},
- "version" : "4.40",
+ "version" : "4.41",
"x_contributors" : [
"Ashley Willis <[email protected]>",
"Chip Salzenberg <[email protected]>",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/META.yml
new/Cpanel-JSON-XS-4.41/META.yml
--- old/Cpanel-JSON-XS-4.40/META.yml 2025-09-08 16:00:50.000000000 +0200
+++ new/Cpanel-JSON-XS-4.41/META.yml 2026-05-27 20:00:39.000000000 +0200
@@ -48,7 +48,7 @@
bugtracker: https://github.com/rurban/Cpanel-JSON-XS/issues
license: http://dev.perl.org/licenses/
repository: https://github.com/rurban/Cpanel-JSON-XS
-version: '4.40'
+version: '4.41'
x_contributors:
- 'Ashley Willis <[email protected]>'
- 'Chip Salzenberg <[email protected]>'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/SIGNATURE
new/Cpanel-JSON-XS-4.41/SIGNATURE
--- old/Cpanel-JSON-XS-4.40/SIGNATURE 2025-09-08 16:00:52.000000000 +0200
+++ new/Cpanel-JSON-XS-4.41/SIGNATURE 2026-05-27 20:00:41.000000000 +0200
@@ -16,18 +16,18 @@
SHA256 aac2b4bbaa7b93eaf72300f60e167a17e05adcd721087f735ba55d2900f31490
.appveyor.yml
SHA256 082201a3cbd62a55f2e58ffbb991c4b2bb806de0009bc9497ffcc07202f60855
.github/FUNDING.yml
-SHA256 27d585f5789434eac4d99d9a66b143c3c76d27c7a622061922919e4f70f93887
.github/workflows/testsuite.yml
+SHA256 a7081377424ff33494fd0e7fad1ce807657b29794dcca9dd238f30465579dad1
.github/workflows/testsuite.yml
SHA256 a3c34aba52e269e6cec558ecf9cff393138574189fdff26b183bee9cc2e0434f
.travis.yml
SHA256 c3f2a1a4f66382f796f71a571946722edba53cf3238152b26fd325f4c2f1a20f
.whitesource
SHA256 8de3540a3cd7ecc9a9dcb48975fe852c082fe17d4462f87bb72aa7cc47f083ad COPYING
-SHA256 ae4bb1db5a3fa099f35c9a5b79648fa98c3e17bc30d01fb66e55bb72344bed39 Changes
+SHA256 5f125d9df9f2de624ecb1de0f26f820e4b940c78d4fbbb52a22c849e57740e2e Changes
SHA256 a5378ebe65273d49047a21e94af087f70a303793ffed2a695c800ed965ac185d
MANIFEST
-SHA256 48ed49a7b028baa86cec0aa499e2448f68890cfa166db960b7fe316f85d16757
META.json
-SHA256 0acb81669300bb982e04541b1063b424d334af2d2f7e0399fa596abd638161a4
META.yml
+SHA256 2a1d33955bd96ad9effd5f0ec39d589ecb51b0c08a11c196567979ca8a85899e
META.json
+SHA256 f7714a74c855e188aa85d5422a1438ff469796876a833a128cea8661684f641f
META.yml
SHA256 0fc7078919ff510137a654acc66bd68c971786cafd8ee621afae6d99321df4bb
Makefile.PL
SHA256 c62f5a06dffaa850fe7d55cad1c5ce3fbdb5504031b73b6043aa2974708c9293 README
-SHA256 5ff0b6a015d21a2344ec786a6f8faa7547346720cfa02a0526c9952b2211d903 XS.pm
-SHA256 5bf1c4bc302db55d0e23eeac0dc9c2b1f03bb76a6d6af0f87d496cbbf1527315 XS.xs
+SHA256 e7b813bc4beea51b9ad2bb35c5a97f22f103b01d1274e6f1b5b03711e857e927 XS.pm
+SHA256 1fd3cedb5e734964e9410b452c50858df494924994fcee092f0921e13aea6766 XS.xs
SHA256 c95e4b970183cbd6d1ec9c88c37a80f12bd2b66ed6be3c008ffd578d2f622c01
XS/Boolean.pm
SHA256 20596259e7e399ed1984a469a9a907be878499406d5285a11f1ab98f93aff44f
XS/Type.pm
SHA256 2f34a530b7ce981b0df9aacd2b6944ccf74c4a7f8bb49fde57b342663e7feb26
bin/cpanel_json_xs
@@ -46,7 +46,7 @@
SHA256 e88b03d3c8c5c85d4fc2c086848efd7d0fd7b69f839cf0936a698af77a7a59b8
t/09_pc_extra_number.t
SHA256 f177821982876d02403298d44ffe4e2193fdcd70b76da252b055f3eab8dd3cdf
t/104_sortby.t
SHA256 e8bf435b08bfd00e6ab7f278c6ce68ef8691011b80615fa372961f2d807f5c76
t/105_esc_slash.t
-SHA256 8549eb57bd2ac40cbe57d8441f9188210ef0894c76626e3052ac40302f4f52a4
t/106_allow_barekey.t
+SHA256 d633b016ec1e792b84d4f53ac75166953a95298328185aaa08932dc7236a929b
t/106_allow_barekey.t
SHA256 16f34295a33f59b8fe7a4f70b701df03fc866d77eac300ca0503a98875675569
t/107_allow_singlequote.t
SHA256 f2047975a3b8392feb6a87d782ecc7746ae2117bde57f716cc90877c8850f2e0
t/108_decode.t
SHA256 e6f7738431bc8d77ad0b8ad2db9ab54426f7bbc86eb5f5794b1a4616f454baef
t/109_encode.t
@@ -71,7 +71,7 @@
SHA256 4f73fcceb31cfb06ac5110ec89107cc14302905061d28b0700d4673f654d5592
t/16_tied.t
SHA256 398e5ff51603a52de901f4c1934265601e226d05b88ac604dcd9e9d179a0344f
t/17_relaxed.t
SHA256 1585a6aecec5c73b7a6f70982b3bcc1edc1d63ca55467223ab0d6f0956254bc4
t/18_json_checker.t
-SHA256 9f9006c1f925d9ace7d1621e1479c21f9b50459ab57aa0046209fed2b3e66530
t/19_incr.t
+SHA256 d89efdc36f0e1b2be955c91f320ef73cebb9aa9bc63b0b309e31ed58590cf0ae
t/19_incr.t
SHA256 dde73ed3cfc0e28d064f61fc08871accf88b780aee06a3cb0040f59f04c1ff36
t/20_faihu.t
SHA256 56e11977ce3d544f8c8e62a38cbcc4f58f7f1d53b71918f803536acd62122713
t/20_unknown.t
SHA256 388f8e0f0e41c9921aedc67313f8b89bdd08b95ced0dba242986d3b76d9a1688
t/21_evans.t
@@ -79,9 +79,9 @@
SHA256 2a6506fb07b27b1fef52b251d3876d23bd572596ff487d37c2f6597be554836c
t/23_array_ctx.t
SHA256 a8dfccba0b60b0fc91812fcfd96656e993abb74970509926d738c67a58641f01
t/24_freeze_recursion.t
SHA256 d6e46428bf221ea9bca6f8c0a9d14ee76305d91e01d9946b570aac125d392ba8
t/25_boolean.t
-SHA256 e7297f97fe3fea65c865658675b72e667b37b201e7fec8b8128f2006f8999d86
t/26_duplicate.t
+SHA256 9f6e48c5519a1fcf8be484e8c231138b66054027ac9bdca7c97672864a13db35
t/26_duplicate.t
SHA256 814438975ce229d4ff0deb6a9aef967b7f088e03894b8b8e6ca1ccfb6d953117
t/30_jsonspec.t
-SHA256 cf2181a691d5e1862d71e4e902928a0d899b9671e3633584efa8ae3f5cc0d174
t/31_bom.t
+SHA256 bf3103d7dcb5e6fe0603d9ab640c51652eb1c41393a9b5fc06db80b6ae7a5c95
t/31_bom.t
SHA256 59c743137453c8c4e9e785a15dcd057b0209d5ce160d683d7ab416dc37a92b6d
t/52_object.t
SHA256 3b9ce402e2d0cae8a525df4beca05f2656ba5cf02b074d02fd690fe97773d2d7
t/53_readonly.t
SHA256 a08be137b59c9cd58410bc41969e1e9e9fa2159469523394b6bfd0c798c00908
t/54_stringify.t
@@ -446,15 +446,15 @@
SHA256 aca6f846869ab2e4881e807739086e1535b1438bd0e23d7a021360742736a6a9
xt/pod.t
-----BEGIN PGP SIGNATURE-----
-iQGzBAEBAwAdFiEEOKQWew22nknF9yFsuMKIZqsnp6IFAmi+4ZMACgkQuMKIZqsn
-p6KuoAwAr4PmFqtyelLfhw0SXAmFBDuysAAYlLKb/bq0vrWM8xsrhRnIYZF4bAPw
-eEeM8nxMigZ3Dn1lFnK90q2+qtsU324zOzH57cGOBCCy+chL3rOSTSmGHed4badZ
-G6ocNL4E+1NUHz3bkTmjflsjiScxemCgUz1VSRE+Ob57rWnm9mtsofdVRViDwcrb
-kiLH5WwyPZYtu4KByxGs64nijg6WE3M12dDsvrm1f0dKbq4Y+gCCDKUn6IreOfRo
-ylr4/be0jJeSKfH+2riJ33cNtO8JBl3o9//p1eXM3k4gQgujs1HDiJO64j+u+vbq
-gW94FpHzOmoffufp9izq5sidgXj1kfbonFXw2mB/odVzjsHh05HBqeAZ6s4aTWFL
-O3TAKYeZYrE3fqS5y2DIoSC6gCqIQiKUy/00loG2vq6vVzjF+DbetDBiNc0WDOop
-eDkxmipMmVTA+ZUQvWtQAUUhP42QcGv5Am2OeeieKB2SuQ1BHl5hRcz9PE5FGldR
-ZrWYP67e
-=Z+fz
+iQGzBAEBAwAdFiEEOKQWew22nknF9yFsuMKIZqsnp6IFAmoXMUkACgkQuMKIZqsn
+p6IH/AwAlP87Q9QalXZtyOrJ6NegS/x+OwWp6/GprVe4mp9Mqosy9WEfcjf2zt6v
+0qEHQSYW3UOxTg0pjcM4Aw/wJWWDZzZRn9EsSnX2Gc2OJOJdQyfobYQgMOFxdni+
+T9xuHGpjtwsqk2oOzRVptrXa1bxTfWn0AJgHc3VAj+m3J3wk7mA3amd7a+5J+bL/
+dR2tq6iAEgPzjplwzytHkfPyXH3YdePXSM7xbzT5agzxgxZKiol6mwwLPwZe24x+
+xf67L9ksOY8dZzKMb/cQW/1CjoqJzwobxMNfBk5+PG8FBa9npPSvModkdI3Ty4Rh
+DL7GB7AIyhyDp0aSFrfpEdhsoySJK6m1rfRdk5qpYZaSdC8XY5MtD2a/eP747Jw0
+yy5rx7h1UqOuZipxd+7BW4izyas9FW37o/AEQHAv8AWN0MYTdq38e2W7qLjRb+Bb
+/ShHY3PdwkWOsEsfm1hj08LTEMLY/6LksSEqSZuTGivPsI4PT3s/jQQ+BldhIXRv
+yn0x3SIH
+=PtUe
-----END PGP SIGNATURE-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/XS.pm
new/Cpanel-JSON-XS-4.41/XS.pm
--- old/Cpanel-JSON-XS-4.40/XS.pm 2025-09-08 13:53:39.000000000 +0200
+++ new/Cpanel-JSON-XS-4.41/XS.pm 2026-05-27 20:00:10.000000000 +0200
@@ -1,5 +1,5 @@
package Cpanel::JSON::XS;
-our $VERSION = '4.40';
+our $VERSION = '4.41';
our $XS_VERSION = $VERSION;
# $VERSION = eval $VERSION;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/XS.xs
new/Cpanel-JSON-XS-4.41/XS.xs
--- old/Cpanel-JSON-XS-4.40/XS.xs 2025-09-08 13:53:39.000000000 +0200
+++ new/Cpanel-JSON-XS-4.41/XS.xs 2026-05-27 20:00:10.000000000 +0200
@@ -366,7 +366,6 @@
#define F_REQUIRE_TYPES 0x01000000UL
#define F_TYPE_ALL_STRING 0x02000000UL
#define F_DUPKEYS_AS_AREF 0x04000000UL
-#define F_DUPKEYS_FIRST 0x08000000UL /* internal only */
#define F_HOOK 0x80000000UL /* some hooks exist, so slow-path
processing */
#define F_PRETTY F_INDENT | F_SPACE_BEFORE | F_SPACE_AFTER
@@ -426,7 +425,9 @@
INCR_M_BS, /* inside backslash */
INCR_M_C0, /* inside comment in initial whitespace sequence */
INCR_M_C1, /* inside comment in other places */
- INCR_M_JSON /* outside anything, count nesting */
+ INCR_M_JSON, /* outside anything, count nesting */
+ INCR_M_SQSTR, /* inside single-quoted string (allow_singlequote) */
+ INCR_M_SQBS /* inside backslash inside single-quoted string */
};
#define INCR_DONE(json) ((json)->incr_nest <= 0 && (json)->incr_mode ==
INCR_M_JSON)
@@ -3924,7 +3925,7 @@
int allow_barekey = dec->json.flags & F_ALLOW_BAREKEY;
int allow_dupkeys = dec->json.flags & F_ALLOW_DUPKEYS;
int dupkeys_as_arrayref = dec->json.flags & F_DUPKEYS_AS_AREF;
- int dupkeys_first = dec->json.flags & F_DUPKEYS_FIRST;
+ HV *dupkeys_seen = NULL;
char endstr = '"';
DEC_INC_DEPTH;
@@ -3978,9 +3979,11 @@
for (;;)
{
/* the >= 0x80 is false on most architectures */
- if (UNLIKELY(!is_bare &&
+ /* !*p must be checked before !is_bare: a bare-key scan has no
+ bounds guard and would run one byte past dec->end otherwise */
+ if (UNLIKELY(!*p || (!is_bare &&
(p == e || *p < 0x20 || *(U8*)p >= 0x80 || *p == '\\'
- || allow_squote)))
+ || allow_squote))))
{
/* slow path, back up and use decode_str */
/* utf8 hash keys are handled here */
@@ -3996,16 +3999,21 @@
// extend the value to arrayref or push
old_value = HeVAL(hv_fetch_ent (hv, keysv, 0, 0));
SvREFCNT_inc (old_value);
- if (dupkeys_first) {
- AV *av = newAV ();
- av_extend (av, 2);
- if (av_store(av, 0, old_value))
- old_value = newRV ((SV*)av);
- } else if (SvTYPE (old_value) != SVt_RV &&
- SvTYPE (SvRV (old_value)) != SVt_PVAV) {
- // not an AvREF
- ERR ("Invalid dupkeys_as_arrayref hash key");
- }
+ if (!dupkeys_seen
+ || !hv_exists_ent (dupkeys_seen, keysv, 0))
+ {
+ AV *av = newAV ();
+ av_extend (av, 2);
+ if (av_store (av, 0, old_value))
+ old_value = newRV ((SV*)av);
+ if (!dupkeys_seen)
+ {
+ dupkeys_seen = newHV ();
+ sv_2mortal ((SV *)dupkeys_seen);
+ }
+ (void)hv_store_ent (dupkeys_seen, keysv,
+ newSV (0), 0);
+ }
} // else overwrite it below
}
decode_ws (dec);
@@ -4029,11 +4037,6 @@
{
av_push ((AV*)SvRV (old_value), value);
(void)hv_store_ent (hv, keysv, old_value, 0);
- if (dupkeys_first)
- {
- dupkeys_first = 0;
- dec->json.flags &= ~F_DUPKEYS_FIRST;
- }
}
else
{
@@ -4067,16 +4070,21 @@
SV** rv = hv_fetch (hv, key, len, 0);
old_value = *rv;
SvREFCNT_inc (old_value);
- if (dupkeys_first) {
- AV *av = newAV ();
- av_extend (av, 2);
- if (av_store(av, 0, old_value))
- old_value = newRV ((SV*)av);
- } else if (SvTYPE (old_value) != SVt_RV &&
- SvTYPE (SvRV (old_value)) != SVt_PVAV) {
- // not an AvREF
- ERR ("Invalid dupkeys_as_arrayref hash key");
- }
+ if (!dupkeys_seen
+ || !hv_exists (dupkeys_seen, key, len))
+ {
+ AV *av = newAV ();
+ av_extend (av, 2);
+ if (av_store (av, 0, old_value))
+ old_value = newRV ((SV*)av);
+ if (!dupkeys_seen)
+ {
+ dupkeys_seen = newHV ();
+ sv_2mortal ((SV *)dupkeys_seen);
+ }
+ (void)hv_store (dupkeys_seen, key, len,
+ newSV (0), 0);
+ }
} // else overwrite it below
}
@@ -4101,11 +4109,6 @@
{
av_push ((AV*)SvRV (old_value), value);
hv_store_str (aTHX_ hv, key, len, old_value);
- if (dupkeys_first)
- {
- dupkeys_first = 0;
- dec->json.flags &= ~F_DUPKEYS_FIRST;
- }
}
else
{
@@ -4503,8 +4506,6 @@
converted = 1 + (json->flags & F_UTF8);
json->flags |= F_UTF8;
offset = 3;
- SvPV_set(string, SvPVX_mutable (string) + 3);
- SvCUR_set(string, len - 3);
SvUTF8_on(string);
/* omitting the endian name will skip the BOM in the result */
} else if (len >= 4 && memEQc(s, UTF32BOM)) {
@@ -4539,7 +4540,7 @@
SvGROW (string, SvCUR (string) + 1);
dec.json = *json;
- dec.cur = SvPVX (string);
+ dec.cur = SvPVX (string) + offset;
dec.end = SvEND (string);
dec.err = 0;
dec.depth = 0;
@@ -4553,10 +4554,11 @@
sv = decode_sv (aTHX_ &dec, typesv);
if (offset_return) {
- if (dec.cur < SvPVX (string) || dec.cur > SvEND (string))
+ char *base = SvPVX (string) + offset;
+ if (dec.cur < base || dec.cur > SvEND (string))
*offset_return = 0;
else
- *offset_return = dec.cur - SvPVX (string);
+ *offset_return = dec.cur - base;
}
if (!(offset_return || !sv))
@@ -4571,12 +4573,6 @@
sv = NULL;
}
}
- /* restore old utf8 string with BOM */
- if (UNLIKELY(offset)) {
- SvPV_set(string, SvPVX_mutable (string) - offset);
- SvCUR_set(string, len);
- }
-
if (!sv)
{
SV *uni = sv_newmortal ();
@@ -4667,6 +4663,15 @@
self->incr_mode = INCR_M_STR;
goto incr_m_str;
+ /* skip a single char inside a single-quoted string (for
\\-processing) */
+ case INCR_M_SQBS:
+ if (!*p)
+ goto interrupt;
+
+ ++p;
+ self->incr_mode = INCR_M_SQSTR;
+ goto incr_m_sqstr;
+
/* inside #-style comments */
case INCR_M_C0:
case INCR_M_C1:
@@ -4717,6 +4722,37 @@
++p;
}
+ /* inside a single-quoted string (allow_singlequote) */
+ case INCR_M_SQSTR:
+ incr_m_sqstr:
+ for (;;)
+ {
+ if (*p == '\'')
+ {
+ ++p;
+ self->incr_mode = INCR_M_JSON;
+
+ if (!self->incr_nest)
+ goto interrupt;
+
+ goto incr_m_json;
+ }
+ else if (*p == '\\')
+ {
+ ++p;
+
+ if (!*p)
+ {
+ self->incr_mode = INCR_M_SQBS;
+ goto interrupt;
+ }
+ }
+ else if (!*p)
+ goto interrupt;
+
+ ++p;
+ }
+
/* after initial ws, outside string */
case INCR_M_JSON:
incr_m_json:
@@ -4743,6 +4779,14 @@
self->incr_mode = INCR_M_STR;
goto incr_m_str;
+ case '\'':
+ if (self->flags & F_ALLOW_SQUOTE)
+ {
+ self->incr_mode = INCR_M_SQSTR;
+ goto incr_m_sqstr;
+ }
+ break;
+
case '[':
case '{':
case '(':
@@ -4886,7 +4930,7 @@
# Turning on DUPKEYS_AS_AREF also turns on ALLOW_DUPKEYS
# But turning off DUPKEYS_AS_AREF does not
if (ix == F_DUPKEYS_AS_AREF && enable != 0)
- self->flags |= F_ALLOW_DUPKEYS | F_DUPKEYS_FIRST;
+ self->flags |= F_ALLOW_DUPKEYS;
XPUSHs (ST (0));
void get_ascii (JSON *self)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/t/106_allow_barekey.t
new/Cpanel-JSON-XS-4.41/t/106_allow_barekey.t
--- old/Cpanel-JSON-XS-4.40/t/106_allow_barekey.t 2023-02-22
12:08:39.000000000 +0100
+++ new/Cpanel-JSON-XS-4.41/t/106_allow_barekey.t 2026-05-27
20:00:10.000000000 +0200
@@ -1,5 +1,5 @@
-use Test::More tests => 6;
+use Test::More tests => 9;
use strict;
use utf8;
use Cpanel::JSON::XS;
@@ -25,3 +25,21 @@
is(utf8::is_utf8($k[0]), 1, 'keep utf8 as bare key');
}
+# GH #244: truncated bare-key input must not cause a one-byte OOB heap read.
+# The fast-scan loop previously ran p past dec->end before checking for ':'.
+{
+ my $coder = Cpanel::JSON::XS->new->allow_barekey(1);
+ my $err;
+
+ # bare key with no ':' or value — truncated at key end
+ eval { $coder->decode('{a') };
+ $err = $@;
+ ok($err, 'truncated bare key {a errors');
+ like($err, qr/expected|truncated|':'/i, 'truncated bare key: sensible
error');
+
+ # bare key followed by truncated value
+ eval { $coder->decode('{ab:') };
+ $err = $@;
+ ok($err, 'truncated bare key {ab: errors');
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/t/19_incr.t
new/Cpanel-JSON-XS-4.41/t/19_incr.t
--- old/Cpanel-JSON-XS-4.40/t/19_incr.t 2022-05-03 13:12:46.000000000 +0200
+++ new/Cpanel-JSON-XS-4.41/t/19_incr.t 2026-05-27 20:00:10.000000000 +0200
@@ -2,7 +2,7 @@
use strict;
no warnings;
-use Test::More $] < 5.008 ? (tests => 39) : (tests => 702);
+use Test::More $] < 5.008 ? (tests => 39) : (tests => 713);
use Cpanel::JSON::XS;
@@ -110,3 +110,51 @@
is (encode_json($coder->incr_parse($text)), '[1]', "incr_parse1");
is (encode_json($coder->incr_parse), '[5]', "incr_parse2");
}
+
+# allow_singlequote: } inside single-quoted string must not close the object
+{
+ my $coder = Cpanel::JSON::XS->new->allow_singlequote(1);
+
+ # feed partial input: the } is inside the single-quoted value, must not
trigger done
+ ok (!defined $coder->incr_parse("{'a':'}'"), "sqstr-incr: } inside
single-quote does not close object");
+
+ # complete the object
+ my $r = $coder->incr_parse("}");
+ ok (defined $r, "sqstr-incr: object completes after closing brace");
+ is_deeply ($r, {a => "}"}, "sqstr-incr: decoded value correct");
+}
+
+# allow_singlequote: chunked streaming with structural chars inside
single-quoted string
+{
+ my $coder = Cpanel::JSON::XS->new->allow_singlequote(1);
+
+ # feed one byte at a time to exercise every state transition
+ my $json = "{'x':'}[{'}";
+ my $r;
+ for my $ch (split //, $json) {
+ $r = $coder->incr_parse($ch);
+ }
+ ok (defined $r, "sqstr-incr chunked: defined result");
+ is_deeply ($r, {x => "}[{"}, "sqstr-incr chunked: decoded value correct");
+}
+
+# allow_singlequote: backslash inside single-quoted string does not cause
premature end
+{
+ my $coder = Cpanel::JSON::XS->new->allow_singlequote(1);
+
+ ok (!defined $coder->incr_parse("{'k':'a\\'"), "sqstr-incr BS: partial with
escaped quote waits");
+ my $r = $coder->incr_parse("b'}");
+ ok (defined $r, "sqstr-incr BS: completes after full input");
+ is_deeply ($r, {k => "a'b"}, "sqstr-incr BS: decoded value correct");
+}
+
+# allow_singlequote: single-quoted array element containing structural chars
+{
+ my $coder = Cpanel::JSON::XS->new->allow_singlequote(1);
+ my $r;
+ $r = $coder->incr_parse("['he");
+ ok (!defined $r, "sqstr-incr array: partial waits");
+ $r = $coder->incr_parse("llo}']");
+ ok (defined $r, "sqstr-incr array: completes");
+ is_deeply ($r, ['hello}'], "sqstr-incr array: value correct");
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/t/26_duplicate.t
new/Cpanel-JSON-XS-4.41/t/26_duplicate.t
--- old/Cpanel-JSON-XS-4.40/t/26_duplicate.t 2022-05-06 07:40:07.000000000
+0200
+++ new/Cpanel-JSON-XS-4.41/t/26_duplicate.t 2026-05-27 20:00:10.000000000
+0200
@@ -1,5 +1,5 @@
use strict;
-use Test::More tests => 12;
+use Test::More tests => 17;
use Cpanel::JSON::XS;
my $json = Cpanel::JSON::XS->new;
@@ -47,3 +47,33 @@
'dupkeys_as_arrayref to []');
is (encode_json ($json->decode ('{"a":["b","c"],"a":["c"]}')),
'{"a":[["b","c"],["c"]]}',
'dupkeys_as_arrayref to [[]]');
+
+# fast path: short ASCII keys
+is_deeply ($json->decode ('{"a":1,"a":2,"b":3,"b":4}'),
+ { a => [1, 2], b => [3, 4] },
+ 'dupkeys_as_arrayref: two distinct duplicated keys, fast path');
+
+# slow path: keys longer than 24 bytes force _decode_str
+{
+ my $k1 = 'a' x 30;
+ my $k2 = 'b' x 30;
+ my $in = qq({"$k1":1,"$k1":2,"$k2":3,"$k2":4});
+ is_deeply ($json->decode ($in),
+ { $k1 => [1, 2], $k2 => [3, 4] },
+ 'dupkeys_as_arrayref: two distinct duplicated keys, slow path');
+}
+
+# three distinct duplicated keys - confirms fix past the first transition
+is_deeply ($json->decode ('{"a":1,"a":2,"b":3,"b":4,"c":5,"c":6}'),
+ { a => [1, 2], b => [3, 4], c => [5, 6] },
+ 'dupkeys_as_arrayref: three distinct duplicated keys');
+
+# triple duplicate of a second key - further dups should append, not re-wrap
+is_deeply ($json->decode ('{"a":1,"a":2,"b":3,"b":4,"b":5}'),
+ { a => [1, 2], b => [3, 4, 5] },
+ 'dupkeys_as_arrayref: triple dup of second key');
+
+# pre-existing arrayref values combine correctly across multiple keys
+is_deeply ($json->decode ('{"a":["x"],"a":"y","b":["p"],"b":"q"}'),
+ { a => [['x'], 'y'], b => [['p'], 'q'] },
+ 'dupkeys_as_arrayref: existing array values, two distinct keys');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Cpanel-JSON-XS-4.40/t/31_bom.t
new/Cpanel-JSON-XS-4.41/t/31_bom.t
--- old/Cpanel-JSON-XS-4.40/t/31_bom.t 2022-05-03 13:12:46.000000000 +0200
+++ new/Cpanel-JSON-XS-4.41/t/31_bom.t 2026-05-27 20:00:10.000000000 +0200
@@ -2,7 +2,7 @@
#
# https://tools.ietf.org/html/rfc7159#section-8.1
# JSON text SHALL be encoded in UTF-8, UTF-16, or UTF-32.
-use Test::More ($] >= 5.008) ? (tests => 9) : (skip_all => "needs 5.8");;
+use Test::More ($] >= 5.008) ? (tests => 9 + 6) : (skip_all => "needs 5.8");;
use Cpanel::JSON::XS;
use Encode; # Currently required for <5.20
use charnames qw(:short);
@@ -41,3 +41,50 @@
ok(eval { $j->decode($as_json) }, 'can decode again');
ok(eval { $j->decode("\x{feff}" . $as_json) }, 'can decode with BOM');
ok(eval { $j->decode($as_json) }, 'can decode original');
+
+# Tests by Paul Johnson:
+
+# Assert the caller's input SV is preserved bit-for-bit across a decode
+# call whose filter callback throws, for each of the three croak-reachable
+# callback sites (filter_json_object, filter_json_single_key_object, and
+# allow_tags + THAW), with a leading UTF-8 BOM on the input.
+
+my $bom = "\xef\xbb\xbf";
+
+sub assert_preserved {
+ my ($name, $payload, $setup) = @_;
+ my $original = $bom . $payload;
+ my $s = $bom . $payload;
+ my $j = Cpanel::JSON::XS->new;
+ $setup->($j);
+ eval { $j->decode ($s) };
+ ok ($@, "$name: callback threw");
+ # The BOM-decode path legitimately sets SvUTF8 on the caller's SV.
+ # We care about the underlying byte sequence (no SvPVX shift), not
+ # the flag, so clear SvUTF8 on a copy and compare raw bytes.
+ my $copy = $s;
+ Encode::_utf8_off ($copy);
+ is ($copy, $original, "$name: SV bytes preserved across throw");
+}
+
+assert_preserved (
+ "filter_json_object",
+ '{}',
+ sub { $_[0]->filter_json_object (sub { die "boom\n" }) },
+);
+
+assert_preserved (
+ "filter_json_single_key_object",
+ '{"k":1}',
+ sub { $_[0]->filter_json_single_key_object (k => sub { die "boom\n" }) },
+);
+
+{
+ package BomFilterCorruption::Thaw;
+ sub THAW { die "boom\n" }
+}
+assert_preserved (
+ "allow_tags THAW",
+ '("BomFilterCorruption::Thaw")[]',
+ sub { $_[0]->allow_tags (1) },
+);
++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.Axe8ku/_old 2026-06-03 20:30:27.237191143 +0200
+++ /var/tmp/diff_new_pack.Axe8ku/_new 2026-06-03 20:30:27.245191475 +0200
@@ -1,6 +1,6 @@
-mtime: 1757351017
-commit: 8bf9656a284497e3756b5e3b0057cec36ffe9828d8cace5e2beea00487cc3673
-url: https://src.opensuse.org/perl/perl-Cpanel-JSON-XS.git
-revision: 8bf9656a284497e3756b5e3b0057cec36ffe9828d8cace5e2beea00487cc3673
+mtime: 1779958415
+commit: 06d5182b5f0a2350b0d78e9abcc91c7a661926ee49d2df426628bbf170461d5d
+url: https://src.opensuse.org/perl/perl-Cpanel-JSON-XS
+revision: 06d5182b5f0a2350b0d78e9abcc91c7a661926ee49d2df426628bbf170461d5d
projectscmsync: https://src.opensuse.org/perl/_ObsPrj
++++++ build.specials.obscpio ++++++
++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore 1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore 2026-05-28 10:53:35.000000000 +0200
@@ -0,0 +1 @@
+.osc