Fix CVE-2006-10002, CVE-2006-10003

This commit is contained in:
Jitka Plesnikova 2026-03-27 10:20:26 +01:00
parent 25a18d3d2a
commit 562dc618d6
6 changed files with 206 additions and 3 deletions

1
.fmf/version Normal file
View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,106 @@
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";
+}

View File

@ -0,0 +1,66 @@
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";

7
gating.yaml Normal file
View File

@ -0,0 +1,7 @@
# RHEL
--- !Policy
product_versions:
- rhel-*
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

View File

@ -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 <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
- Fix a buffer overwrite in parse_stream() with wide characters on the standard
input (bug #1658512)

12
plans/internal.fmf Normal file
View File

@ -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