Subject: Re: bug#21250: sed: empty label for :/b/t commands

From: Jim Meyering <[email-masked]>
Date: Sun, 23 Aug 2015 21:54:30 -0700

On Sun, Aug 23, 2015 at 5:08 AM, Stephane Chazelas
<[email-masked]> wrote:
> 2015-08-22 22:02:42 -0700, Jim Meyering:
> [...]
>> I am preparing a patch to remove that functionality, making sed do
>> this, instead:
>>
>>   $ sed :
>>   sed: -e expression #1, char 1: ":" lacks a label
>>
>> Does anyone feel differently?
>> However, note that I have not surveyed other sed implementations.
> [...]
>
> Thanks.
>
> Solaris 11 (/bin/sed or /usr/xpg4/bin/sed):
>
> $ echo aa | sed -e : -e s/a/b/ -e t
> ba
>
> (it doesn't complain on :, but t branches to the end, not to
> that empty label).
>
> Same with busybox sed.
>
> With FreeBSD sed:
>
> $ echo aa | sed -e : -e s/a/b/ -e t
> sed: 1: ":
> ": empty label
>
> (exit status: 1)

Thanks for checking those.
Here's the patch I expect to push tomorrow:
From 31c84cbcfd2516e278a2a75523c7d5ad78f7bc57 Mon Sep 17 00:00:00 2001
From: Jim Meyering <[email-masked]>
Date: Sat, 22 Aug 2015 22:02:12 -0700
Subject: [PATCH] sed: reject a ":" command without a label

Before, sed would accept it and treat it as a label whose name
had length 0, and that could be referenced via a "b" or "t"
command with no label.
* sed/compile.c (errors): Add the new diagnostic.
(COLON_LACKS_LABEL): Define.
(compile_program): Reject ":" command with no label.
* testsuite/colon-with-no-label.sh: New file.
* testsuite/Makefile.am (T): Add it.
* NEWS (Bug fixes): Mention it.
Reported by Stephane Chazelas in http://bugs.gnu.org/21250
---
 NEWS                             |  5 +++++
 sed/compile.c                    | 14 +++++++++++---
 testsuite/Makefile.am            | 13 +++++++------
 testsuite/colon-with-no-label.sh | 33 +++++++++++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 9 deletions(-)
 create mode 100755 testsuite/colon-with-no-label.sh

diff --git a/NEWS b/NEWS
index 6367dea..bc2f96f 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,11 @@ GNU sed NEWS                                    -*- outline -*-

 ** Bug fixes

+  sed no longer accepts a ":" command without a label; before, it would
+  treat that as defining a label whose name is empty, and subsequent
+  label-free "t" and "b" commands would use that label. Now, sed emits
+  a diagnostic and fails for that invalid construct.
+
   sed no longer accesses uninitialized memory when processing certain
   invalid multibyte sequences. Demonstrate with this:
     echo a | LC_ALL=ja_JP.eucJP valgrind sed/sed 's/a/b\U\xb2c/'
diff --git a/sed/compile.c b/sed/compile.c
index 51103e5..507a19f 100644
--- a/sed/compile.c
+++ b/sed/compile.c
@@ -138,7 +138,8 @@ static const char errors[] =
   "expected newer version of sed\0"
   "invalid usage of line address 0\0"
   "unknown command: `%c'\0"
-  "incomplete command";
+  "incomplete command\0"
+  "\":\" lacks a label";

 #define BAD_BANG (errors)
 #define BAD_COMMA (BAD_BANG + sizeof(N_("multiple `!'s")))
@@ -180,7 +181,9 @@ static const char errors[] =
 #define UNKNOWN_CMD (INVALID_LINE_0 \
   + sizeof(N_("invalid usage of line address 0")))
 #define INCOMPLETE_CMD (UNKNOWN_CMD + sizeof(N_("unknown command: `%c'")))
-/* #define END_ERRORS (INCOMPLETE_CMD + sizeof(N_("incomplete command"))) */
+#define COLON_LACKS_LABEL (INCOMPLETE_CMD \
+  + sizeof(N_("incomplete command")))
+/* #define END_ERRORS (COLON_LACKS_LABEL + sizeof(N_("\":\" lacks a label"))) */

 static struct output *file_read = NULL;
 static struct output *file_write = NULL;
@@ -1133,7 +1136,12 @@ compile_program(struct vector *vector)
         case ':':
           if (cur_cmd->a1)
             bad_prog(_(NO_COLON_ADDR));
-          labels = setup_label(labels, vector->v_length, read_label(), NULL);
+          {
+            char *label = read_label ();
+            if (!*label)
+              bad_prog(_(COLON_LACKS_LABEL));
+            labels = setup_label(labels, vector->v_length, label, NULL);
+          }
           break;

         case 'T':
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 9bd7465..455cb55 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -5,12 +5,13 @@ SH_LOG_COMPILER = $(SHELL)

 # Put new, init.sh-using tests here, so that each name
 # is listed in only one place.
-T =			\
-  follow-symlinks-stdin.sh \
-  help-version.sh	\
-  in-place-hyphen.sh	\
-  invalid-mb-seq-UMR.sh	\
-  range-overlap.sh	\
+T =				\
+  colon-with-no-label.sh	\
+  follow-symlinks-stdin.sh	\
+  help-version.sh		\
+  in-place-hyphen.sh		\
+  invalid-mb-seq-UMR.sh		\
+  range-overlap.sh		\
   temp-file-cleanup.sh

 TESTS = $(check_PROGRAMS) $(SEDTESTS) $(T)
diff --git a/testsuite/colon-with-no-label.sh b/testsuite/colon-with-no-label.sh
new file mode 100755
index 0000000..a2c4f3b
--- /dev/null
+++ b/testsuite/colon-with-no-label.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Verify that a ":" command with no label is now rejected.
+
+# Copyright (C) 2015 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+. "${srcdir=.}/init.sh"; path_prepend_ ../sed
+print_ver_ sed
+
+echo 'sed: -e expression #1, char 1: ":" lacks a label' > exp-err \
+  || framework_failure_
+
+fail=0
+
+# Before sed-4.3, sed would mistakenly accept a ":" with no following
+# label name.
+echo x | sed : > out 2> err && fail=1
+
+compare /dev/null out || fail=1
+compare exp-err err || fail=1
+
+Exit $fail
-- 
2.3.7