Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package perl-YAML-Syck for openSUSE:Factory checked in at 2026-07-17 18:49:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-YAML-Syck (Old) and /work/SRC/openSUSE:Factory/.perl-YAML-Syck.new.24530 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-YAML-Syck" Fri Jul 17 18:49:30 2026 rev:44 rq:1366352 version:1.470.0 Changes: -------- --- /work/SRC/openSUSE:Factory/perl-YAML-Syck/perl-YAML-Syck.changes 2026-06-08 14:24:56.212103698 +0200 +++ /work/SRC/openSUSE:Factory/.perl-YAML-Syck.new.24530/perl-YAML-Syck.changes 2026-07-17 18:50:51.448050064 +0200 @@ -1,0 +2,41 @@ +Tue Jul 14 07:27:12 UTC 2026 - Tina Müller <[email protected]> + +- updated to 1.470.0 (1.47) + see /usr/share/doc/packages/perl-YAML-Syck/Changes + + 1.47 Jul 13 2026 + [Security] + - Fix four libsyck memory-safety CVEs reachable from the default + YAML::Syck::Load() path on untrusted input with no special flags + (reported by Paul Johnson via CPANSec, PR #213): + - CVE-2026-57075 (CWE-125): out-of-bounds read in the base64 decoder + caused by signed-char indexing of the decode table on !!binary input + bsc#1271632 + - CVE-2026-57076 (CWE-416): use-after-free of an anchor key string + shared between the node and the anchors table + bsc#1271633 + - CVE-2026-57077 (CWE-125): one-byte out-of-bounds read in the lexer + newline scan during block-scalar parsing (incomplete-fix follow-on + to CVE-2025-11683) + bsc#1271634 + - CVE-2026-13713 (CWE-416/CWE-415): use-after-free / double-free of an + anchor node on anchor redefinition, a remote-crash DoS from a + 7-byte input + bsc#1271631 + - Harden syck_base64dec() to bounds-check each read so it cannot run past + a non-NUL-terminated input buffer (defense-in-depth for callers passing + raw buffers; PR #213) + [Bug Fixes] + - Fix: enforce $MaxDepth on Load to prevent C-stack exhaustion from + deeply nested YAML/JSON input; YAML::Syck and JSON::Syck Load now + default to 512, matching Dump (PR #204) + - Fix: emit YAML canonical forms (.nan, .inf, -.inf) for NaN/Inf values + in Dump so they roundtrip with ImplicitTyping instead of reloading as + plain strings (PR #201) + [Maintenance] + - CI: add an AddressSanitizer job that builds the XS with + -fsanitize=address and runs the suite plus the CVE trigger inputs to + catch libsyck memory-safety defects; de-pin the libasan version so it + tracks the runner's GCC (PR #213) + +------------------------------------------------------------------- Old: ---- YAML-Syck-1.46.tar.gz New: ---- YAML-Syck-1.47.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-YAML-Syck.spec ++++++ --- /var/tmp/diff_new_pack.fuE4eL/_old 2026-07-17 18:50:52.220076162 +0200 +++ /var/tmp/diff_new_pack.fuE4eL/_new 2026-07-17 18:50:52.224076298 +0200 @@ -18,10 +18,10 @@ %define cpan_name YAML-Syck Name: perl-YAML-Syck -Version: 1.460.0 +Version: 1.470.0 Release: 0 -# 1.46 -> normalize -> 1.460.0 -%define cpan_version 1.46 +# 1.47 -> normalize -> 1.470.0 +%define cpan_version 1.47 License: MIT Summary: Perl YAML loader and dumper URL: https://metacpan.org/release/%{cpan_name} ++++++ YAML-Syck-1.46.tar.gz -> YAML-Syck-1.47.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/Changes new/YAML-Syck-1.47/Changes --- old/YAML-Syck-1.46/Changes 2026-05-25 05:02:04.000000000 +0200 +++ new/YAML-Syck-1.47/Changes 2026-07-13 18:16:35.000000000 +0200 @@ -1,3 +1,37 @@ +1.47 Jul 13 2026 + + [Security] + - Fix four libsyck memory-safety CVEs reachable from the default + YAML::Syck::Load() path on untrusted input with no special flags + (reported by Paul Johnson via CPANSec, PR #213): + - CVE-2026-57075 (CWE-125): out-of-bounds read in the base64 decoder + caused by signed-char indexing of the decode table on !!binary input + - CVE-2026-57076 (CWE-416): use-after-free of an anchor key string + shared between the node and the anchors table + - CVE-2026-57077 (CWE-125): one-byte out-of-bounds read in the lexer + newline scan during block-scalar parsing (incomplete-fix follow-on + to CVE-2025-11683) + - CVE-2026-13713 (CWE-416/CWE-415): use-after-free / double-free of an + anchor node on anchor redefinition, a remote-crash DoS from a + 7-byte input + - Harden syck_base64dec() to bounds-check each read so it cannot run past + a non-NUL-terminated input buffer (defense-in-depth for callers passing + raw buffers; PR #213) + + [Bug Fixes] + - Fix: enforce $MaxDepth on Load to prevent C-stack exhaustion from + deeply nested YAML/JSON input; YAML::Syck and JSON::Syck Load now + default to 512, matching Dump (PR #204) + - Fix: emit YAML canonical forms (.nan, .inf, -.inf) for NaN/Inf values + in Dump so they roundtrip with ImplicitTyping instead of reloading as + plain strings (PR #201) + + [Maintenance] + - CI: add an AddressSanitizer job that builds the XS with + -fsanitize=address and runs the suite plus the CVE trigger inputs to + catch libsyck memory-safety defects; de-pin the libasan version so it + tracks the runner's GCC (PR #213) + 1.46 May 24 2026 [Bug Fixes] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/MANIFEST new/YAML-Syck-1.47/MANIFEST --- old/YAML-Syck-1.46/MANIFEST 2026-05-25 05:06:01.000000000 +0200 +++ new/YAML-Syck-1.47/MANIFEST 2026-07-13 18:32:33.000000000 +0200 @@ -38,15 +38,20 @@ t/bug/rt-49404-double_free.t t/bug/rt-54167.t t/croak-leak.t +t/cve-2026-13713-anchor-node-uaf.t +t/cve-2026-57075-base64-oob-read.t +t/cve-2026-57076-anchor-key-uaf.t +t/cve-2026-57077-newline-oob-read.t t/gh-132-base60-safety.t t/gh-193-blessed-alias-tag.t +t/gh-199-preserve-string-type.t t/gh-25-inline-array-no-space.t t/gh-26-implicit-type-roundtrip.t t/gh-28-wide-char-dumpfile.t t/gh-dumpcode-prototype.t t/gh-load-list-context.t t/gh-loadfile-dumpfile-errors.t -t/gh-199-preserve-string-type.t +t/gh-nan-inf-dump.t t/gh-negative-base60.t t/gh-negative-float-base60.t t/gh-negative-hex-oct.t diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/META.json new/YAML-Syck-1.47/META.json --- old/YAML-Syck-1.46/META.json 2026-05-25 05:06:01.000000000 +0200 +++ new/YAML-Syck-1.47/META.json 2026-07-13 18:32:33.000000000 +0200 @@ -39,7 +39,7 @@ "provides" : { "JSON::Syck" : { "file" : "lib/JSON/Syck.pm", - "version" : "1.46" + "version" : "1.47" }, "YAML::Dumper::Syck" : { "file" : "lib/YAML/Dumper/Syck.pm" @@ -49,7 +49,7 @@ }, "YAML::Syck" : { "file" : "lib/YAML/Syck.pm", - "version" : "1.46" + "version" : "1.47" } }, "release_status" : "stable", @@ -67,6 +67,6 @@ "web" : "https://github.com/toddr/YAML-Syck" } }, - "version" : "1.46", + "version" : "1.47", "x_serialization_backend" : "JSON::PP version 4.16" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/META.yml new/YAML-Syck-1.47/META.yml --- old/YAML-Syck-1.46/META.yml 2026-05-25 05:06:01.000000000 +0200 +++ new/YAML-Syck-1.47/META.yml 2026-07-13 18:32:33.000000000 +0200 @@ -20,14 +20,14 @@ provides: JSON::Syck: file: lib/JSON/Syck.pm - version: '1.46' + version: '1.47' YAML::Dumper::Syck: file: lib/YAML/Dumper/Syck.pm YAML::Loader::Syck: file: lib/YAML/Loader/Syck.pm YAML::Syck: file: lib/YAML/Syck.pm - version: '1.46' + version: '1.47' requires: perl: '5.006' resources: @@ -35,5 +35,5 @@ homepage: https://github.com/toddr/YAML-Syck license: https://dev.perl.org/licenses/ repository: https://github.com/toddr/YAML-Syck.git -version: '1.46' +version: '1.47' x_serialization_backend: 'CPAN::Meta::YAML version 0.020' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/README.md new/YAML-Syck-1.47/README.md --- old/YAML-Syck-1.46/README.md 2026-05-25 05:02:30.262275011 +0200 +++ new/YAML-Syck-1.47/README.md 2026-07-13 18:29:52.000000000 +0200 @@ -47,10 +47,11 @@ ## $YAML::Syck::MaxDepth -Maximum nesting depth for `Dump`. Defaults to 512. If a data structure -is nested deeper than this limit, `Dump` will `croak` instead of -overflowing the C stack. Increase this if you legitimately need to -serialize very deeply nested structures. +Maximum nesting depth for `Load` and `Dump`. Defaults to 512. +`Dump` will `croak` if a data structure exceeds this depth, and `Load` +will `croak` if a YAML document is nested deeper than this limit. This +prevents stack exhaustion from maliciously crafted input. Increase the +value if you legitimately need very deeply nested structures. ## $YAML::Syck::Headless diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/emitter.c new/YAML-Syck-1.47/emitter.c --- old/YAML-Syck-1.46/emitter.c 2026-04-23 17:12:20.000000000 +0200 +++ new/YAML-Syck-1.47/emitter.c 2026-07-13 17:43:22.000000000 +0200 @@ -82,10 +82,10 @@ while (s < send) { 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; - if ((d = b64_xtable[(int)s[3]]) == -1) break; + if ((a = b64_xtable[(unsigned char)s[0]]) == -1) break; + if (s + 1 >= send || (b = b64_xtable[(unsigned char)s[1]]) == -1) break; + if (s + 2 >= send || (c = b64_xtable[(unsigned char)s[2]]) == -1) break; + if (s + 3 >= send || (d = b64_xtable[(unsigned char)s[3]]) == -1) break; *end++ = a << 2 | b >> 4; *end++ = b << 4 | c >> 2; *end++ = c << 6 | d; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/handler.c new/YAML-Syck-1.47/handler.c --- old/YAML-Syck-1.46/handler.c 2026-03-16 05:22:19.000000000 +0100 +++ new/YAML-Syck-1.47/handler.c 2026-07-13 17:43:22.000000000 +0200 @@ -27,6 +27,21 @@ return id; } +/* + * A node evicted from the anchors table by redefinition may still be live on + * the parser's value stack, so it cannot be freed here. Keep it for teardown. + */ +void +syck_retire_node( SyckParser *p, SyckNode *n ) +{ + if ( p->retired == NULL ) + { + p->retired = st_init_numtable(); + } + st_insert( p->retired, (st_data_t)( p->retired->num_entries + 1 ), + (st_data_t)n ); +} + SyckNode * syck_hdlr_add_anchor( SyckParser *p, char *a, SyckNode *n ) { @@ -64,10 +79,15 @@ { if ( ntmp != (void *)1 ) { - syck_free_node( ntmp ); + syck_retire_node( p, ntmp ); } + st_insert( p->anchors, (st_data_t)a, (st_data_t)n ); + } + else + { + st_insert( p->anchors, (st_data_t)syck_strndup( a, strlen( a ) ), + (st_data_t)n ); } - st_insert( p->anchors, (st_data_t)a, (st_data_t)n ); return n; } @@ -84,10 +104,12 @@ { if ( ntmp != (void *)1 ) { - syck_free_node( ntmp ); + syck_retire_node( p, ntmp ); } + S_FREE( atmp ); } - st_insert( p->anchors, (st_data_t)a, (st_data_t)1 ); + st_insert( p->anchors, (st_data_t)syck_strndup( a, strlen( a ) ), + (st_data_t)1 ); } SyckNode * @@ -113,7 +135,9 @@ if ( ! st_lookup( p->bad_anchors, (st_data_t)a, (st_data_t *)&n ) ) { n = (p->bad_anchor_handler)( p, a ); - st_insert( p->bad_anchors, (st_data_t)a, (st_data_t)n ); + st_insert( p->bad_anchors, + (st_data_t)syck_strndup( a, strlen( a ) ), + (st_data_t)n ); } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/lib/JSON/Syck.pm new/YAML-Syck-1.47/lib/JSON/Syck.pm --- old/YAML-Syck-1.46/lib/JSON/Syck.pm 2026-05-25 05:02:30.226749660 +0200 +++ new/YAML-Syck-1.47/lib/JSON/Syck.pm 2026-07-13 18:29:52.124754231 +0200 @@ -4,7 +4,7 @@ use Exporter; use YAML::Syck (); -our $VERSION = '1.46'; +our $VERSION = '1.47'; our @EXPORT_OK = qw( Load Dump LoadFile DumpFile DumpInto ); our @ISA = qw/Exporter/; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/lib/YAML/Syck.pm new/YAML-Syck-1.47/lib/YAML/Syck.pm --- old/YAML-Syck-1.46/lib/YAML/Syck.pm 2026-05-25 05:02:30.226964328 +0200 +++ new/YAML-Syck-1.47/lib/YAML/Syck.pm 2026-07-13 18:29:52.000000000 +0200 @@ -10,7 +10,7 @@ use Exporter; use XSLoader (); -our $VERSION = '1.46'; +our $VERSION = '1.47'; our @EXPORT = qw( Dump Load DumpFile LoadFile ); our @EXPORT_OK = qw( DumpInto LoadBytes LoadUTF8 DumpBytes DumpUTF8 ); our @ISA = qw( Exporter ); @@ -233,10 +233,11 @@ =head2 $YAML::Syck::MaxDepth -Maximum nesting depth for C<Dump>. Defaults to 512. If a data structure -is nested deeper than this limit, C<Dump> will C<croak> instead of -overflowing the C stack. Increase this if you legitimately need to -serialize very deeply nested structures. +Maximum nesting depth for C<Load> and C<Dump>. Defaults to 512. +C<Dump> will C<croak> if a data structure exceeds this depth, and C<Load> +will C<croak> if a YAML document is nested deeper than this limit. This +prevents stack exhaustion from maliciously crafted input. Increase the +value if you legitimately need very deeply nested structures. =head2 $YAML::Syck::Headless diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/perl_syck.h new/YAML-Syck-1.47/perl_syck.h --- old/YAML-Syck-1.46/perl_syck.h 2026-05-25 05:00:27.000000000 +0200 +++ new/YAML-Syck-1.47/perl_syck.h 2026-07-13 06:46:00.000000000 +0200 @@ -904,6 +904,7 @@ SV *implicit_unicode = GvSV(gv_fetchpv(form("%s::ImplicitUnicode", PACKAGE_NAME), TRUE, SVt_PV)); SV *singlequote = GvSV(gv_fetchpv(form("%s::SingleQuote", PACKAGE_NAME), TRUE, SVt_PV)); SV *load_blessed = GvSV(gv_fetchpv(form("%s::LoadBlessed", PACKAGE_NAME), TRUE, SVt_PV)); + SV *max_depth = GvSV(gv_fetchpv(form("%s::MaxDepth", PACKAGE_NAME), TRUE, SVt_PV)); json_quote_char = (SvTRUE(singlequote) ? '\'' : '"' ); ENTER; SAVETMPS; @@ -933,6 +934,10 @@ syck_parser_bad_anchor_handler( parser, perl_syck_bad_anchor_handler ); syck_parser_implicit_typing(parser, SvTRUE(implicit_typing)); syck_parser_taguri_expansion(parser, 0); + if (SvIOK(max_depth)) + parser->max_depth = SvIV(max_depth); + else + parser->max_depth = 512; bonus.objects = (AV*)sv_2mortal((SV*)newAV()); bonus.implicit_unicode = SvTRUE(implicit_unicode); @@ -1301,19 +1306,42 @@ } } else if (SvNIOK(sv)) { - /* Stringify the sv, being careful not to overwrite its PV part */ - SV *sv2 = newSVsv(sv); - STRLEN len; - char *str = SvPV(sv2, len); - if (SvIOK(sv) /* original SV was an int */ - && syck_str_is_unquotable_integer(str, len)) /* small enough to safely round-trip */ - { - syck_emit_scalar(e, OBJOF("str"), SCALAR_NUMBER, 0, 0, 0, str, len); - } else { - /* We need to quote it */ - syck_emit_scalar(e, OBJOF("str"), SCALAR_QUOTED, 0, 0, 0, str, len); +#ifndef YAML_IS_JSON + int special_nv = 0; + { + NV nv = SvNV(sv); +#ifdef NV_NAN + if (nv != nv) { + syck_emit_scalar(e, OBJOF("str"), scalar_plain, 0, 0, 0, ".nan", 4); + special_nv = 1; + } +#endif +#ifdef NV_INF + if (!special_nv && nv == NV_INF) { + syck_emit_scalar(e, OBJOF("str"), scalar_plain, 0, 0, 0, ".inf", 4); + special_nv = 1; + } + if (!special_nv && nv == -NV_INF) { + syck_emit_scalar(e, OBJOF("str"), scalar_plain, 0, 0, 0, "-.inf", 5); + special_nv = 1; + } +#endif + } + if (!special_nv) +#endif + { + SV *sv2 = newSVsv(sv); + STRLEN len; + char *str = SvPV(sv2, len); + if (SvIOK(sv) /* original SV was an int */ + && syck_str_is_unquotable_integer(str, len)) /* small enough to safely round-trip */ + { + syck_emit_scalar(e, OBJOF("str"), SCALAR_NUMBER, 0, 0, 0, str, len); + } else { + syck_emit_scalar(e, OBJOF("str"), SCALAR_QUOTED, 0, 0, 0, str, len); + } + SvREFCNT_dec(sv2); } - SvREFCNT_dec(sv2); } else { switch (ty) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/syck.h new/YAML-Syck-1.47/syck.h --- old/YAML-Syck-1.46/syck.h 2026-04-23 17:12:20.000000000 +0200 +++ new/YAML-Syck-1.47/syck.h 2026-07-13 17:43:22.000000000 +0200 @@ -284,12 +284,16 @@ } io; /* Symbol table for anchors */ st_table *anchors, *bad_anchors; + /* Nodes evicted from anchors by redefinition, freed at teardown */ + st_table *retired; /* Optional symbol table for SYMIDs */ st_table *syms; /* Levels of indentation */ SyckLevel *levels; int lvl_idx; int lvl_capa; + /* Maximum nesting depth (0 = no limit) */ + int max_depth; /* Pointer for extension's use */ void *bonus; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/syck_.c new/YAML-Syck-1.47/syck_.c --- old/YAML-Syck-1.46/syck_.c 2026-03-16 06:24:17.000000000 +0100 +++ new/YAML-Syck-1.47/syck_.c 2026-07-13 17:43:22.000000000 +0200 @@ -166,11 +166,13 @@ p->syms = NULL; p->anchors = NULL; p->bad_anchors = NULL; + p->retired = NULL; p->implicit_typing = 1; p->taguri_expansion = 0; p->bufsize = SYCK_BUFFERSIZE; p->buffer = NULL; p->lvl_idx = 0; + p->max_depth = 0; syck_parser_reset_levels( p ); return p; } @@ -199,7 +201,16 @@ syck_st_free_nodes( st_data_t key, st_data_t value, st_data_t arg ) { SyckNode *n = (SyckNode *)value; + char *k = (char *)key; if ( n != (void *)1 ) syck_free_node( n ); + S_FREE( k ); /* the anchor tables own their key strings */ + return ST_CONTINUE; +} + +enum st_retval +syck_st_free_retired( st_data_t key, st_data_t value, st_data_t arg ) +{ + syck_free_node( (SyckNode *)value ); return ST_CONTINUE; } @@ -222,6 +233,13 @@ st_free_table( p->bad_anchors ); p->bad_anchors = NULL; } + + if ( p->retired != NULL ) + { + st_foreach( p->retired, syck_st_free_retired, 0 ); + st_free_table( p->retired ); + p->retired = NULL; + } } void @@ -356,10 +374,15 @@ free( p->levels[p->lvl_idx].domain ); } -void +void syck_parser_add_level( SyckParser *p, int len, enum syck_level_status status ) { ASSERT( p != NULL ); + if ( p->max_depth > 0 && p->lvl_idx >= p->max_depth ) + { + (p->error_handler)(p, "document is nested too deeply"); + return; + } if ( p->lvl_idx + 1 > p->lvl_capa ) { p->lvl_capa += ALLOC_CT; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/t/cve-2026-13713-anchor-node-uaf.t new/YAML-Syck-1.47/t/cve-2026-13713-anchor-node-uaf.t --- old/YAML-Syck-1.46/t/cve-2026-13713-anchor-node-uaf.t 1970-01-01 01:00:00.000000000 +0100 +++ new/YAML-Syck-1.47/t/cve-2026-13713-anchor-node-uaf.t 2026-07-13 17:43:22.000000000 +0200 @@ -0,0 +1,33 @@ +#!perl + +# CVE-2026-13713 - CWE-416 (Use After Free) / CWE-415 (Double Free) +# +# In the bundled libsyck, when an anchor name is redefined or removed, +# syck_hdlr_remove_anchor / syck_hdlr_add_anchor freed the SyckNode that was +# stored under that name (syck_free_node). That node could still be live on +# the parser's value stack, so the grammar reached it again in +# syck_hdlr_add_node (handler.c:17) and freed the same node a second time. +# +# Trigger (7 bytes): YAML::Syck::Load("[&a\x01\n&a") +# +# This is the one defect of the four that faults WITHOUT AddressSanitizer: +# on a normal build the 48-byte node chunk is freed twice and the interpreter +# aborts (heap corruption -> SIGABRT/SIGTRAP). So against an unpatched libsyck +# this whole test file crashes and the harness reports it as failed +# ("Dubious, test returned ... wstat ..."). Once patched, Load() raises an +# ordinary parse error (caught below) and the file passes cleanly. + +use strict; +use warnings; +use Test::More tests => 1; +use YAML::Syck (); + +# The unpatched behaviour is a C-level abort() that eval cannot catch: it takes +# the whole file down before the assertion below and the harness reports the +# file as failed. Patched, Load() croaks on the malformed input, so we assert +# it died with the expected parse error (verifying the graceful failure, not +# merely that the process survived). +eval { YAML::Syck::Load("[&a\x01\n&a") }; + +like( $@, qr/syntax error/, + 'CVE-2026-13713: Load("[&a\\x01\\n&a") croaked with a parse error, not a double-free crash' ); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/t/cve-2026-57075-base64-oob-read.t new/YAML-Syck-1.47/t/cve-2026-57075-base64-oob-read.t --- old/YAML-Syck-1.46/t/cve-2026-57075-base64-oob-read.t 1970-01-01 01:00:00.000000000 +0100 +++ new/YAML-Syck-1.47/t/cve-2026-57075-base64-oob-read.t 2026-07-13 17:43:22.000000000 +0200 @@ -0,0 +1,32 @@ +#!perl + +# CVE-2026-57075 - CWE-125 (Out-of-bounds Read) +# +# syck_base64dec (emitter.c) indexed the 256-entry static b64_xtable with a +# plain signed char from the input: +# if ((a = b64_xtable[(int)s[0]]) == -1) break; +# Any !!binary byte >= 0x80 sign-extends to a NEGATIVE index and reads before +# the table. The fix casts each index to (unsigned char). +# +# Trigger: YAML::Syck::Load("--- !!binary \x80\x80\x80\x80") +# +# The read is non-crashing and its negative index lands in live static memory +# adjacent to b64_xtable rather than an AddressSanitizer redzone, so it neither +# crashes nor trips ASan through Load() (see the CPANSec report). It is still +# observable at runtime: with the fix every byte >= 0x80 maps to -1, so the +# decoder rejects the payload and yields an EMPTY string deterministically; +# without the fix the negative index reads adjacent memory and that garbage can +# surface in the decoded result (on the author's build it decoded to "A" rather +# than ""). So this assertion fails on an unpatched build. The exact unpatched +# value is layout-dependent, but the patched value is always "". + +use strict; +use warnings; +use Test::More tests => 1; +use YAML::Syck (); + +my $decoded = eval { YAML::Syck::Load("--- !!binary \x80\x80\x80\x80") }; + +is( $decoded, '', +'CVE-2026-57075: high-bit-only !!binary decodes to empty string, no OOB leak' +); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/t/cve-2026-57076-anchor-key-uaf.t new/YAML-Syck-1.47/t/cve-2026-57076-anchor-key-uaf.t --- old/YAML-Syck-1.46/t/cve-2026-57076-anchor-key-uaf.t 1970-01-01 01:00:00.000000000 +0100 +++ new/YAML-Syck-1.47/t/cve-2026-57076-anchor-key-uaf.t 2026-07-13 17:43:22.000000000 +0200 @@ -0,0 +1,29 @@ +#!perl + +# CVE-2026-57076 - CWE-416 (Use After Free) +# +# An anchor name string allocated by syck_strndup was freed in +# syck_hdlr_add_anchor (handler.c:43) while still stored as a live KEY in the +# parser's anchors table. On an anchor redefinition, syck_hdlr_remove_anchor +# calls st_delete, whose st_strcmp then compares against that freed key. +# +# Trigger (9 bytes): YAML::Syck::Load("- &a&V\n&a") +# +# This is a NON-crashing use-after-free: on a normal build the freed key is +# still readable and nothing faults, so this file cannot fail a plain build - +# it just confirms Load() completes. The defect is PROVEN by the ASan CI job +# (the `asan` job in .github/workflows/testsuite.yml), where this same Load +# aborts the process with: +# heap-use-after-free READ in st_strcmp, freed by syck_hdlr_add_anchor +# and the harness reports this file as failed. + +use strict; +use warnings; +use Test::More tests => 1; +use YAML::Syck (); + +# Under ASan (unpatched) this Load aborts the process; on a normal build it +# returns/croaks harmlessly. eval keeps a normal parse error from failing us. +eval { YAML::Syck::Load("- &a&V\n&a") }; + +pass('CVE-2026-57076: Load("- &a&V\\n&a") completed without an ASan fault'); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/t/cve-2026-57077-newline-oob-read.t new/YAML-Syck-1.47/t/cve-2026-57077-newline-oob-read.t --- old/YAML-Syck-1.46/t/cve-2026-57077-newline-oob-read.t 1970-01-01 01:00:00.000000000 +0100 +++ new/YAML-Syck-1.47/t/cve-2026-57077-newline-oob-read.t 2026-07-13 17:43:22.000000000 +0200 @@ -0,0 +1,29 @@ +#!perl + +# CVE-2026-57077 - CWE-125 (Out-of-bounds Read) +# +# newline_len()/is_newline() (token.c) dereferenced *ptr (and *(ptr+1) for +# \r\n) with no NUL terminator or bounds guarantee. During block-scalar +# lexing at a document boundary the scan pointer ran one byte past the heap +# lexer buffer. This is an incomplete-fix follow-on to CVE-2025-11683, on a +# lexer path that earlier fix did not cover. +# +# Trigger (6 bytes): YAML::Syck::Load("|\n---\n") +# +# A one-byte over-read that does not crash a normal build, so this file cannot +# fail a plain build - it just confirms Load() completes. The defect is PROVEN +# by the ASan CI job (the `asan` job in .github/workflows/testsuite.yml), where +# this same Load aborts the process with: +# heap-buffer-overflow READ in newline_len +# and the harness reports this file as failed. + +use strict; +use warnings; +use Test::More tests => 1; +use YAML::Syck (); + +# Under ASan (unpatched) this Load aborts the process; on a normal build it +# returns harmlessly. eval keeps a normal parse error from failing us. +eval { YAML::Syck::Load("|\n---\n") }; + +pass('CVE-2026-57077: Load("|\\n---\\n") completed without an ASan fault'); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/t/gh-nan-inf-dump.t new/YAML-Syck-1.47/t/gh-nan-inf-dump.t --- old/YAML-Syck-1.46/t/gh-nan-inf-dump.t 1970-01-01 01:00:00.000000000 +0100 +++ new/YAML-Syck-1.47/t/gh-nan-inf-dump.t 2026-07-13 06:46:00.000000000 +0200 @@ -0,0 +1,39 @@ +use strict; +use warnings; +use Test::More; +use YAML::Syck; + +plan tests => 12; + +local $YAML::Syck::ImplicitTyping = 1; + +my $nan = YAML::Syck::Load("--- .nan\n"); +my $inf = YAML::Syck::Load("--- .inf\n"); +my $ninf = YAML::Syck::Load("--- -.inf\n"); + +ok($nan != $nan, 'loaded .nan is NaN'); +ok($inf == 9**9**9, 'loaded .inf is Inf'); +ok($ninf == -(9**9**9), 'loaded -.inf is -Inf'); + +my $nan_dump = YAML::Syck::Dump($nan); +my $inf_dump = YAML::Syck::Dump($inf); +my $ninf_dump = YAML::Syck::Dump($ninf); + +like($nan_dump, qr/^--- \.nan\s*$/m, 'Dump NaN produces .nan'); +like($inf_dump, qr/^--- \.inf\s*$/m, 'Dump Inf produces .inf'); +like($ninf_dump, qr/^--- -\.inf\s*$/m, 'Dump -Inf produces -.inf'); + +my $nan2 = YAML::Syck::Load($nan_dump); +my $inf2 = YAML::Syck::Load($inf_dump); +my $ninf2 = YAML::Syck::Load($ninf_dump); + +ok($nan2 != $nan2, 'NaN roundtrips through Dump/Load'); +ok($inf2 == 9**9**9, 'Inf roundtrips through Dump/Load'); +ok($ninf2 == -(9**9**9), '-Inf roundtrips through Dump/Load'); + +my $list = YAML::Syck::Load("---\n- .nan\n- .inf\n- -.inf\n"); +my $list_dump = YAML::Syck::Dump($list); + +like($list_dump, qr/- \.nan/, 'NaN in list uses .nan'); +like($list_dump, qr/- \.inf/, 'Inf in list uses .inf'); +like($list_dump, qr/- -\.inf/, '-Inf in list uses -.inf'); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/t/json-max-depth.t new/YAML-Syck-1.47/t/json-max-depth.t --- old/YAML-Syck-1.46/t/json-max-depth.t 2026-04-23 17:12:20.000000000 +0200 +++ new/YAML-Syck-1.47/t/json-max-depth.t 2026-07-13 06:46:00.000000000 +0200 @@ -1,9 +1,9 @@ use strict; use warnings; -use Test::More tests => 6; +use Test::More; use JSON::Syck; -# Build a nested structure of given depth +# Build a nested Perl structure of given depth sub make_nested { my $depth = shift; my $data = "leaf"; @@ -11,26 +11,38 @@ return $data; } +# Build a nested JSON string of given depth +sub make_nested_json { + my $depth = shift; + my $json = '{"leaf":"value"}'; + for my $i (1..$depth) { + $json = '{"l' . $i . '":' . $json . '}'; + } + return $json; +} + +# === Dump-side MaxDepth === + # 1. Normal structures work fine { my $data = { a => [1, { b => [2, 3] }, "c"] }; my $json = eval { JSON::Syck::Dump($data) }; - ok( !$@, "shallow structure dumps without error" ); - like( $json, qr/\{/, "produces valid JSON" ); + ok( !$@, "Dump: shallow structure dumps without error" ); + like( $json, qr/\{/, "Dump: produces valid JSON" ); } # 2. Moderate nesting within default limit works { my $data = make_nested(200); my $json = eval { JSON::Syck::Dump($data) }; - ok( !$@, "200-level nesting works with default MaxDepth" ); + ok( !$@, "Dump: 200-level nesting works with default MaxDepth" ); } # 3. Deep nesting beyond default limit croaks cleanly { my $data = make_nested(600); eval { JSON::Syck::Dump($data) }; - like( $@, qr/MaxDepth/, "600-level nesting croaks with MaxDepth message" ); + like( $@, qr/MaxDepth/, "Dump: 600-level nesting croaks with MaxDepth message" ); } # 4. Increasing MaxDepth allows deeper structures @@ -38,7 +50,7 @@ local $JSON::Syck::MaxDepth = 4096; my $data = make_nested(600); my $json = eval { JSON::Syck::Dump($data) }; - ok( !$@, "600-level nesting works with MaxDepth=4096" ); + ok( !$@, "Dump: 600-level nesting works with MaxDepth=4096" ); } # 5. After croak, normal dumps still work @@ -46,5 +58,54 @@ my $data = make_nested(600); eval { JSON::Syck::Dump($data) }; my $normal = eval { JSON::Syck::Dump({ hello => "world" }) }; - ok( !$@ && $normal, "emitter recovers after MaxDepth croak" ); + ok( !$@ && $normal, "Dump: emitter recovers after MaxDepth croak" ); +} + +# === Load-side MaxDepth === + +# 6. Moderate JSON nesting within default limit works +{ + my $json = make_nested_json(50); + my $data = eval { JSON::Syck::Load($json) }; + ok( !$@, "Load: 50-level nesting works with default MaxDepth" ); +} + +# 7. Deep JSON beyond default limit croaks +{ + my $json = make_nested_json(600); + eval { JSON::Syck::Load($json) }; + like( $@, qr/nested too deeply/, + "Load: 600-level JSON nesting croaks" ); } + +# 8. Custom MaxDepth on Load +{ + local $JSON::Syck::MaxDepth = 10; + my $json_ok = make_nested_json(5); + my $data = eval { JSON::Syck::Load($json_ok) }; + ok( !$@, "Load: 5-level nesting works with MaxDepth=10" ); + + my $json_deep = make_nested_json(20); + eval { JSON::Syck::Load($json_deep) }; + like( $@, qr/nested too deeply/, + "Load: 20-level nesting croaks with MaxDepth=10" ); +} + +# 9. Increasing MaxDepth allows deeper Load +{ + local $JSON::Syck::MaxDepth = 4096; + my $json = make_nested_json(600); + my $data = eval { JSON::Syck::Load($json) }; + ok( !$@, "Load: 600-level nesting works with MaxDepth=4096" ); +} + +# 10. Parser recovers after MaxDepth croak +{ + local $JSON::Syck::MaxDepth = 5; + eval { JSON::Syck::Load(make_nested_json(20)) }; + my $data = eval { JSON::Syck::Load('{"hello":"world"}') }; + ok( !$@ && ref($data) eq 'HASH' && $data->{hello} eq 'world', + "Load: parser recovers after MaxDepth croak" ); +} + +done_testing(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/t/yaml-max-depth.t new/YAML-Syck-1.47/t/yaml-max-depth.t --- old/YAML-Syck-1.46/t/yaml-max-depth.t 2026-03-31 22:29:06.000000000 +0200 +++ new/YAML-Syck-1.47/t/yaml-max-depth.t 2026-07-13 06:46:00.000000000 +0200 @@ -1,9 +1,9 @@ use strict; use warnings; -use Test::More tests => 7; +use Test::More; use YAML::Syck; -# Build a nested structure of given depth +# Build a nested Perl structure of given depth sub make_nested { my $depth = shift; my $data = "leaf"; @@ -11,26 +11,39 @@ return $data; } +# Build a nested YAML string of given depth (block-style mappings) +sub make_nested_yaml { + my $depth = shift; + my $yaml = "---\n"; + for my $i (0..$depth-1) { + $yaml .= (" " x $i) . "l$i:\n"; + } + $yaml .= (" " x $depth) . "leaf: value\n"; + return $yaml; +} + +# === Dump-side MaxDepth === + # 1. Normal structures work fine { my $data = { a => [1, { b => [2, 3] }, "c"] }; my $yaml = eval { Dump($data) }; - ok( !$@, "shallow structure dumps without error" ); - like( $yaml, qr/---/, "produces valid YAML" ); + ok( !$@, "Dump: shallow structure dumps without error" ); + like( $yaml, qr/---/, "Dump: produces valid YAML" ); } # 2. Moderate nesting within default limit works { my $data = make_nested(200); my $yaml = eval { Dump($data) }; - ok( !$@, "200-level nesting works with default MaxDepth" ); + ok( !$@, "Dump: 200-level nesting works with default MaxDepth" ); } # 3. Deep nesting beyond default limit croaks cleanly { my $data = make_nested(600); eval { Dump($data) }; - like( $@, qr/MaxDepth/, "600-level nesting croaks with MaxDepth message" ); + like( $@, qr/MaxDepth/, "Dump: 600-level nesting croaks with MaxDepth message" ); } # 4. Increasing MaxDepth allows deeper structures @@ -38,14 +51,14 @@ local $YAML::Syck::MaxDepth = 4096; my $data = make_nested(600); my $yaml = eval { Dump($data) }; - ok( !$@, "600-level nesting works with MaxDepth=4096" ); + ok( !$@, "Dump: 600-level nesting works with MaxDepth=4096" ); } # 5. MaxDepth croak is catchable (eval traps it) { my $data = make_nested(600); eval { Dump($data) }; - ok( $@, "croak is catchable with eval" ); + ok( $@, "Dump: croak is catchable with eval" ); } # 6. After croak, normal dumps still work @@ -53,5 +66,78 @@ my $data = make_nested(600); eval { Dump($data) }; my $normal = eval { Dump({ hello => "world" }) }; - ok( !$@ && $normal, "emitter recovers after MaxDepth croak" ); + ok( !$@ && $normal, "Dump: emitter recovers after MaxDepth croak" ); +} + +# === Load-side MaxDepth === + +# 7. Moderate nesting within default limit works +{ + my $yaml = make_nested_yaml(50); + my $data = eval { Load($yaml) }; + ok( !$@, "Load: 50-level nesting works with default MaxDepth" ); + my $node = $data; + for my $i (0..49) { $node = $node->{"l$i"}; } + is( $node->{leaf}, 'value', + "Load: deeply nested value is correct" ); +} + +# 8. Deep YAML beyond default limit croaks +{ + my $yaml = make_nested_yaml(600); + eval { Load($yaml) }; + like( $@, qr/nested too deeply/, + "Load: 600-level nesting croaks with depth message" ); +} + +# 9. Custom MaxDepth on Load +{ + local $YAML::Syck::MaxDepth = 10; + my $yaml_shallow = make_nested_yaml(5); + my $data = eval { Load($yaml_shallow) }; + ok( !$@, "Load: 5-level nesting works with MaxDepth=10" ); + + my $yaml_deep = make_nested_yaml(20); + eval { Load($yaml_deep) }; + like( $@, qr/nested too deeply/, + "Load: 20-level nesting croaks with MaxDepth=10" ); } + +# 10. Increasing MaxDepth allows deeper Load +{ + local $YAML::Syck::MaxDepth = 4096; + my $yaml = make_nested_yaml(600); + my $data = eval { Load($yaml) }; + ok( !$@, "Load: 600-level nesting works with MaxDepth=4096" ); +} + +# 11. Load croak is catchable +{ + local $YAML::Syck::MaxDepth = 5; + my $yaml = make_nested_yaml(20); + eval { Load($yaml) }; + ok( $@, "Load: croak is catchable with eval" ); +} + +# 12. Parser recovers after MaxDepth croak +{ + local $YAML::Syck::MaxDepth = 5; + my $yaml_deep = make_nested_yaml(20); + eval { Load($yaml_deep) }; + + my $yaml_ok = "---\nhello: world\n"; + my $data = eval { Load($yaml_ok) }; + ok( !$@ && ref($data) eq 'HASH' && $data->{hello} eq 'world', + "Load: parser recovers after MaxDepth croak" ); +} + +# 13. Flow collections also respect MaxDepth +{ + local $YAML::Syck::MaxDepth = 5; + my $yaml = "---\na: {b: {c: {d: {e: {f: {g: deep}}}}}}\n"; + eval { Load($yaml) }; + like( $@, qr/nested too deeply/, + "Load: deeply nested flow mapping respects MaxDepth" ); +} + +done_testing(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/YAML-Syck-1.46/token.c new/YAML-Syck-1.47/token.c --- old/YAML-Syck-1.46/token.c 2026-03-25 23:17:31.000000000 +0100 +++ new/YAML-Syck-1.47/token.c 2026-07-13 17:43:22.000000000 +0200 @@ -39,7 +39,7 @@ /* * Track line numbers */ -#define NEWLINE(ptr) YYLINEPTR = ptr + newline_len(ptr); if ( YYLINEPTR > YYLINECTPTR ) { YYLINE++; YYLINECTPTR = YYLINEPTR; } +#define NEWLINE(ptr) YYLINEPTR = ptr + newline_len(ptr, YYLIMIT); if ( YYLINEPTR > YYLINECTPTR ) { YYLINE++; YYLINECTPTR = YYLINEPTR; } /* * I like seeing the level operations as macros... @@ -132,7 +132,7 @@ /* concat the inline characters to the plain scalar */ #define PLAIN_NOT_INL() \ - if ( *(YYCURSOR - 1) == ' ' || is_newline( YYCURSOR - 1 ) ) \ + if ( *(YYCURSOR - 1) == ' ' || is_newline( YYCURSOR - 1, YYLIMIT ) ) \ { \ YYCURSOR--; \ } \ @@ -176,7 +176,8 @@ if ( nlDoWhat != NL_KEEP ) \ { \ char *fc = n->data.str->ptr + n->data.str->len - 1; \ - while ( is_newline( fc ) ) fc--; \ + while ( fc >= n->data.str->ptr && \ + is_newline( fc, n->data.str->ptr + n->data.str->len ) ) fc--; \ if ( nlDoWhat != NL_CHOMP && fc < n->data.str->ptr + n->data.str->len - 1 ) \ fc += 1; \ n->data.str->len = fc - n->data.str->ptr + 1; \ @@ -194,7 +195,7 @@ NEWLINE(indent); \ while ( indent < YYCURSOR ) \ { \ - if ( is_newline( ++indent ) ) \ + if ( is_newline( ++indent, YYLIMIT ) ) \ { \ NEWLINE(indent); \ } \ @@ -237,8 +238,8 @@ */ void eat_comments( SyckParser * ); char escape_seq( char ); -int is_newline( char *ptr ); -int newline_len( char *ptr ); +int is_newline( char *ptr, char *limit ); +int newline_len( char *ptr, char *limit ); int sycklex_yaml_utf8( SYCKSTYPE *, SyckParser * ); int sycklex_bytecode_utf8( SYCKSTYPE *, SyckParser * ); int syckwrap(void); @@ -898,7 +899,7 @@ ++YYCURSOR; yy71: #line 482 "token.re" - { if ( is_newline( YYCURSOR - 1 ) ) + { if ( is_newline( YYCURSOR - 1, YYLIMIT ) ) { YYCURSOR--; } @@ -1087,7 +1088,7 @@ #line 444 "token.re" { ENSURE_YAML_IOPEN(lvl, YYTOKEN - YYLINEPTR, 1); FORCE_NEXT_TOKEN(YAML_IOPEN); - if ( *YYCURSOR == '#' || is_newline( YYCURSOR ) || is_newline( YYCURSOR - 1 ) ) + if ( *YYCURSOR == '#' || is_newline( YYCURSOR, YYLIMIT ) || is_newline( YYCURSOR - 1, YYLIMIT ) ) { YYCURSOR--; ADD_LEVEL((YYTOKEN + 1) - YYLINEPTR, syck_lvl_seq); @@ -1622,7 +1623,7 @@ while ( YYTOKEN < YYCURSOR ) { - int nl_len = newline_len( YYTOKEN++ ); + int nl_len = newline_len( YYTOKEN++, YYLIMIT ); if ( nl_len ) { nl_count++; @@ -1872,7 +1873,7 @@ while ( YYTOKEN < YYCURSOR ) { - int nl_len = newline_len( YYTOKEN++ ); + int nl_len = newline_len( YYTOKEN++, YYLIMIT ); if ( nl_len ) { nl_count++; @@ -2035,7 +2036,7 @@ { while ( YYTOKEN < YYCURSOR ) { - int nl_len = newline_len( YYTOKEN++ ); + int nl_len = newline_len( YYTOKEN++, YYLIMIT ); if ( nl_len ) { nl_count++; @@ -2638,7 +2639,7 @@ pacer = YYTOKEN; while ( pacer < YYCURSOR ) { - int nl_len = newline_len( pacer++ ); + int nl_len = newline_len( pacer++, YYLIMIT ); if ( nl_len ) { nl_count++; @@ -2905,18 +2906,21 @@ } int -is_newline( char *ptr ) +is_newline( char *ptr, char *limit ) { - return newline_len( ptr ); + return newline_len( ptr, limit ); } int -newline_len( char *ptr ) +newline_len( char *ptr, char *limit ) { + if ( ptr >= limit ) + return 0; + if ( *ptr == '\n' ) return 1; - - if ( *ptr == '\r' && *( ptr + 1 ) == '\n' ) + + if ( *ptr == '\r' && ptr + 1 < limit && *( ptr + 1 ) == '\n' ) return 2; return 0; ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.fuE4eL/_old 2026-07-17 18:50:52.560087657 +0200 +++ /var/tmp/diff_new_pack.fuE4eL/_new 2026-07-17 18:50:52.564087792 +0200 @@ -1,6 +1,6 @@ -mtime: 1779700158 -commit: c78eb2b0eabbb7062b67ab11d00e687e58bca160c3274f2143ec1e20601af202 +mtime: 1784278262 +commit: 38a98b505117c26d69657c3694a56289e5397f6226ee2bd93dbaf54b0ecc7ddc url: https://src.opensuse.org/perl/perl-YAML-Syck -revision: c78eb2b0eabbb7062b67ab11d00e687e58bca160c3274f2143ec1e20601af202 +revision: 38a98b505117c26d69657c3694a56289e5397f6226ee2bd93dbaf54b0ecc7ddc projectscmsync: https://src.opensuse.org/perl/_ObsPrj ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-07-17 10:51:02.000000000 +0200 @@ -0,0 +1 @@ +.osc
