bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

sed bug (and fix) with regular files not at start ...


From: Cameron Simpson
Subject: sed bug (and fix) with regular files not at start ...
Date: Sun, 26 Aug 2001 09:25:50 +0000

Using sed-3.02 on a Linux system I saw behaviour I didn't believe.
I've just read the sed source and it's a bug in sed.

When sed is handed a regular file it mmap()s it for efficiency.  When it
does this it doesn't bother to check the file offset.  for files named
on the command line that's fine, because they are opened de novo.

However, when the file is stdin then the offset is vital.

Test script:

        #!/bin/sh
        tmp=/tmp/foo
        echo foo >$tmp
        echo bar >>$tmp
        exec <$tmp
        read line1
        echo "$line1"
        sed 's/^/SED/'

That script should print:

        foo
        SEDbar

With GNU sed-3.02 it prints:

        foo
        SEDfoo
        SEDbar

This is because the mmap()ed file is read from the beginning.
An example patch to correct this behaviour is appended below.

This is somewhat a classic case of needless optimisation introducing bugs,
and a bit annoying because a good stdio library (like glibc or the stdio
in solaris) will do this optimisation for you.

I notice that compile.c makes the same mistake.
Probably this fix should be applied in map_file and not in compile.c and
execute.c.

Cheers,
Cameron Simpson, DoD#743        address@hidden    http://www.zip.com.au/~cs/

--- sed-3.02/sed/execute.c-orig Sun Aug 26 19:31:39 2001
+++ sed-3.02/sed/execute.c      Sun Aug 26 20:12:11 2001
@@ -234,6 +234,7 @@
   const char *name;
   struct input *input;
 {
+  long offset;
   input->base = NULL;
   buffer.length = 0;
 
@@ -252,10 +253,12 @@
     }
 
   input->read_fn = read_file_line;
-  if (map_file(input->fp, &input->base, &input->length))
+  if (map_file(input->fp, &input->base, &input->length)
+   && (offset=ftell(input->fp)) != -1
+     )
     {
-      input->cur = VCAST(char *)input->base;
-      input->left = input->length;
+      input->cur = VCAST(char *)input->base+offset;
+      input->left = input->length-offset;
       input->read_fn = read_mem_line;
     }
 #ifdef HAVE_ISATTY



reply via email to

[Prev in Thread] Current Thread [Next in Thread]