diff --git a/debian/changelog b/debian/changelog index d343c84..2d5c476 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +libhtml-parser-perl (3.76-1deepin1) unstable; urgency=medium + + * Fix CVE-2026-8829: heap-use-after-free in _decode_entities + When the input SV passed to _decode_entities is the same SV stored as a + self-referential value in the entity hash, grow_gap() could realloc the + SV's PV buffer, leaving repl pointing at freed memory. Copy the entity + value into an owned buffer when the hash entry SV aliases the input SV. + + -- deepin-ci-robot Tue, 09 Jun 2026 09:48:53 +0800 + libhtml-parser-perl (3.76-1) unstable; urgency=medium * Team upload. diff --git a/debian/patches/CVE-2026-8829.patch b/debian/patches/CVE-2026-8829.patch new file mode 100644 index 0000000..5e586b0 --- /dev/null +++ b/debian/patches/CVE-2026-8829.patch @@ -0,0 +1,104 @@ +Index: repo/util.c +=================================================================== +--- repo.orig/util.c ++++ repo/util.c +@@ -72,6 +72,7 @@ decode_entities(pTHX_ SV* sv, HV* entity + + char *repl; + STRLEN repl_len; ++ char *repl_allocated = 0; + #ifdef UNICODE_HTML_PARSER + char buf[UTF8_MAXLEN]; + int repl_utf8; +@@ -93,6 +94,7 @@ decode_entities(pTHX_ SV* sv, HV* entity + + ent_start = s; + repl = 0; ++ repl_allocated = 0; + + if (s < end && *s == '#') { + UV num = 0; +@@ -188,20 +190,38 @@ decode_entities(pTHX_ SV* sv, HV* entity + (*s == ';' && (svp = hv_fetch(entity2char, ent_name, s - ent_name + 1, 0))) + ) + { +- repl = SvPV(*svp, repl_len); ++ char *src = SvPV(*svp, repl_len); + #ifdef UNICODE_HTML_PARSER + repl_utf8 = SvUTF8(*svp); + #endif ++ if ((SV*)*svp == sv) { ++ /* Self-aliased: hash entry SV == input SV. ++ * grow_gap() may realloc sv's PV later; copy ++ * the entity value into an owned buffer first. ++ * Freed by the repl_allocated cleanup below. */ ++ Newx(repl_allocated, repl_len ? repl_len : 1, char); ++ Copy(src, repl_allocated, repl_len, char); ++ repl = repl_allocated; ++ } else { ++ repl = src; ++ } + } + else if (expand_prefix) { + char *ss = s - 1; + while (ss > ent_name) { + svp = hv_fetch(entity2char, ent_name, ss - ent_name, 0); + if (svp) { +- repl = SvPV(*svp, repl_len); ++ char *src = SvPV(*svp, repl_len); + #ifdef UNICODE_HTML_PARSER + repl_utf8 = SvUTF8(*svp); + #endif ++ if ((SV*)*svp == sv) { ++ Newx(repl_allocated, repl_len ? repl_len : 1, char); ++ Copy(src, repl_allocated, repl_len, char); ++ repl = repl_allocated; ++ } else { ++ repl = src; ++ } + s = ss; + break; + } +@@ -215,7 +235,6 @@ decode_entities(pTHX_ SV* sv, HV* entity + } + + if (repl) { +- char *repl_allocated = 0; + if (s < end && *s == ';') + s++; + t--; /* '&' already copied, undo it */ +Index: repo/t/entities.t +=================================================================== +--- repo.orig/t/entities.t ++++ repo/t/entities.t +@@ -3,7 +3,7 @@ use warnings; + use utf8; + + use HTML::Entities qw(decode_entities encode_entities encode_entities_numeric); +-use Test::More tests => 20; ++use Test::More tests => 21; + + my $x = "Våre norske tegn bør æres"; + +@@ -77,6 +77,21 @@ is($x, $ent); + is($got, (values %hash)[0], "decode_entities() decodes a key properly"); + } + ++# CVE-2026-8829 ++# _decode_entities heap-use-after-free when the input SV is the same SV as ++# a self-referential entity value. The payload must be large enough to ++# force grow_gap() to realloc the SV's PV; the fix copies the entity value ++# into an owned buffer so repl is not left pointing at the freed allocation. ++{ ++ my $prefix_a = "A" x 32; ++ my $suffix_b = "B" x 8192; ++ my %h; ++ $h{foo} = $prefix_a . "&foo;" . $suffix_b; ++ HTML::Entities::_decode_entities($h{foo}, \%h); ++ is($h{foo}, ("A" x 64) . "&foo;" . ("B" x 16384), ++ "_decode_entities() with self-aliased entity hash value"); ++} ++ + # From: Bill Simpson-Young + # Subject: HTML entities problem with 5.11 + # To: libwww-perl@ics.uci.edu diff --git a/debian/patches/series b/debian/patches/series index 79cf579..05bbf9e 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1 +1,2 @@ debian_examples_location.patch +CVE-2026-8829.patch