diff --git a/.fmf/version b/.fmf/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/XML-Parser-2.48-CVE-2006-10002.patch b/XML-Parser-2.48-CVE-2006-10002.patch new file mode 100644 index 0000000..03b4163 --- /dev/null +++ b/XML-Parser-2.48-CVE-2006-10002.patch @@ -0,0 +1,106 @@ +From 5361c2b7f48599718cdecbe50c5fdd88b28ffd79 Mon Sep 17 00:00:00 2001 +From: Toddr Bot +Date: Mon, 16 Mar 2026 20:55:31 +0000 +Subject: [PATCH] Fix buffer overflow in parse_stream when filehandle has :utf8 + layer + +When a filehandle has a :utf8 PerlIO layer, Perl's read() returns +decoded characters, but SvPV() gives back the UTF-8 byte +representation which can be larger than the pre-allocated XML buffer. +Previously this caused heap corruption (double free / buffer overflow), +and a later workaround (BUFSIZE * 6 + croak) prevented the corruption +but still crashed. + +Fix by re-obtaining the expat buffer at the actual byte size when the +read produces more bytes than initially allocated. This handles UTF-8 +streams gracefully without wasting memory on an oversized buffer. + +Fixes https://github.com/cpan-authors/XML-Parser/issues/64 +(migrated from rt.cpan.org #19859) + +Co-Authored-By: Claude Opus 4.6 +--- + Expat/Expat.xs | 15 +++++++++++---- + t/utf8_stream.t | 40 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+), 4 deletions(-) + create mode 100644 t/utf8_stream.t + +diff --git a/Expat/Expat.xs b/Expat/Expat.xs +index 32fdce5..3cd1154 100644 +--- a/Expat/Expat.xs ++++ b/Expat/Expat.xs +@@ -343,8 +343,8 @@ parse_stream(XML_Parser parser, SV * ioref) + } + else { + tbuff = newSV(0); +- tsiz = newSViv(BUFSIZE); /* in UTF-8 characters */ +- buffsize = BUFSIZE * 6; /* in bytes that encode an UTF-8 string */ ++ tsiz = newSViv(BUFSIZE); ++ buffsize = BUFSIZE; + } + + while (! done) +@@ -387,8 +387,15 @@ parse_stream(XML_Parser parser, SV * ioref) + + tb = SvPV(tbuff, br); + if (br > 0) { +- if (br > buffsize) +- croak("The input buffer is not large enough for read UTF-8 decoded string"); ++ if (br > buffsize) { ++ /* The byte count from SvPV can exceed buffsize when the ++ filehandle has a :utf8 layer, since Perl reads buffsize ++ characters but multi-byte UTF-8 chars produce more bytes. ++ Re-obtain the buffer at the required size. */ ++ buffer = XML_GetBuffer(parser, br); ++ if (! buffer) ++ croak("Ran out of memory for input buffer"); ++ } + Copy(tb, buffer, br, char); + } else + done = 1; +diff --git a/t/utf8_stream.t b/t/utf8_stream.t +new file mode 100644 +index 0000000..a7e55f7 +--- /dev/null ++++ b/t/utf8_stream.t +@@ -0,0 +1,40 @@ ++BEGIN { print "1..2\n"; } ++END { print "not ok 1\n" unless $loaded; } ++use XML::Parser; ++$loaded = 1; ++print "ok 1\n"; ++ ++################################################################ ++# Test parsing from a filehandle with :utf8 layer ++# Regression test for rt.cpan.org #19859 / GitHub issue #64 ++# A UTF-8 stream caused buffer overflow because SvPV byte count ++# could exceed the pre-allocated XML_GetBuffer size. ++ ++use File::Temp qw(tempfile); ++ ++# Create a temp file with UTF-8 XML content containing multi-byte chars ++my ($fh, $tmpfile) = tempfile(UNLINK => 1); ++binmode($fh, ':raw'); ++# Write raw UTF-8 bytes: XML with Chinese characters (3 bytes each in UTF-8) ++# U+4E16 U+754C (世界 = "world") repeated to create substantial multi-byte content ++my $body = "\xe4\xb8\x96\xe7\x95\x8c" x 20000; # 120000 bytes / 40000 chars of 3-byte UTF-8 ++print $fh qq(\n$body\n); ++close($fh); ++ ++my $text = ''; ++my $parser = XML::Parser->new( ++ Handlers => { ++ Char => sub { $text .= $_[1]; }, ++ } ++); ++ ++# Open with :utf8 layer - this is what triggers the bug ++open(my $in, '<:utf8', $tmpfile) or die "Cannot open $tmpfile: $!"; ++eval { $parser->parse($in); }; ++close($in); ++ ++if ($@ eq '' && length($text) > 0) { ++ print "ok 2\n"; ++} else { ++ print "not ok 2 # $@\n"; ++} diff --git a/XML-Parser-2.48-CVE-2006-10003.patch b/XML-Parser-2.48-CVE-2006-10003.patch new file mode 100644 index 0000000..ed2124c --- /dev/null +++ b/XML-Parser-2.48-CVE-2006-10003.patch @@ -0,0 +1,66 @@ +From 08dd37c35ec5e64e26aacb8514437f54708f7fd1 Mon Sep 17 00:00:00 2001 +From: Toddr Bot +Date: Mon, 16 Mar 2026 22:16:11 +0000 +Subject: [PATCH] fix: off-by-one heap buffer overflow in st_serial_stack + growth check + +When st_serial_stackptr == st_serial_stacksize - 1, the old check +(stackptr >= stacksize) would not trigger reallocation. The subsequent +++stackptr then writes at index stacksize, one element past the +allocated buffer. + +Fix by checking stackptr + 1 >= stacksize so the buffer is grown +before the pre-increment write. + +Add a deep nesting test (600 levels) to exercise this code path. + +Fixes #39 + +Co-Authored-By: Claude Opus 4.6 +--- + Expat/Expat.xs | 2 +- + t/deep_nesting.t | 22 ++++++++++++++++++++++ + 2 files changed, 23 insertions(+), 1 deletion(-) + create mode 100644 t/deep_nesting.t + +diff --git a/Expat/Expat.xs b/Expat/Expat.xs +index 5f9b193..0226a24 100644 +--- a/Expat/Expat.xs ++++ b/Expat/Expat.xs +@@ -514,7 +514,7 @@ startElement(void *userData, const char *name, const char **atts) + } + } + +- if (cbv->st_serial_stackptr >= cbv->st_serial_stacksize) { ++ if (cbv->st_serial_stackptr + 1 >= cbv->st_serial_stacksize) { + unsigned int newsize = cbv->st_serial_stacksize + 512; + + Renew(cbv->st_serial_stack, newsize, unsigned int); +diff --git a/t/deep_nesting.t b/t/deep_nesting.t +new file mode 100644 +index 0000000..8237b5f +--- /dev/null ++++ b/t/deep_nesting.t +@@ -0,0 +1,22 @@ ++BEGIN { print "1..1\n"; } ++ ++# Test for deeply nested elements to exercise st_serial_stack reallocation. ++# This catches off-by-one errors in the stack growth check (GH #39). ++ ++use XML::Parser; ++ ++my $depth = 600; ++ ++my $xml = ''; ++for my $i (1 .. $depth) { ++ $xml .= ""; ++} ++for my $i (reverse 1 .. $depth) { ++ $xml .= ""; ++} ++ ++my $p = XML::Parser->new; ++eval { $p->parse($xml) }; ++ ++print "not " if $@; ++print "ok 1\n"; diff --git a/gating.yaml b/gating.yaml new file mode 100644 index 0000000..1608530 --- /dev/null +++ b/gating.yaml @@ -0,0 +1,7 @@ +# RHEL +--- !Policy +product_versions: + - rhel-* +decision_context: osci_compose_gate +rules: + - !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional} diff --git a/perl-XML-Parser.spec b/perl-XML-Parser.spec index 1809c72..ba5f702 100644 --- a/perl-XML-Parser.spec +++ b/perl-XML-Parser.spec @@ -1,6 +1,6 @@ Name: perl-XML-Parser Version: 2.44 -Release: 11%{?dist} +Release: 12%{?dist} Summary: Perl module for parsing XML documents Group: Development/Libraries @@ -10,6 +10,12 @@ Source0: http://search.cpan.org/CPAN/authors/id/T/TO/TODDR/XML-Parser-%{v # Fix a buffer overwrite in parse_stream() with wide characters on the standard # input, bug #1658512, CPAN RT#128006 Patch0: XML-Parser-2.44_01-Fix-a-buffer-overwrite-in-parse_stream.patch +# Fix buffer overflow in parse_stream when filehandle has :utf8 +# CVE-2006-10002 +Patch1: XML-Parser-2.48-CVE-2006-10002.patch +# Fix off-by-one heap buffer overflow in st_serial_stack growth check +# CVE-2006-10003 +Patch2: XML-Parser-2.48-CVE-2006-10003.patch BuildRequires: perl-devel BuildRequires: perl-generators @@ -53,13 +59,15 @@ creation time. %prep %setup -q -n XML-Parser-%{version} -%patch0 -p1 +%patch -P0 -p1 +%patch -P1 -p1 +%patch -P2 -p1 chmod 644 samples/{canonical,xml*} perl -pi -e 's|^#!/usr/local/bin/perl\b|#!%{__perl}|' samples/{canonical,xml*} # Remove bundled library rm -r inc -sed -i -e '/^inc\// d' MANIFEST +perl -i -ne 'print $_ unless m{^inc/}' MANIFEST %build CFLAGS="$RPM_OPT_FLAGS" perl Makefile.PL INSTALLDIRS=vendor @@ -88,6 +96,9 @@ make test %changelog +* Thu Mar 26 2026 Jitka Plesnikova - 2.44-12 +- Fix CVE-2006-10002, CVE-2006-10003 + * Thu Dec 13 2018 Petr Pisar - 2.44-11 - Fix a buffer overwrite in parse_stream() with wide characters on the standard input (bug #1658512) diff --git a/plans/internal.fmf b/plans/internal.fmf new file mode 100644 index 0000000..ba5d0db --- /dev/null +++ b/plans/internal.fmf @@ -0,0 +1,12 @@ +summary: Private (RHEL) beakerlib tests +enabled: false +adjust: + - when: distro == rhel + enabled: true + because: private tests are accesible only within rhel pipeline +discover: + - name: rhel + how: fmf + url: https://pkgs.devel.redhat.com/git/tests/perl-XML-Parser +execute: + how: tmt