Compare commits
No commits in common. "c8" and "c8-beta" have entirely different histories.
@ -1,106 +0,0 @@
|
|||||||
From 5361c2b7f48599718cdecbe50c5fdd88b28ffd79 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Toddr Bot <toddbot@rinaldo.us>
|
|
||||||
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 <noreply@anthropic.com>
|
|
||||||
---
|
|
||||||
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(<?xml version="1.0" encoding="UTF-8"?>\n<doc>$body</doc>\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";
|
|
||||||
+}
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
From 08dd37c35ec5e64e26aacb8514437f54708f7fd1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Toddr Bot <toddbot@rinaldo.us>
|
|
||||||
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 <noreply@anthropic.com>
|
|
||||||
---
|
|
||||||
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 .= "<e$i>";
|
|
||||||
+}
|
|
||||||
+for my $i (reverse 1 .. $depth) {
|
|
||||||
+ $xml .= "</e$i>";
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+my $p = XML::Parser->new;
|
|
||||||
+eval { $p->parse($xml) };
|
|
||||||
+
|
|
||||||
+print "not " if $@;
|
|
||||||
+print "ok 1\n";
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
Name: perl-XML-Parser
|
Name: perl-XML-Parser
|
||||||
Version: 2.44
|
Version: 2.44
|
||||||
Release: 12%{?dist}
|
Release: 11%{?dist}
|
||||||
Summary: Perl module for parsing XML documents
|
Summary: Perl module for parsing XML documents
|
||||||
|
|
||||||
Group: Development/Libraries
|
Group: Development/Libraries
|
||||||
@ -10,29 +10,18 @@ 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
|
# Fix a buffer overwrite in parse_stream() with wide characters on the standard
|
||||||
# input, bug #1658512, CPAN RT#128006
|
# input, bug #1658512, CPAN RT#128006
|
||||||
Patch0: XML-Parser-2.44_01-Fix-a-buffer-overwrite-in-parse_stream.patch
|
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: make
|
|
||||||
BuildRequires: perl-devel
|
BuildRequires: perl-devel
|
||||||
BuildRequires: perl-generators
|
BuildRequires: perl-generators
|
||||||
BuildRequires: perl-interpreter
|
|
||||||
BuildRequires: perl(Carp)
|
BuildRequires: perl(Carp)
|
||||||
BuildRequires: perl(Config)
|
BuildRequires: perl(Config)
|
||||||
BuildRequires: perl(Devel::CheckLib)
|
BuildRequires: perl(Devel::CheckLib)
|
||||||
BuildRequires: perl(DynaLoader)
|
|
||||||
BuildRequires: perl(ExtUtils::MakeMaker)
|
BuildRequires: perl(ExtUtils::MakeMaker)
|
||||||
BuildRequires: perl(FileHandle)
|
BuildRequires: perl(FileHandle)
|
||||||
BuildRequires: perl(File::Temp)
|
|
||||||
BuildRequires: perl(if)
|
BuildRequires: perl(if)
|
||||||
BuildRequires: perl(IO::File)
|
BuildRequires: perl(IO::File)
|
||||||
BuildRequires: perl(IO::Handle)
|
BuildRequires: perl(IO::Handle)
|
||||||
BuildRequires: perl(lib)
|
BuildRequires: perl(lib)
|
||||||
BuildRequires: perl(overload)
|
|
||||||
BuildRequires: perl(strict)
|
BuildRequires: perl(strict)
|
||||||
BuildRequires: perl(Test)
|
BuildRequires: perl(Test)
|
||||||
BuildRequires: perl(Test::More)
|
BuildRequires: perl(Test::More)
|
||||||
@ -64,15 +53,13 @@ creation time.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n XML-Parser-%{version}
|
%setup -q -n XML-Parser-%{version}
|
||||||
%patch -P0 -p1
|
%patch0 -p1
|
||||||
%patch -P1 -p1
|
|
||||||
%patch -P2 -p1
|
|
||||||
chmod 644 samples/{canonical,xml*}
|
chmod 644 samples/{canonical,xml*}
|
||||||
perl -pi -e 's|^#!/usr/local/bin/perl\b|#!%{__perl}|' samples/{canonical,xml*}
|
perl -pi -e 's|^#!/usr/local/bin/perl\b|#!%{__perl}|' samples/{canonical,xml*}
|
||||||
|
|
||||||
# Remove bundled library
|
# Remove bundled library
|
||||||
rm -r inc
|
rm -r inc
|
||||||
perl -i -ne 'print $_ unless m{^inc/}' MANIFEST
|
sed -i -e '/^inc\// d' MANIFEST
|
||||||
|
|
||||||
%build
|
%build
|
||||||
CFLAGS="$RPM_OPT_FLAGS" perl Makefile.PL INSTALLDIRS=vendor
|
CFLAGS="$RPM_OPT_FLAGS" perl Makefile.PL INSTALLDIRS=vendor
|
||||||
@ -101,9 +88,6 @@ make test
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Thu Mar 26 2026 Jitka Plesnikova <jplesnik@redhat.com> - 2.44-12
|
|
||||||
- Fix CVE-2006-10002, CVE-2006-10003
|
|
||||||
|
|
||||||
* Thu Dec 13 2018 Petr Pisar <ppisar@redhat.com> - 2.44-11
|
* Thu Dec 13 2018 Petr Pisar <ppisar@redhat.com> - 2.44-11
|
||||||
- Fix a buffer overwrite in parse_stream() with wide characters on the standard
|
- Fix a buffer overwrite in parse_stream() with wide characters on the standard
|
||||||
input (bug #1658512)
|
input (bug #1658512)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user