Subject: Re: bug#7992: cut segmentation fault with unbounded ranges

From: Jim Meyering <[email-masked]>
Date: Mon, 07 Feb 2011 08:50:59 +0100

Paul Marinescu wrote:
> In coreutils 8.9 (latest), the following commands trigger an invalid
> memory access.
>
> cut -c1234567890- --output-d=: foo
> cut -f1234567890- --output-d=: foo
> cut -b1234567890- --output-d=: foo
>
> The number 1234567890 is just a random number 'big enough' to make the
> invalid access generate a segmentation fault but the invalid access
> happens for values as low as 8 (valgrind)
>
> The problem is that ranges going to end of line (i.e., 'x-') are not
> taken into account when calculating the size of the printable_field
> vector, but their lower bound is used as an index on line 525:
>
>   if (output_delimiter_specified
>       && !complement
>       && eol_range_start && !is_printable_field (eol_range_start))

Thanks a lot for the report.
Here's a fix:

>From 43be5f4911f252ac298ac19865487f543c12db02 Mon Sep 17 00:00:00 2001
From: Jim Meyering <[email-masked]>
Date: Mon, 7 Feb 2011 08:29:33 +0100
Subject: [PATCH] cut: don't segfault for large unbounded range

* src/cut.c (set_fields): When computing the maximum range endpoint,
take into consideration the start of any unbounded range, like "999-".
* NEWS (Bug fixes): Mention it.
* tests/misc/cut (big-unbounded-b,c,f): Add tests.
Reported by Paul Marinescu in http://debbugs.gnu.org/7993
The bug was introduced on 2004-12-04 via commit 7380cf79.
---
 NEWS           |    6 ++++++
 src/cut.c      |    2 ++
 tests/misc/cut |    4 ++++
 3 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/NEWS b/NEWS
index 9c5a5a8..a367d8d 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,12 @@ GNU coreutils NEWS                                    -*- outline -*-

 * Noteworthy changes in release ?.? (????-??-??) [?]

+** Bug fixes
+
+  cut could segfault when invoked with a user-specified output
+  delimiter and an unbounded range like "-f1234567890-".
+  [bug introduced in coreutils-5.3.0]
+

 * Noteworthy changes in release 8.10 (2011-02-04) [stable]

diff --git a/src/cut.c b/src/cut.c
index 3f8e3e6..e2fe851 100644
--- a/src/cut.c
+++ b/src/cut.c
@@ -496,6 +496,8 @@ set_fields (const char *fieldstr)
       if (rp[i].hi > max_range_endpoint)
         max_range_endpoint = rp[i].hi;
     }
+  if (max_range_endpoint < eol_range_start)
+    max_range_endpoint = eol_range_start;

   /* Allocate an array large enough so that it may be indexed by
      the field numbers corresponding to all finite ranges
diff --git a/tests/misc/cut b/tests/misc/cut
index 4353994..c905ba9 100755
--- a/tests/misc/cut
+++ b/tests/misc/cut
@@ -150,6 +150,10 @@ my @Tests =
    {ERR=>$no_endpoint}],
   ['inval5', '-f', '1-,-', {IN=>''}, {OUT=>''}, {EXIT=>1}, {ERR=>$no_endpoint}],
   ['inval6', '-f', '-1,-', {IN=>''}, {OUT=>''}, {EXIT=>1}, {ERR=>$no_endpoint}],
+  # This would evoke a segfault from 5.3.0..6.10
+  ['big-unbounded-b', '--output-d=:', '-b1234567890-', {IN=>''}, {OUT=>''}],
+  ['big-unbounded-c', '--output-d=:', '-c1234567890-', {IN=>''}, {OUT=>''}],
+  ['big-unbounded-f', '--output-d=:', '-f1234567890-', {IN=>''}, {OUT=>''}],
  );

 @Tests = triple_test \@Tests;
--
1.7.4.2.g597a6