Re: busybox sed not POSIX-conforming?

"Roberto A. Foglietta" <[email protected]>
Newsgroups gmane.comp.printing.groff.general
Message-ID <CAJGKYO71DyJ7+sQCHRkshHOG3OneENyuYP3FT-W14t1_Ld_CoQ@mail.gmail.com>
On Thu, 20 Aug 2026 at 22:55, Rob Landley via busybox
<[email protected]> wrote:
>
> On 8/6/26 21:30, G. Branden Robinson via busybox wrote:
> > [looping in busybox mailing list; Bruno found a sed portability problem]
> >
> > Background:
> > https://savannah.gnu.org/bugs/?68601
> >
> > Hi Bruno,
> >
> > At 2026-08-06T18:07:55+0200, Bruno Haible wrote:
> >> I wrote:
> >>> The reason is that the 'sed' program on this platform (from BusyBox)
> >>> ignores '-e' options when a '-f' option is present, regardless
> >>> whether the '-e' options come before or after the '-f' option.
>
> Which apparently nobody noticed for 20 years.

Or nobody cared about it for 20 years, which is apparently the same
thing but it isn't.

sed.c: POSIX compliance fix about '-f' with '-e' ordered options v3
https://github.com/robang74/busybox/commit/825b8f85af52adfe14bc07eb3aaff5fcc50a7070

sed.c: POSIX compliance fix about '-f' with '-e' ordered options v2
https://github.com/robang74/busybox/commit/d1f50a14db96968d4ecc1cb042dfb83bd2cd6a01

Are these two solving the problem?

Best regards,
-- 
Roberto A. Foglietta
+49.176.274.75.661
+39.349.33.30.697
0002-sed.c-POSIX-compliance-fix-about-f-with-e-ordered-op.patch (text/x-patch, 3.5 KB)
From 825b8f85af52adfe14bc07eb3aaff5fcc50a7070 Mon Sep 17 00:00:00 2001
From: "Roberto A. Foglietta" <[email protected]>
Date: Mon, 17 Aug 2026 08:57:33 +0200
Subject: [PATCH 2/9] sed.c: POSIX compliance fix about '-f' with '-e' ordered
 options v3

goal:

Processing '-e' and '-f' options in command line order for
achieving the POSIX compliance as expected by the command line.

how:

The getopt32long stores them in separate lists, losing
their relative order. We determine which appeared first
by finding which argv[] element each optarg points into.

bug:

- https://savannah.gnu.org/bugs/?68601

fix:

   text    data     bss     dec     hex filename
   7352       0       0    7352    1cb8 editors/sed.o
   7441       0       0    7441    1d11 editors/sed.o v1
   7465       0       0    7465    1d29 editors/sed.o v2
   7508       0       0    7508    1d54 editors/sed.o v3
                           +156

v1 --> v2:
- from string comparison to a more compatct options check
v2 --> v3:
- what about -nre? or -nve? uncommon but lecit and broken, fixed

requires:

- sed.c: POSIX compliance fix about '-f' with '-e' ordered options v2

todo:

- test in testsuite
- footprint reduction

Signed-off-by: Roberto A. Foglietta <[email protected]>
---
 editors/sed.c | 57 ++++++++++++++++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 21 deletions(-)

diff --git a/editors/sed.c b/editors/sed.c
index 9d14294fb..4dd89fa8d 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -1528,7 +1528,7 @@ static void add_cmd_block(char *cmdstr)
 int sed_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int sed_main(int argc UNUSED_PARAM, char **argv)
 {
-	unsigned opt, i;
+	unsigned opt;
 	llist_t *opt_e, *opt_f;
 	char *opt_i;
 
@@ -1568,36 +1568,51 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
 			sed_longopts,
 			&opt_i, &opt_e, &opt_f,
 			&G.be_quiet); /* counter for -n */
-
-
-	/* Process -e and -f options in command line order.
-	 * getopt32long stores them in separate lists, losing
-	 * their relative order. We re-scan argv to preserve it.
+	/*
+	 * RAF: process -e and -f options in command line order.
+	 * The getopt32long stores them in separate lists, losing
+	 * their relative order. We determine which appeared first
+	 * by finding which argv[] element each optarg points into.
 	 */
-	for (i = 1; i < optind; i++)
-	{
-		char *p = argv[i], c = *p;
-		if (c != '-' || !*++p) //'-'
-			continue;
-		if (*p == '-' && !*++p) //'--'
-			continue;
-		c = *p;
-		if (c == 'e' && opt_e) {
-			add_cmd_block(llist_pop(&opt_e));
+	while (opt_e || opt_f) {
+		int use_e = 1;
+		if (opt_e && opt_f) {
+			int i, idx_e = optind, idx_f = optind;
+			for (i = 1; i < optind; i++) {
+				char *end = argv[i] + strlen(argv[i]);
+				if (idx_e == optind
+				&&  opt_e->data >= argv[i]
+				&&  opt_e->data <= end
+				){
+					idx_e = i;
+				}
+				if (idx_f == optind
+				&&  opt_f->data >= argv[i]
+				&&  opt_f->data <= end
+				){
+					idx_f = i;
+				}
+			}
+			if (idx_f < idx_e) {
+				use_e = 0;
+			}
 		}
 		else
-		if (c == 'f' && opt_f) {
+		if (!opt_e) {
+			use_e = 0;
+		}
+		if (use_e) {
+			add_cmd_block(llist_pop(&opt_e));
+		} else {
 			char *line;
 			FILE *cmdfile = xfopen_stdin(llist_pop(&opt_f));
-			while ( (line = xmalloc_fgetline(cmdfile)) ) {
+			while ((line = xmalloc_fgetline(cmdfile)) != NULL) {
 				add_cmd(line);
 				free(line);
 			}
 			fclose_if_not_stdin(cmdfile);
-		}
+ 		}
 	}
-	llist_free(opt_e, free);
-	llist_free(opt_f, free);
 
 	//argc -= optind;
 	argv += optind;
-- 
2.34.1
0001-sed.c-POSIX-compliance-fix-about-f-with-e-ordered-op.patch (text/x-patch, 2.7 KB)
From d1f50a14db96968d4ecc1cb042dfb83bd2cd6a01 Mon Sep 17 00:00:00 2001
From: "Roberto A. Foglietta" <[email protected]>
Date: Mon, 17 Aug 2026 07:38:13 +0200
Subject: [PATCH 1/9] sed.c: POSIX compliance fix about '-f' with '-e' ordered
 options v2

bug found:

- https://savannah.gnu.org/bugs/?68601

fix size:

   text    data     bss     dec     hex filename
   7352       0       0    7352    1cb8 editors/sed.o
   7441       0       0    7441    1d11 editors/sed.o v1
   7465       0       0    7465    1d29 editors/sed.o v2
                           +113

regression:

- what about -nre? or -nve? uncommon but lecit and broken

Signed-off-by: Roberto A. Foglietta <[email protected]>
---
 editors/sed.c | 47 +++++++++++++++++++++++++++++++++--------------
 1 file changed, 33 insertions(+), 14 deletions(-)

diff --git a/editors/sed.c b/editors/sed.c
index 029e9b8e7..9d14294fb 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -1528,7 +1528,7 @@ static void add_cmd_block(char *cmdstr)
 int sed_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int sed_main(int argc UNUSED_PARAM, char **argv)
 {
-	unsigned opt;
+	unsigned opt, i;
 	llist_t *opt_e, *opt_f;
 	char *opt_i;
 
@@ -1568,6 +1568,37 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
 			sed_longopts,
 			&opt_i, &opt_e, &opt_f,
 			&G.be_quiet); /* counter for -n */
+
+
+	/* Process -e and -f options in command line order.
+	 * getopt32long stores them in separate lists, losing
+	 * their relative order. We re-scan argv to preserve it.
+	 */
+	for (i = 1; i < optind; i++)
+	{
+		char *p = argv[i], c = *p;
+		if (c != '-' || !*++p) //'-'
+			continue;
+		if (*p == '-' && !*++p) //'--'
+			continue;
+		c = *p;
+		if (c == 'e' && opt_e) {
+			add_cmd_block(llist_pop(&opt_e));
+		}
+		else
+		if (c == 'f' && opt_f) {
+			char *line;
+			FILE *cmdfile = xfopen_stdin(llist_pop(&opt_f));
+			while ( (line = xmalloc_fgetline(cmdfile)) ) {
+				add_cmd(line);
+				free(line);
+			}
+			fclose_if_not_stdin(cmdfile);
+		}
+	}
+	llist_free(opt_e, free);
+	llist_free(opt_f, free);
+
 	//argc -= optind;
 	argv += optind;
 	if (opt & OPT_in_place) { // -i
@@ -1577,19 +1608,7 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
 		G.regex_type |= REG_EXTENDED; // -r or -E
 	//if (opt & 8)
 	//	G.be_quiet++; // -n (implemented with a counter instead)
-	while (opt_e) { // -e
-		add_cmd_block(llist_pop(&opt_e));
-	}
-	while (opt_f) { // -f
-		char *line;
-		FILE *cmdfile;
-		cmdfile = xfopen_stdin(llist_pop(&opt_f));
-		while ((line = xmalloc_fgetline(cmdfile)) != NULL) {
-			add_cmd(line);
-			free(line);
-		}
-		fclose_if_not_stdin(cmdfile);
-	}
+
 	/* if we didn't get a pattern from -e or -f, use argv[0] */
 	if (!(opt & 0x30)) {
 		if (!*argv)
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.