Version in base suite: 1.34-2+deb13u1 Base version: libyaml-syck-perl_1.34-2+deb13u1 Target version: libyaml-syck-perl_1.34-2+deb13u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/liby/libyaml-syck-perl/libyaml-syck-perl_1.34-2+deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/liby/libyaml-syck-perl/libyaml-syck-perl_1.34-2+deb13u2.dsc changelog | 7 patches/fix-address-all-4-C-layer-audit-findings-from-issue-.patch | 269 ++++++++++ patches/series | 1 3 files changed, 277 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpa9ws7y7g/libyaml-syck-perl_1.34-2+deb13u1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpa9ws7y7g/libyaml-syck-perl_1.34-2+deb13u2.dsc: no acceptable signature found diff -Nru libyaml-syck-perl-1.34/debian/changelog libyaml-syck-perl-1.34/debian/changelog --- libyaml-syck-perl-1.34/debian/changelog 2025-10-17 04:18:57.000000000 +0000 +++ libyaml-syck-perl-1.34/debian/changelog 2026-03-21 18:13:45.000000000 +0000 @@ -1,3 +1,10 @@ +libyaml-syck-perl (1.34-2+deb13u2) trixie-security; urgency=high + + * Non-maintainer upload by the Security Team. + * fix: address all 4 C-layer audit findings from issue #67 (CVE-2026-4177) + + -- Salvatore Bonaccorso Sat, 21 Mar 2026 19:13:45 +0100 + libyaml-syck-perl (1.34-2+deb13u1) trixie; urgency=medium * Team upload. diff -Nru libyaml-syck-perl-1.34/debian/patches/fix-address-all-4-C-layer-audit-findings-from-issue-.patch libyaml-syck-perl-1.34/debian/patches/fix-address-all-4-C-layer-audit-findings-from-issue-.patch --- libyaml-syck-perl-1.34/debian/patches/fix-address-all-4-C-layer-audit-findings-from-issue-.patch 1970-01-01 00:00:00.000000000 +0000 +++ libyaml-syck-perl-1.34/debian/patches/fix-address-all-4-C-layer-audit-findings-from-issue-.patch 2026-03-21 18:13:45.000000000 +0000 @@ -0,0 +1,269 @@ +From: Toddr Bot +Date: Sat, 14 Mar 2026 07:18:00 +0000 +Subject: fix: address all 4 C-layer audit findings from issue #67 +Origin: https://github.com/cpan-authors/YAML-Syck/commit/e8844a31c8cf0052914b198fc784ed4e6b8ae69e +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2026-4177 + +- HIGH: Fix heap buffer overflow in emitter tag buffer. The 512-byte + fixed allocation overflowed via strcat(tag, ref) with long class names. + Now tracks buffer size and grows dynamically with Renew() when needed. + +- MEDIUM: Fix base64 decoder reading past buffer end on trailing + newlines. Added s < send guard to the inner whitespace-skip loop. + +- MEDIUM: Replace strtok(id, "/:") with savepv copy + strtok at all 6 + call sites in the parser handler. strtok mutated n->type_id in place, + corrupting shared node data. Each site now operates on a local copy + that is freed after use. + +- LOW: Fix memory leak in syck_hdlr_add_anchor when a node already has + an anchor. The incoming anchor string 'a' was leaked on early return. + +Closes #67 + +Co-Authored-By: Claude Opus 4.6 +--- + emitter.c | 3 ++- + handler.c | 1 + + perl_common.h | 1 + + perl_syck.h | 36 +++++++++++++++++++++++++++++------- + t/tag-overflow.t | 44 ++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 77 insertions(+), 8 deletions(-) + create mode 100644 t/tag-overflow.t + +diff --git a/emitter.c b/emitter.c +index cd8150b107fc..da3c91b94372 100644 +--- a/emitter.c ++++ b/emitter.c +@@ -80,7 +80,8 @@ syck_base64dec( char *s, long len, long *out_len ) + } + } + while (s < send) { +- while (s[0] == '\r' || s[0] == '\n') { s++; } ++ while (s < send && (s[0] == '\r' || s[0] == '\n')) { s++; } ++ if (s >= send) break; + if ((a = b64_xtable[(int)s[0]]) == -1) break; + if ((b = b64_xtable[(int)s[1]]) == -1) break; + if ((c = b64_xtable[(int)s[2]]) == -1) break; +diff --git a/handler.c b/handler.c +index 5de4359a142e..48341a99edf6 100644 +--- a/handler.c ++++ b/handler.c +@@ -40,6 +40,7 @@ syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n ) + * Happens if you have two anchors after each other or an anchor + * before an alias + * */ ++ S_FREE(a); + return n; + } + n->anchor = a; +diff --git a/perl_common.h b/perl_common.h +index 451223731108..bc9924b5a9ac 100644 +--- a/perl_common.h ++++ b/perl_common.h +@@ -37,6 +37,7 @@ struct emitter_xtra { + PerlIO* outio; + } out; + char* tag; ++ STRLEN tag_len; + char dump_code; + bool implicit_binary; + int ioerror; +diff --git a/perl_syck.h b/perl_syck.h +index 14cd311bef8f..1b00bd6c58de 100644 +--- a/perl_syck.h ++++ b/perl_syck.h +@@ -332,7 +332,8 @@ yaml_syck_parser_handler + + } else if (strnEQ( n->data.str->ptr, REF_LITERAL, 1+REF_LITERAL_LENGTH)) { + /* type tag in a scalar ref */ +- char *lang = strtok(id, "/:"); ++ char *id_copy = savepv(id); ++ char *lang = strtok(id_copy, "/:"); + char *type = strtok(NULL, ""); + + if (lang == NULL || (strEQ(lang, "perl"))) { +@@ -341,6 +342,7 @@ yaml_syck_parser_handler + else { + sv = newSVpv(form((type == NULL) ? "%s" : "%s::%s", lang, type), 0); + } ++ Safefree(id_copy); + } else if ( strEQ( id, "perl/scalar" ) || strnEQ( id, "perl/scalar:", 12 ) ) { + char *pkg = id + 12; + +@@ -362,7 +364,8 @@ yaml_syck_parser_handler + } else if ( (strEQ(id, "perl/regexp") || strnEQ( id, "perl/regexp:", 12 ) ) ) { + dSP; + SV *val = newSVpvn(n->data.str->ptr, n->data.str->len); +- char *lang = strtok(id, "/:"); ++ char *id_copy = savepv(id); ++ char *lang = strtok(id_copy, "/:"); + char *type = strtok(NULL, ""); + + ENTER; +@@ -396,6 +399,7 @@ yaml_syck_parser_handler + sv_bless(sv, gv_stashpv(form((type == NULL) ? "%s" : "%s::%s", lang, type), TRUE)); + } + } ++ Safefree(id_copy); + #endif /* PERL_LOADMOD_NOIMPORT */ + #endif /* !YAML_IS_JSON */ + } else { +@@ -427,7 +431,8 @@ yaml_syck_parser_handler + + if (id) { + /* bless it if necessary */ +- char *lang = strtok(id, "/:"); ++ char *id_copy = savepv(id); ++ char *lang = strtok(id_copy, "/:"); + char *type = strtok(NULL, ""); + + if ( type != NULL ) { +@@ -435,7 +440,7 @@ yaml_syck_parser_handler + /* !perl/array:Foo::Bar blesses into Foo::Bar */ + type += 6; + } +- ++ + /* FIXME deprecated - here compatibility with @Foo::Bar style blessing */ + while ( *type == '@' ) { type++; } + } +@@ -451,6 +456,7 @@ yaml_syck_parser_handler + sv_bless(sv, gv_stashpv(form((type == NULL) ? "%s" : "%s::%s", lang, type), TRUE)); + } + } ++ Safefree(id_copy); + } + #endif + break; +@@ -480,7 +486,8 @@ yaml_syck_parser_handler + } + else { + /* bless it if necessary */ +- char *lang = strtok(id, "/:"); ++ char *id_copy = savepv(id); ++ char *lang = strtok(id_copy, "/:"); + char *type = strtok(NULL, ""); + + if ( type != NULL && strnEQ(type, "ref:", 4)) { +@@ -496,6 +503,7 @@ yaml_syck_parser_handler + else { + sv_bless(sv, gv_stashpv(form((type == NULL) ? "%s" : "%s::%s", lang, type), TRUE)); + } ++ Safefree(id_copy); + } + } + } +@@ -527,7 +535,8 @@ yaml_syck_parser_handler + } + else { + /* bless it if necessary */ +- char *lang = strtok(id, "/:"); ++ char *id_copy = savepv(id); ++ char *lang = strtok(id_copy, "/:"); + char *type = strtok(NULL, ""); + + if ( type != NULL && strnEQ(type, "regexp:", 7)) { +@@ -544,6 +553,7 @@ yaml_syck_parser_handler + else { + sv_bless(sv, gv_stashpv(form((type == NULL) ? "%s" : "%s::%s", lang, type), TRUE)); + } ++ Safefree(id_copy); + } + } + } +@@ -579,7 +589,8 @@ yaml_syck_parser_handler + #ifndef YAML_IS_JSON + if (id) { + /* bless it if necessary */ +- char *lang = strtok(id, "/:"); ++ char *id_copy = savepv(id); ++ char *lang = strtok(id_copy, "/:"); + char *type = strtok(NULL, ""); + + if ( type != NULL ) { +@@ -602,6 +613,7 @@ yaml_syck_parser_handler + sv_bless(sv, gv_stashpv(form((type == NULL) ? "%s" : "%s::%s", lang, type), TRUE)); + } + } ++ Safefree(id_copy); + } + #endif + } +@@ -960,6 +972,15 @@ yaml_syck_emitter_handler + #endif + } + } ++ { ++ /* Grow tag buffer if ref won't fit (prevents heap overflow) */ ++ STRLEN need = strlen(tag) + strlen(ref) + 1; ++ if (need > bonus->tag_len) { ++ Renew(bonus->tag, need, char); ++ bonus->tag_len = need; ++ tag = bonus->tag; ++ } ++ } + strcat(tag, ref); + } + #endif +@@ -1284,6 +1305,7 @@ DumpYAMLImpl + emitter->anchor_format = "%d"; + + New(801, bonus->tag, 512, char); ++ bonus->tag_len = 512; + *(bonus->tag) = '\0'; + bonus->dump_code = SvTRUE(use_code) || SvTRUE(dump_code); + bonus->implicit_binary = SvTRUE(implicit_binary); +diff --git a/t/tag-overflow.t b/t/tag-overflow.t +new file mode 100644 +index 000000000000..8570f130632b +--- /dev/null ++++ b/t/tag-overflow.t +@@ -0,0 +1,44 @@ ++use FindBin; ++BEGIN { push @INC, $FindBin::Bin } ++ ++use TestYAML tests => 6; ++ ++$YAML::Syck::LoadBlessed = 1; ++ ++# Test that Dump handles objects with very long class names without crashing. ++# This exercises the dynamic tag buffer growth added to prevent a heap overflow ++# when class names exceed the initial 512-byte allocation. ++ ++my $short_class = 'A' x 100; ++my $long_class = 'B' x 600; # exceeds initial 512-byte tag buffer ++my $huge_class = 'C' x 2000; ++ ++# Short class name (fits in initial buffer) ++{ ++ my $obj = bless {}, $short_class; ++ my $yaml = Dump($obj); ++ like($yaml, qr/!!perl\/hash:\Q$short_class\E/, "dump short class name ($short_class)"); ++ ++ my $rt = Load($yaml); ++ is(ref($rt), $short_class, "roundtrip short class name"); ++} ++ ++# Long class name (exceeds 512-byte buffer) ++{ ++ my $obj = bless {}, $long_class; ++ my $yaml = Dump($obj); ++ like($yaml, qr/!!perl\/hash:\Q$long_class\E/, "dump long class name (600 chars)"); ++ ++ my $rt = Load($yaml); ++ is(ref($rt), $long_class, "roundtrip long class name"); ++} ++ ++# Huge class name ++{ ++ my $obj = bless {}, $huge_class; ++ my $yaml = Dump($obj); ++ like($yaml, qr/!!perl\/hash:\Q$huge_class\E/, "dump huge class name (2000 chars)"); ++ ++ my $rt = Load($yaml); ++ is(ref($rt), $huge_class, "roundtrip huge class name"); ++} +-- +2.53.0 + diff -Nru libyaml-syck-perl-1.34/debian/patches/series libyaml-syck-perl-1.34/debian/patches/series --- libyaml-syck-perl-1.34/debian/patches/series 2025-10-17 04:18:57.000000000 +0000 +++ libyaml-syck-perl-1.34/debian/patches/series 2026-03-21 18:13:45.000000000 +0000 @@ -1,2 +1,3 @@ disable-compiler-check.patch Address-memory-corruption-leading-to-str-value-being.patch +fix-address-all-4-C-layer-audit-findings-from-issue-.patch