Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -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 <packages@deepin.org> Tue, 09 Jun 2026 09:48:53 +0800

libhtml-parser-perl (3.76-1) unstable; urgency=medium

* Team upload.
Expand Down
104 changes: 104 additions & 0 deletions debian/patches/CVE-2026-8829.patch
Original file line number Diff line number Diff line change
@@ -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&aring;re norske tegn b&oslash;r &#230res";

@@ -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 <bill.simpson-young@cmis.csiro.au>
# Subject: HTML entities problem with 5.11
# To: libwww-perl@ics.uci.edu
1 change: 1 addition & 0 deletions debian/patches/series
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
debian_examples_location.patch
CVE-2026-8829.patch
Loading