Re: [PATCH] Fix ed shell command when stdout isn't line-buffered

2022-01-22 Thread Theo de Raadt
Todd C. Miller  wrote:

> On Sat, 22 Jan 2022 14:24:17 +0100, =?UTF-8?Q?S=C3=B6ren?= Tempel wrote:
> 
> > The patch below fixes this issue by flushing all open output streams
> > before executing the command using system(3). Alternatively, it may also
> > be sufficient to only flush stdout and (maybe) stderr.
> 
> Just flushing everything is the safest approach.  This looks fine
> to me.

Yes I agree also.



Re: [PATCH] Fix ed shell command when stdout isn't line-buffered

2022-01-22 Thread Todd C . Miller
On Sat, 22 Jan 2022 14:24:17 +0100, =?UTF-8?Q?S=C3=B6ren?= Tempel wrote:

> The patch below fixes this issue by flushing all open output streams
> before executing the command using system(3). Alternatively, it may also
> be sufficient to only flush stdout and (maybe) stderr.

Just flushing everything is the safest approach.  This looks fine
to me.

 - todd



[PATCH] Fix ed shell command when stdout isn't line-buffered

2022-01-22 Thread Sören Tempel
Hello,

The ed shell escape command currently behaves incorrectly if standard
output isn't line-buffered. As an example, consider the following ed(1)
invocations:

$ cat /tmp/ed-cmd
!echo foo
!!
$ ed < /tmp/ed-cmd
foo
!
echo foo
foo
!
$ ed < /tmp/ed-cmd > /tmp/ed-out.txt
$ cat /tmp/ed-out.txt
foo
foo
!
echo foo
!

The output of the first and second invocation differs in regards to when
the modified command-string of the !! command is output. In the first
invocation, it is output before the command is executed (which is the
behavior mandated by POSIX). However, in the second invocation it is
output **after** the command was executed (which is incorrect).

This is due to the fact that in the second invocation standard output is
a file and hence not line-buffered. Unfortunately, ed(1) does currently
not flush all I/O buffers before executing the command using system(3).
As such, output of the command will be written to standard output before
any data buffered by ed itself is written.

The patch below fixes this issue by flushing all open output streams
before executing the command using system(3). Alternatively, it may also
be sufficient to only flush stdout and (maybe) stderr.

This issue was originally discovered in GNU ed where it has been fixed
since. See: https://lists.gnu.org/archive/html/bug-ed/2021-12/msg0.html

Greetings,
Sören Tempel

diff --git bin/ed/main.c bin/ed/main.c
index dc73dd92b..1e3cd8bdb 100644
--- bin/ed/main.c
+++ bin/ed/main.c
@@ -852,6 +852,7 @@ exec_command(void)
return ERR;
GET_COMMAND_SUFFIX();
if (sflags) printf("%s\n", shcmd + 1);
+   fflush(NULL); /* flush any buffered I/O */
system(shcmd + 1);
if (!scripted) printf("!\n");
break;