Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package perl-Text-CSV_XS for 
openSUSE:Factory checked in at 2026-10-21 20:51:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Text-CSV_XS (Old)
 and      /work/SRC/openSUSE:Factory/.perl-Text-CSV_XS.new.2252680 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "perl-Text-CSV_XS"

Wed Oct 21 20:51:47 2026 rev:62 rq:1386512 version:1.650.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Text-CSV_XS/perl-Text-CSV_XS.changes        
2026-06-30 15:11:51.536843644 +0200
+++ 
/work/SRC/openSUSE:Factory/.perl-Text-CSV_XS.new.2252680/perl-Text-CSV_XS.changes
   2026-10-21 20:51:51.434803639 +0200
@@ -1,0 +2,17 @@
+Thu Oct 15 09:58:32 UTC 2026 - Tina Müller <[email protected]>
+
+- updated to 1.650.0 (1.65)
+   see /usr/share/doc/packages/perl-Text-CSV_XS/ChangeLog
+
+  1.65 - 2026-10-15, H.Merijn Brand
+      * CPAN.org does not forward email anymore
+      * parse (): report trailing lone CR, do not store EOF as 0xFF 
(CVE-2026-110759) bsc#1286128
+      * Under allow_whitespace, do not strip beyond field start     
(CVE-2026-110758) bsc#1286137
+      * combine (): decide quoting from the bytes, not the NV flags 
(CVE-2026-110757) bsc#1286191
+      * Flush saved bytes in Combine ()                             
(CVE-2026-110756) bsc#1286130
+      * Re-use AHEAD with \r instead of copying                     
(CVE-2026-110755) bsc#1286198
+      * getline (): free the result array when the parse fails      
(CVE-2026-110754) bsc#1286188
+      * Do not free the bound column scalar in skip_empty_rows      
(CVE-2026-110753) bsc#1286187
+      * fragment (): do not size memory by the selector integers    
(CVE-2026-110752) bsc#1286138
+
+-------------------------------------------------------------------
@@ -376 +393,2 @@
-      * Small additional fix for eol =   + BOM
+      * Small additional fix for eol = 
+ + BOM

Old:
----
  Text-CSV_XS-1.64.tgz

New:
----
  Text-CSV_XS-1.65.tgz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ perl-Text-CSV_XS.spec ++++++
--- /var/tmp/diff_new_pack.1vDgs9/_old  2026-10-21 20:51:52.429845134 +0200
+++ /var/tmp/diff_new_pack.1vDgs9/_new  2026-10-21 20:51:52.432845259 +0200
@@ -18,10 +18,10 @@
 
 %define cpan_name Text-CSV_XS
 Name:           perl-Text-CSV_XS
-Version:        1.640.0
+Version:        1.650.0
 Release:        0
-# 1.64 -> normalize -> 1.640.0
-%define cpan_version 1.64
+# 1.65 -> normalize -> 1.650.0
+%define cpan_version 1.65
 License:        Artistic-1.0 OR GPL-1.0-or-later
 Summary:        Comma-Separated Values manipulation routines
 URL:            https://metacpan.org/release/%{cpan_name}

++++++ Text-CSV_XS-1.64.tgz -> Text-CSV_XS-1.65.tgz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/CSV_XS.pm 
new/Text-CSV_XS-1.65/CSV_XS.pm
--- old/Text-CSV_XS-1.64/CSV_XS.pm      2026-06-22 12:57:04.000000000 +0200
+++ new/Text-CSV_XS-1.65/CSV_XS.pm      2026-10-14 17:37:14.000000000 +0200
@@ -23,7 +23,7 @@
 use Carp;
 
 use vars qw( $VERSION @ISA @EXPORT_OK %EXPORT_TAGS );
-$VERSION = "1.64";
+$VERSION = "1.65";
 @ISA     = qw( Exporter );
 XSLoader::load ("Text::CSV_XS", $VERSION);
 
@@ -1154,7 +1154,10 @@
                my ($tlr, $tlc, $brr, $brc) = @{$s};
                $r <  $tlr || ($brr ne "*" && $r > $brr) and next;
                !defined $lc || $tlc < $lc and $lc = $tlc;
-               my $rr = $brc eq "*" ? $#{$row} : $brc;
+               # Do not pad past the data: an explicit column beyond the
+               # row would otherwise allocate one slot per selector integer
+               my $lr = $#{$row} > $tlc ? $#{$row} : $tlc;
+               my $rr = $brc eq "*" ? $#{$row} : $brc > $lr ? $lr : $brc;
                $row{$_} = $row->[$_] for $tlc .. $rr;
                }
            push @c, [ @row{sort { $a <=> $b } keys %row } ];
@@ -1168,7 +1171,11 @@
        }
 
     # row or col
+    # Keep the ranges as pairs and test membership per row or column:
+    # materialising every index in an array cost memory proportional
+    # to the integers in the selector, not to the data
     my @r;
+    my $max = 0;
     my $eod = 0;
     for (split m/\s*;\s*/ => $range) {
        my ($from, $to) = m/^\s* ([0-9]+) (?: \s* - \s* ([0-9]+ | \* ))? \s* $/x
@@ -1177,16 +1184,21 @@
        $to eq "*" and ($to, $eod) = ($from, 1);
        # $to cannot be <= 0 due to regex and ||=
        $from <= 0 || $to < $from and croak ($self->SetDiag (2013));
-       $r[$_] = 1 for $from .. $to;
+       push @r => [ $from, $to ];
+       $to > $max and $max = $to;
        }
+    my $in = sub {
+       my $i = shift;
+       $i > $max and return $eod;
+       $i >= $_->[0] && $i <= $_->[1] and return 1 for @r;
+       return 0;
+       };
 
     my $r = 0;
-    $type eq "col" and shift @r;
-    $_ ||= 0 for @r;
     while (my $row = $self->getline ($io)) {
        $r++;
        if ($type eq "row") {
-           if (($r > $#r && $eod) || $r[$r]) {
+           if ($in->($r)) {
                push @c, $row;
                if (@h) {
                    my %h; @h{@h} = @{$c[-1]};
@@ -1195,7 +1207,7 @@
                }
            next;
            }
-       push @c, [ map { ($_ > $#r && $eod) || $r[$_] ? $row->[$_] : () } 
0..$#{$row} ];
+       push @c, [ map { $in->($_ + 1) ? $row->[$_] : () } 0..$#{$row} ];
        if (@h) {
            my %h; @h{@h} = @{$c[-1]};
            $c[-1] = \%h;
@@ -2907,6 +2919,10 @@
  $csv->column_names ("Name", "Age");
  my $AoH = $csv->fragment ($fh, "col=3;8");
 
+When passing indices beyond the content of the rows,  only the cells parsed
+will be passed: C<col=1-9> will not return 9 entries if a row only has four
+fields.
+
 If the L</after_parse> callback is active,  it is also called on every line
 parsed and skipped before the fragment.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/CSV_XS.xs 
new/Text-CSV_XS-1.65/CSV_XS.xs
--- old/Text-CSV_XS-1.64/CSV_XS.xs      2026-05-03 21:08:08.000000000 +0200
+++ new/Text-CSV_XS-1.65/CSV_XS.xs      2026-10-14 16:35:20.000000000 +0200
@@ -1112,9 +1112,9 @@
        csv->fld_idx = 0;                                               \
        c = CSV_GET;                                                    \
        if (c == EOF || ser == 2) {                                     \
-           sv_free (sv);                                               \
+           unless (csv->is_bound) sv_free (sv);                        \
            sv = NULL;                                                  \
-           seenSomething = FALSE;                                              
\
+           seenSomething = FALSE;                                      \
            if (ser == 2) return FALSE;                                 \
            break;                                                      \
            }                                                           \
@@ -1137,7 +1137,7 @@
        SPAGAIN;                                                        \
        unless (result) {                                               \
            /* A false return will stop the parsing */                  \
-           sv_free (sv);                                               \
+           unless (csv->is_bound) sv_free (sv);                        \
            sv = NULL;                                                  \
            waitingForField = 0;                                        \
            return FALSE;                                               \
@@ -1245,8 +1245,7 @@
                 * (always_quote), if binary or blank characters are found
                 * and if the string contains quote or escape characters.
                 */
-               if (!quoteMe &&
-                  ( quoteMe = (!SvIOK (sv) && !SvNOK (sv) && CH_QUOTE))) {
+               if (!quoteMe && (quoteMe = CH_QUOTE)) {
                    char        *ptr2;
                    STRLEN       l;
 
@@ -1353,8 +1352,20 @@
        while (len--)
            CSV_PUT (csv, dst, *ptr++);
        }
-    if (csv->used)
-       return Print (csv, dst);
+    if (csv->used) {
+       unless (Print (csv, dst))
+           return FALSE;
+       if (csv->used) {
+           /* Print () held back trailing bytes that are not valid UTF-8
+            * to complete them on the next flush. This was the last flush
+            * of the record, so write them now, as they are */
+           int r, utf8 = csv->utf8;
+           csv->utf8 = 0;
+           r = Print (csv, dst);
+           csv->utf8 = utf8;
+           return r;
+           }
+       }
     return TRUE;
     } /* Combine */
 
@@ -1586,7 +1597,7 @@
     STRLEN len;
     char   *s = SvPV (sv, len);
     unless (s && len) return;
-    while (s[len - 1] == CH_SPACE || s[len - 1] == CH_TAB)
+    while (len && (s[len - 1] == CH_SPACE || s[len - 1] == CH_TAB))
        s[--len] = (char)0;
     SvCUR_set (sv, len);
     } /* strip_trail_whitespace */
@@ -2102,6 +2113,11 @@
 #endif
                    unless (seenSomething)
                        break;
+                   /* parse (): a CR at the very end of the input is not part
+                    * of an EOL, as for a non-empty last field; do not go on
+                    * with EOF as if it were a data byte */
+                   unless (csv->useIO)
+                       ERROR_INSIDE_FIELD (2032);
                    goto restart;
                    }
 
@@ -2474,8 +2490,17 @@
 
     if (csv.useIO) {
        if (csv.tmp && csv.used < csv.size && csv.has_ahead) {
-           SV *sv = newSVpvn (csv.bptr + csv.used, csv.size - csv.used);
-           (void)hv_store  (hv, "_AHEAD", 6, sv, 0);
+           SV **svp;
+           if (ahead && SvREFCNT (csv.tmp) == 1
+                     && (svp = hv_fetchs (hv, "_AHEAD", FALSE)) && *svp == 
csv.tmp)
+               /* The remainder already lives in _AHEAD: drop the parsed
+                * part in place instead of copying the whole tail again,
+                * which made CR-only input quadratic */
+               sv_chop (csv.tmp, csv.bptr + csv.used);
+           else {
+               SV *sv = newSVpvn (csv.bptr + csv.used, csv.size - csv.used);
+               (void)hv_store  (hv, "_AHEAD", 6, sv, 0);
+               }
            }
        else {
            csv.has_ahead = 0;
@@ -2604,11 +2629,15 @@
            }
        av_push (avr, newRV_noinc ((SV *)row));
 
-       if (n >= length && skip >= 0)
+       if (n >= length && skip >= 0) {
+           row = NULL;
            break; /* We have enough */
+           }
 
        row = newAV ();
        }
+    if (row)
+       SvREFCNT_dec ((SV *)row);
     while (n > length) {
        SvREFCNT_dec (av_pop (avr));
        n--;
@@ -2734,7 +2763,7 @@
 
     CSV_XS_SELF;
     if (fields == &PL_sv_undef)
-       av = newAV ();
+       av = (AV *)sv_2mortal ((SV *)newAV ());
     else {
        unless (_is_arrayref (fields))
            croak ("Expected fields to be an array ref");
@@ -2759,6 +2788,8 @@
     av  = newAV ();
     avf = newAV ();
     r   = xsParse (self, hv, av, avf, io, 1);
+    unless (r)
+       SvREFCNT_dec ((SV *)av);
     PUT_RETURN (r ? sv_2mortal (newRV_noinc ((SV *)av)) : undef);
     /* XS getline */
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/ChangeLog 
new/Text-CSV_XS-1.65/ChangeLog
--- old/Text-CSV_XS-1.64/ChangeLog      2026-06-22 14:46:30.000000000 +0200
+++ new/Text-CSV_XS-1.65/ChangeLog      2026-10-15 09:00:43.000000000 +0200
@@ -1,3 +1,14 @@
+1.65   - 2026-10-15, H.Merijn Brand
+    * CPAN.org does not forward email anymore
+    * parse (): report trailing lone CR, do not store EOF as 0xFF 
(CVE-2026-110759)
+    * Under allow_whitespace, do not strip beyond field start     
(CVE-2026-110758)
+    * combine (): decide quoting from the bytes, not the NV flags 
(CVE-2026-110757)
+    * Flush saved bytes in Combine ()                             
(CVE-2026-110756)
+    * Re-use AHEAD with \r instead of copying                     
(CVE-2026-110755)
+    * getline (): free the result array when the parse fails      
(CVE-2026-110754)
+    * Do not free the bound column scalar in skip_empty_rows      
(CVE-2026-110753)
+    * fragment (): do not size memory by the selector integers    
(CVE-2026-110752)
+
 1.64   - 2026-06-22, H.Merijn Brand
     * Fix syntax error in csv2xlsx
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/MANIFEST 
new/Text-CSV_XS-1.65/MANIFEST
--- old/Text-CSV_XS-1.64/MANIFEST       2026-06-22 14:48:23.000000000 +0200
+++ new/Text-CSV_XS-1.65/MANIFEST       2026-10-15 10:00:55.000000000 +0200
@@ -43,6 +43,7 @@
 t/90_csv.t             Function csv () checks
 t/91_csv_cb.t          Callbacks with csv function
 t/92_stream.t          Streaming functionality
+t/97_parse_eof.t       Trailing CR at the end of parse () input
 t/99_mem.t             Overlong attribute guard check
 t/util.pl              Extra test utilities
 examples/csv2xls       Script to onvert CSV files to M$Excel       XLS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/META.json 
new/Text-CSV_XS-1.65/META.json
--- old/Text-CSV_XS-1.64/META.json      2026-06-22 14:48:24.000000000 +0200
+++ new/Text-CSV_XS-1.65/META.json      2026-10-15 10:00:56.000000000 +0200
@@ -1,8 +1,48 @@
 {
-   "dynamic_config" : 1,
-   "abstract" : "Comma-Separated Values manipulation routines",
-   "name" : "Text-CSV_XS",
+   "license" : [
+      "perl_5"
+      ],
+   "resources" : {
+      "license" : [
+         "http://dev.perl.org/licenses/";
+         ],
+      "homepage" : "https://metacpan.org/pod/Text::CSV_XS";,
+      "x_IRC" : "irc://irc.perl.org/#csv",
+      "bugtracker" : {
+         "web" : "https://github.com/Tux/Text-CSV_XS/issues";
+         },
+      "repository" : {
+         "type" : "git",
+         "url" : "https://github.com/Tux/Text-CSV_XS";,
+         "web" : "https://github.com/Tux/Text-CSV_XS";
+         }
+      },
+   "release_status" : "stable",
+   "provides" : {
+      "Text::CSV_XS" : {
+         "version" : "1.65",
+         "file" : "CSV_XS.pm"
+         }
+      },
+   "author" : [
+      "H.Merijn Brand <[email protected]>"
+      ],
+   "generated_by" : "Author",
+   "meta-spec" : {
+      "version" : 2,
+      "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec";
+      },
    "prereqs" : {
+      "runtime" : {
+         "requires" : {
+            "XSLoader" : "0",
+            "perl" : "5.008001",
+            "IO::Handle" : "0"
+            },
+         "recommends" : {
+            "Encode" : "3.24"
+            }
+         },
       "configure" : {
          "recommends" : {
             "ExtUtils::MakeMaker" : "7.78"
@@ -11,60 +51,20 @@
             "ExtUtils::MakeMaker" : "0"
             }
          },
-      "test" : {
-         "requires" : {
-            "Test::More" : "0",
-            "Tie::Scalar" : "0"
-            }
-         },
-      "runtime" : {
-         "recommends" : {
-            "Encode" : "3.24"
-            },
+      "build" : {
          "requires" : {
-            "XSLoader" : "0",
-            "IO::Handle" : "0",
-            "perl" : "5.008001"
+            "Config" : "0"
             }
          },
-      "build" : {
+      "test" : {
          "requires" : {
-            "Config" : "0"
+            "Test::More" : "0",
+            "Tie::Scalar" : "0"
             }
          }
       },
-   "release_status" : "stable",
-   "author" : [
-      "H.Merijn Brand <[email protected]>"
-      ],
-   "meta-spec" : {
-      "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec";,
-      "version" : 2
-      },
-   "version" : "1.64",
-   "generated_by" : "Author",
-   "provides" : {
-      "Text::CSV_XS" : {
-         "file" : "CSV_XS.pm",
-         "version" : "1.64"
-         }
-      },
-   "license" : [
-      "perl_5"
-      ],
-   "resources" : {
-      "x_IRC" : "irc://irc.perl.org/#csv",
-      "repository" : {
-         "type" : "git",
-         "url" : "https://github.com/Tux/Text-CSV_XS";,
-         "web" : "https://github.com/Tux/Text-CSV_XS";
-         },
-      "license" : [
-         "http://dev.perl.org/licenses/";
-         ],
-      "homepage" : "https://metacpan.org/pod/Text::CSV_XS";,
-      "bugtracker" : {
-         "web" : "https://github.com/Tux/Text-CSV_XS/issues";
-         }
-      }
+   "name" : "Text-CSV_XS",
+   "abstract" : "Comma-Separated Values manipulation routines",
+   "dynamic_config" : 1,
+   "version" : "1.65"
    }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/META.yml 
new/Text-CSV_XS-1.65/META.yml
--- old/Text-CSV_XS-1.64/META.yml       2026-06-22 14:48:24.000000000 +0200
+++ new/Text-CSV_XS-1.65/META.yml       2026-10-15 10:00:56.000000000 +0200
@@ -1,13 +1,13 @@
 ---
 abstract: Comma-Separated Values manipulation routines
 author:
-  - H.Merijn Brand <[email protected]>
+  - H.Merijn Brand <[email protected]>
 build_requires:
   Config: '0'
 configure_requires:
   ExtUtils::MakeMaker: '0'
 dynamic_config: 1
-generated_by: Author, CPAN::Meta::Converter version 2.150013
+generated_by: Author, CPAN::Meta::Converter version 2.150015
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -16,7 +16,7 @@
 provides:
   Text::CSV_XS:
     file: CSV_XS.pm
-    version: '1.64'
+    version: '1.65'
 recommends:
   Encode: '3.24'
 requires:
@@ -31,4 +31,4 @@
   homepage: https://metacpan.org/pod/Text::CSV_XS
   license: http://dev.perl.org/licenses/
   repository: https://github.com/Tux/Text-CSV_XS
-version: '1.64'
+version: '1.65'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/SECURITY.md 
new/Text-CSV_XS-1.65/SECURITY.md
--- old/Text-CSV_XS-1.64/SECURITY.md    2025-06-05 21:10:20.000000000 +0200
+++ new/Text-CSV_XS-1.65/SECURITY.md    2026-09-02 13:08:39.000000000 +0200
@@ -1,6 +1,6 @@
 # Security Policy for the Text::CSV_XS distribution.
 
-Report security issues by email to H.Merijn Brand <[email protected]>.
+Report security issues by email to H.Merijn Brand <[email protected]>.
 
 This is the Security Policy for Text::CSV_XS.
 
@@ -14,7 +14,7 @@
 # How to Report a Security Vulnerability
 
 Security vulnerabilities can be reported to the current Text::CSV_XS
-maintainers by email to H.Merijn Brand <[email protected]>.
+maintainers by email to H.Merijn Brand <[email protected]>.
 
 Please include as many details as possible, including code samples
 or test cases, so that we can reproduce the issue.  Check that your
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/ppport.h 
new/Text-CSV_XS-1.65/ppport.h
--- old/Text-CSV_XS-1.64/ppport.h       2026-05-03 21:08:08.000000000 +0200
+++ new/Text-CSV_XS-1.65/ppport.h       2026-09-28 14:45:30.000000000 +0200
@@ -6,7 +6,7 @@
 
     ppport.h -- Perl/Pollution/Portability Version 3.73
 
-    Automatically created by Devel::PPPort running under perl 5.042002.
+    Automatically created by Devel::PPPort running under perl 5.044000.
 
     Do NOT edit this file directly! -- Edit PPPort_pm.PL and the
     includes in parts/inc/ instead.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/t/46_eol_si.t 
new/Text-CSV_XS-1.65/t/46_eol_si.t
--- old/Text-CSV_XS-1.64/t/46_eol_si.t  2026-05-03 10:14:23.000000000 +0200
+++ new/Text-CSV_XS-1.65/t/46_eol_si.t  2026-10-14 16:09:53.000000000 +0200
@@ -13,7 +13,7 @@
        plan skip_all => "No reliable perlIO available";
        }
     else {
-       plan tests => 562;
+       plan tests => 568;
        }
     }
 
@@ -257,4 +257,36 @@
     is ($foo, "x\n", "say, with newline");
     }
 
+{   # CR-only input arrives from getline () as one chunk; each record must
+    # not copy the whole rest of that chunk again
+    my $data = join "" => map { "$_,x\r" } 1 .. 5;
+    open my $fh, "<", \$data or die "$!";
+    my $csv = Text::CSV_XS->new ({ binary => 1 });
+    my (@rows, %ahead);
+    while (my $row = $csv->getline ($fh)) {
+       push @rows, $row->[0];
+       $ahead{0 + \$csv->{_AHEAD}}++ if defined $csv->{_AHEAD} and @rows > 1;
+       }
+    is_deeply (\@rows, [ 1 .. 5 ], "All CR-only records parsed");
+    is (scalar keys %ahead, 1, "The unparsed remainder is kept, not 
re-copied");
+
+    # header () hands its remainder over the same way
+    $data = "a,b\r" . join "" => map { "$_,x\r" } 1 .. 5;
+    open $fh, "<", \$data or die "$!";
+    $csv = Text::CSV_XS->new ({ binary => 1 });
+    is_deeply ([ $csv->header ($fh) ], [qw( a b )], "Header from CR-only 
input");
+    @rows = ();
+    while (my $row = $csv->getline ($fh)) { push @rows, $row->[0] }
+    is_deeply (\@rows, [ 1 .. 5 ], "All records after the header");
+
+    # Same data with LF still behaves
+    $data = join "" => map { "$_,x\n" } 1 .. 5;
+    open $fh, "<", \$data or die "$!";
+    $csv = Text::CSV_XS->new ({ binary => 1 });
+    @rows = ();
+    while (my $row = $csv->getline ($fh)) { push @rows, $row->[0] }
+    is_deeply (\@rows, [ 1 .. 5 ], "LF records");
+    ok ($csv->eof, "At EOF");
+    }
+
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/t/50_utf8.t 
new/Text-CSV_XS-1.65/t/50_utf8.t
--- old/Text-CSV_XS-1.64/t/50_utf8.t    2026-05-03 09:59:50.000000000 +0200
+++ new/Text-CSV_XS-1.65/t/50_utf8.t    2026-10-14 15:58:59.000000000 +0200
@@ -3,6 +3,7 @@
 use strict;
 use warnings;
 
+use Config;
 use Test::More;
 use charnames ":full";
 
@@ -11,7 +12,7 @@
        plan skip_all => "UTF8 tests useless in this ancient perl version";
        }
     else {
-       plan tests => 93;
+       plan tests => 99;
        }
     }
 
@@ -115,8 +116,7 @@
 close $fh;
 open  $fh, "<:encoding(utf-8)", $tfn or die "$tfn: $!\n";
 
-SKIP: {
-    my $out = "";
+{   my $out = "";
     my $isutf8 = sub { utf8::is_utf8 ($out); };
     ok ($csv->auto_diag (1),                   "auto diag");
     ok ($csv->binary (1),                      "set binary");
@@ -135,3 +135,48 @@
     ok (!$isutf8->(1),                         "not utf8");
     close $fh;
     }
+
+if (exists  $Config{useperlio} &&
+    defined $Config{useperlio} &&
+           $Config{useperlio} eq "define") {
+    # A decoded field followed by bytes that are not valid UTF-8 must not
+    # lose the end of the record when written with print ()
+    my $u = "\x{e9}";
+    utf8::upgrade ($u);
+
+    sub emit {
+       my $csv = Text::CSV_XS->new ({ binary => 1, eol => "\n" });
+       my $out = "";
+       open my $fh, ">", \$out or die "$!";
+       $csv->print ($fh, $_) for @_;
+       close $fh;
+       $out;
+       } # emit
+
+    sub rows {
+       my $s = shift;
+       open my $fh, "<", \$s or die "$!";
+       my $csv = Text::CSV_XS->new ({ binary => 1 });
+       my @r;
+       while (my $r = $csv->getline ($fh)) { push @r, $r }
+       scalar @r;
+       } # rows
+
+    my $out = emit ([ $u, "\xe9" ], [ "next", "row" ]);
+    like ($out, qr{\xe9\n}, "Trailing byte and EOL written");
+    is (rows ($out), 2, "Two records, not fused");
+
+    $out = emit ([ $u, qq{x\xe9"} ], [ "next", "row" ]);#"
+    like ($out, qr{"\n}, "Closing quote and EOL written");
+    is (rows ($out), 2, "Quote closed, next record intact");
+
+    my $v = "\x{e8}";
+    utf8::upgrade ($v);
+    is (rows (emit ([ $u, $v ], [ "next", "row" ])), 2, "Both decoded");
+    is (rows (emit ([ "\xc3\xa9", "\xe9" ], [ "next", "row" ])), 2, "Both 
bytes");
+    }
+else {
+    ok (1, "No PerlIO avail for this test") for 1..6;
+    }
+
+1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/t/55_combi.t 
new/Text-CSV_XS-1.65/t/55_combi.t
--- old/Text-CSV_XS-1.64/t/55_combi.t   2022-09-13 09:37:35.000000000 +0200
+++ new/Text-CSV_XS-1.65/t/55_combi.t   2026-10-14 15:40:51.000000000 +0200
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 25119;
+use Test::More tests => 25127;
 
 BEGIN {
     require_ok "Text::CSV_XS";
@@ -141,7 +141,7 @@
 
 {   ok (my $csv = Text::CSV_XS->new ({ binary => 1 }), "New CSV default");
     ok ($csv->combine ("=\x00="), "combine =\\x00=");
-    is ($csv->string, qq{"="0="}, "string");
+    is ($csv->string, qq{"="0="}, "string");#"
     }
 {   ok (my $csv = Text::CSV_XS->new ({ binary => 1, escape_null => 0 }), "New 
CSV no escape_null");
     ok ($csv->combine ("=\x00="), "combine =\\x00=");
@@ -155,4 +155,28 @@
     ok ($csv->combine ("=\x00="), "combine =\\x00=");
     is ($csv->string, qq{"=\0="}, "string");
     }
+
+{   # A string that was used as a number keeps its bytes: quote on content
+    my $csv = Text::CSV_XS->new ({ binary => 1 });
+
+    my $v = "12\n";
+    my $p = $v > 0;
+    ok ($csv->combine ("a", $v, "b"), "combine numeric-looking string with 
NL");
+    is ($csv->string, qq{a,"12\n",b}, "NL field quoted after numeric use");
+
+    my $n = "1.5\r\n";
+    my $x = $n + 0;
+    ok ($csv->combine ("a", $n, "b"), "combine NV-flagged string with CRLF");
+    is ($csv->string, qq{a,"1.5\r\n",b}, "CRLF field quoted after numeric 
use");
+
+    my $s = " 12";
+    my $e = $s == 12;
+    ok ($csv->combine ("a", $s, "b"), "combine numeric-looking string with 
space");
+    is ($csv->string, qq{a," 12",b}, "quote_space honoured after numeric use");
+
+    # Real numbers are still written bare
+    ok ($csv->combine (1, 2.5, -3), "combine numbers");
+    is ($csv->string, "1,2.5,-3", "Numbers unquoted");
+    }
+
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/t/60_samples.t 
new/Text-CSV_XS-1.65/t/60_samples.t
--- old/Text-CSV_XS-1.64/t/60_samples.t 2016-08-12 08:18:59.000000000 +0200
+++ new/Text-CSV_XS-1.65/t/60_samples.t 2026-10-15 09:41:55.000000000 +0200
@@ -3,18 +3,18 @@
 use strict;
 use warnings;
 
-use Test::More tests => 8;
+use Config;
+use Test::More tests => 12;
 
 BEGIN {
     use_ok "Text::CSV_XS", ();
     plan skip_all => "Cannot load Text::CSV_XS" if $@;
     }
 
-# Some assorted examples from the modules history
+# Some assorted examples from the modules history and other sources
 
 # "Pavel Kotala" <[email protected]>
-{
-    my $csv = Text::CSV_XS->new ({
+{   my $csv = Text::CSV_XS->new ({
        quote_char      => '"',
        escape_char     => '\\',
        sep_char        => ';',
@@ -32,3 +32,54 @@
     is ($list[0], $olist[0],           "field 1");
     is ($list[1], $olist[1],           "field 2");
     }
+
+if (-e "/proc/self/statm" and
+       exists  $Config{useperlio} &&
+       defined $Config{useperlio} &&
+       $Config{useperlio} eq "define") {
+    sub rss {
+       open my $fh, "<", "/proc/self/statm" or die "$!";
+       (split m/\s+/ => scalar <$fh>)[1] * 4096;
+       } # rss
+
+    my $csv   = Text::CSV_XS->new ({ binary => 1 });
+    my $width = 20_000;
+    my $good  = ("," x $width) . "\n";
+    my $bad   = ("," x $width) . qq{"a"b\n};
+
+    # Warm up allocator and cache
+    for (1 .. 3) {
+       open my $fh, "<", \$good or die "$!";
+       $csv->getline ($fh);
+       open    $fh, "<", \$bad  or die "$!";
+       $csv->getline ($fh);
+       }
+
+    my $r0 = rss ();
+    for (1 .. 40) {
+       open my $fh, "<", \$bad or die "$!";
+       $csv->getline ($fh);
+       }
+    my $grow = rss () - $r0;
+    is (($csv->error_diag)[0], 2023, "Records fail to parse");
+    cmp_ok ($grow, "<", 8_000_000, "Failed getline () calls do not keep the 
fields");
+
+    $r0 = rss ();
+    for (1 .. 40) {
+       $csv->getline_all (do { open my $fh, "<", \$good or die "$!"; $fh });
+       }
+    $grow = rss () - $r0;
+    cmp_ok ($grow, "<", 8_000_000, "getline_all () does not keep the trailing 
row");
+
+    $r0 = rss ();
+    my $out = "";
+    open my $oh, ">", \$out or die "$!";
+    $csv->print ($oh, undef) for 1 .. 200_000;
+    $grow = rss () - $r0;
+    cmp_ok ($grow, "<", 8_000_000, "print (\$fh, undef) does not keep an 
array");
+    }
+else {
+    ok (1, "This test only runs on Linux with PerlIO") for 1..4;
+    }
+
+1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/t/65_allow.t 
new/Text-CSV_XS-1.65/t/65_allow.t
--- old/Text-CSV_XS-1.64/t/65_allow.t   2022-09-13 09:37:35.000000000 +0200
+++ new/Text-CSV_XS-1.65/t/65_allow.t   2026-10-14 15:24:34.000000000 +0200
@@ -4,7 +4,7 @@
 use warnings;
 
 #use Test::More "no_plan";
- use Test::More tests => 1119;
+ use Test::More tests => 1126;
 
 BEGIN {
     use_ok "Text::CSV_XS", ();
@@ -425,3 +425,30 @@
     is ( $csv->parse ($str),   1,              "Parse trailing ESC");
     is_deeply ([ $csv->fields ], [ 1,3,"\0" ], "Parse passed");
     }
+
+{   # An unquoted field of only blanks under allow_whitespace is stripped
+    # to empty without looking before the start of the field.  The out of
+    # bounds access this guards against shows under valgrind or ASan only.
+    my $csv = Text::CSV_XS->new ({ binary => 1, allow_whitespace => 1, 
escape_char => "\\" });
+    ok ($csv->parse ("\\  ,x"), "parse escaped blanks");
+    is_deeply ([ $csv->fields ], [ "", "x" ], "Blank field stripped to empty");
+
+    ok ($csv->parse ("\\ \t \t,x"), "parse escaped blanks and tabs");
+    is_deeply ([ $csv->fields ], [ "", "x" ], "Blank and tab field stripped to 
empty");
+
+    use Config;
+    if (exists  $Config{useperlio} &&
+       defined $Config{useperlio} &&
+               $Config{useperlio} eq "define") {
+       $csv = Text::CSV_XS->new ({ binary => 1, allow_whitespace => 1 });
+       open my $fh, "<", \qq{"   "\r\r\nx,y\n} or die "$!";
+       ok ($csv->getline ($fh), "getline CR CR auto-detection");
+       ok ($csv->parse ("a  , b "), "Trailing blanks on non-blank fields");
+       is_deeply ([ $csv->fields ], [ "a", "b" ], "Stripped");
+       }
+    else {
+       ok (1, "Test skipped: no PerlIO");
+       ok (1, "Test skipped: no PerlIO");
+       ok (1, "Test skipped: no PerlIO");
+       }
+    }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/t/67_emptrow.t 
new/Text-CSV_XS-1.65/t/67_emptrow.t
--- old/Text-CSV_XS-1.64/t/67_emptrow.t 2026-05-03 10:00:18.000000000 +0200
+++ new/Text-CSV_XS-1.65/t/67_emptrow.t 2026-10-14 17:05:16.000000000 +0200
@@ -3,10 +3,11 @@
 use strict;
 use warnings;
 
+use Config;
 use Test::More;
 
 BEGIN {
-    plan tests => 58;
+    plan tests => 66;
 
     use_ok "Text::CSV_XS", ("csv");
     plan skip_all => "Cannot load Text::CSV_XS" if $@;
@@ -142,3 +143,31 @@
     isnt ($row->{a}, undef, "Column 'a' is defined");
     }
 close $fh;
+
+if (exists  $Config{useperlio} &&
+           defined $Config{useperlio} &&
+           $Config{useperlio} eq "define") {
+    # Skipping an empty row must not release the caller's bound scalar
+    foreach my $t (
+           [ 2, "1,2\n\n3,4\n", 2 ],   # eof: stops at the empty row
+           [ 1, "1,2\n\n",      1 ],   # skip: trailing empty line
+           [ 1, "1,2\n\n3,4\n", 2 ],   # skip: empty row mid-stream
+           [ 0, "1,2\n3,4\n",   2 ],   # no empty row at all
+           ) {
+       my ($ser, $data, $rows) = @$t;
+       open my $fh, "<", \$data or die "$!";
+       my $csv = Text::CSV_XS->new ({ binary => 1, skip_empty_rows => $ser });
+       my ($x, $y);
+       $csv->bind_columns (\$x, \$y);
+       my $before = Internals::SvREFCNT ($x);
+       my $n = 0;
+       $n++ while $csv->getline ($fh);
+       is ($n, $rows, "skip_empty_rows $ser: rows");
+       is (Internals::SvREFCNT ($x), $before, "skip_empty_rows $ser: bound 
scalar keeps its reference");
+       }
+    }
+else {
+    ok (1, "No PerlIO available for this test") for 1..8;
+    }
+
+1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/t/78_fragment.t 
new/Text-CSV_XS-1.65/t/78_fragment.t
--- old/Text-CSV_XS-1.64/t/78_fragment.t        2026-05-03 10:14:28.000000000 
+0200
+++ new/Text-CSV_XS-1.65/t/78_fragment.t        2026-10-14 17:40:10.000000000 
+0200
@@ -14,7 +14,7 @@
         plan skip_all => "No reliable perlIO available";
         }
     else {
-        plan tests => 38;
+        plan tests => 48;
         }
     }
 
@@ -109,6 +109,39 @@
     is (0 + $csv->error_diag, 2013, "Error in spec");
     }
 
+{   my $data = "11,12,13\n21,22,23\n31,32,33\n";
+
+    sub frag {
+       my $spec = shift;
+       open my $io, "<", \$data or die "$!";
+       Text::CSV_XS->new ()->fragment ($io, $spec);
+       } # frag
+
+    # Selector integers beyond the data select nothing extra
+    is_deeply (frag ("row=2-9"),      [[21,22,23],[31,32,33]],   "row range 
past the data");
+    is_deeply (frag ("col=3-9"),      [[13],[23],[33]],          "col range 
past the data");
+    is_deeply (frag ("cell=1,2-2,9"), [[12,13],[22,23]],         "cell range 
past the data");
+    is_deeply (frag ("cell=1,5"),     [[undef]],                 "single cell 
past the data");
+
+    # Existing semantics of open-ended and mixed ranges are unchanged
+    is_deeply (frag ("row=2-*"),      [[21,22,23],[31,32,33]],   "row=2-*");
+    is_deeply (frag ("row=3-*;1"),    [[11,12,13],[31,32,33]],   "row=3-*;1");
+    is_deeply (frag ("col=1;3-*"),    [[11,13],[21,23],[31,33]], "col=1;3-*");
+    is_deeply (frag ("col=2-2"),      [[12],[22],[32]],          "col=2-2");
+
+    # The memory used depends on the data, not on the selector
+    SKIP: {
+       $^O eq "MSWin32" || !-x "/bin/sh" and skip "needs a POSIX shell for 
ulimit", 2;
+       my @inc = map { "-I$_" } @INC;
+       for my $spec ("row=1-400000000", "cell=1,1-1,400000000") {
+           my $prog = q{open my $io, "<", \"1,2\n3,4\n" or die; }
+                    . q{Text::CSV_XS->new->fragment ($io, $ARGV[0]); print 
"ok\n"};
+           my $out = qx{/bin/sh -c 'ulimit -v 524288 2>/dev/null; exec "\$0" 
"\$@"' $^X @inc -MText::CSV_XS -e '$prog' '$spec' 2>&1};
+           like ($out, qr{^ok$}m, "$spec on a tiny CSV within 512 MiB");
+           }
+       }
+    }
+
 #$csv->eol ("\n");
 #foreach my $r (1..9){$csv->print(*STDOUT,[map{$r.$_}1..9])}
 __END__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Text-CSV_XS-1.64/t/97_parse_eof.t 
new/Text-CSV_XS-1.65/t/97_parse_eof.t
--- old/Text-CSV_XS-1.64/t/97_parse_eof.t       1970-01-01 01:00:00.000000000 
+0100
+++ new/Text-CSV_XS-1.65/t/97_parse_eof.t       2026-10-14 14:37:47.000000000 
+0200
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 12;
+
+use Text::CSV_XS;
+
+# A CR at the very end of parse () input is not part of an EOL, also
+# when the last field is empty: report it, do not turn EOF into data
+foreach my $bin (0, 1) {
+    my $csv = Text::CSV_XS->new ({ binary => $bin });
+    ok (!$csv->parse ("a,\r"),                 "binary $bin: a,CR fails");
+    is (($csv->error_diag)[0], 2032,           "binary $bin: a,CR is 2032");
+    ok (!$csv->parse ("a,b\r"),                        "binary $bin: a,b,CR 
fails");
+    is (($csv->error_diag)[0], 2032,           "binary $bin: same as non-empty 
field");
+    }
+
+my $s = "a,\r";
+utf8::upgrade ($s);
+my $csv = Text::CSV_XS->new ();
+ok (!$csv->parse ($s),                         "UTF-8 upgraded a,CR fails");
+is (($csv->error_diag)[0], 2032,               "UTF-8 upgraded a,CR is 2032");
+
+# Unchanged neighbours
+$csv = Text::CSV_XS->new ({ binary => 1 });
+ok ($csv->parse ("a,\r\n"),                    "parse a,CRLF");
+is_deeply ([ $csv->fields ], [ "a", "" ],      "a,CRLF");

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.1vDgs9/_old  2026-10-21 20:51:52.678855519 +0200
+++ /var/tmp/diff_new_pack.1vDgs9/_new  2026-10-21 20:51:52.685855811 +0200
@@ -1,6 +1,6 @@
-mtime: 1782204035
-commit: dd9e6bae88885ec41e68c1b33573872143c2a21d0d5273919cfd4fbae255594f
+mtime: 1792505111
+commit: ec79b0b4fb5e0723f4b5466e39b313bf9f7401b3a582dd2f1138f5c3fd116dad
 url: https://src.opensuse.org/perl/perl-Text-CSV_XS
-revision: dd9e6bae88885ec41e68c1b33573872143c2a21d0d5273919cfd4fbae255594f
+revision: ec79b0b4fb5e0723f4b5466e39b313bf9f7401b3a582dd2f1138f5c3fd116dad
 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-10-20 16:05:11.000000000 +0200
@@ -0,0 +1 @@
+.osc

Reply via email to