Public bug reported:

Source package: mawk
release: 11.10 x86_64
version: 1.3.3-15ubuntu2

on 11.10,  I run this series of commands. Both greps are supposed to return 4.
...
$ grep -c 'abi/mangle33.C.*scan' CAT | grep -v ':0'
4
$ rm -f list[0-9]*
$ cat CAT | mawk -f guts.awk
$ grep -c 'abi/mangle33.C.*scan' list* | grep -v ':0'
3
....
This doesn't reproduce on 10.10, there indeed the last grep returns 4.

Running valgrind on the mawk invocation reveals a problem:
...
$ cat CAT | valgrind mawk -f guts.awk
==8659== Memcheck, a memory error detector
==8659== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==8659== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright 
info
==8659== Command: mawk -f guts.awk
==8659== 
Running target unix
==8659== Source and destination overlap in memcpy(0x545dd90, 0x545e569, 2087)
==8659==    at 0x4C2A1C4: memcpy (mc_replace_strmem.c:635)
==8659==    by 0x410FC7: ??? (in /usr/bin/mawk)
==8659==    by 0x406BA5: ??? (in /usr/bin/mawk)
==8659==    by 0x405F99: ??? (in /usr/bin/mawk)
==8659==    by 0x50D430C: (below main) (libc-start.c:226)
==8659== 
...
And that reproduces on 10.10 as well.

I recompiled the source package at -O0 with -g3, and reran valgrind:
...
$ cat CAT | valgrind mawk/mawk-1.3.3/mawk -f guts.awk
==9007== Memcheck, a memory error detector
==9007== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==9007== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright 
info
==9007== Command: mawk/mawk-1.3.3/mawk -f guts.awk
==9007== 
Running target unix
==9007== Source and destination overlap in memcpy(0x545dd90, 0x545e569, 2087)
==9007==    at 0x4C2A1C4: memcpy (mc_replace_strmem.c:635)
==9007==    by 0x41465E: FINgets (fin.c:329)
==9007==    by 0x409674: execute (execute.c:1116)
==9007==    by 0x406F8A: main (main.c:66)
==9007== 
...

That gives me the violating memcpy:
...
   if (p == fin->buff)
   {
      /* current record is too big for the input buffer, grow buffer */
      p = enlarge_fin_buffer(fin) ;
   }
   else
   {
      /* move a partial line to front of buffer and try again */
      unsigned rr ;

      p = (char *) memcpy(fin->buff, p, r = strlen(p)) ;
      q = p+r ;  rr = fin->nbuffs*BUFFSZ - r ;

      if ((r = fillbuff(fin->fd, q, rr)) < rr)
         fin->flags |= EOF_FLAG ;
   }
...

Using the following patch, I abort when the error condition is detected, and 
now I can reproduce on both 11.10 and 10.10 without valgrind, and easily hit 
the error in a gdb session.
...
--- fin.c       2012-03-15 09:03:59.674854168 +0100
+++ fin.c.fixed 2012-03-15 09:02:32.910857237 +0100
@@ -76,6 +76,7 @@
 #include "field.h"
 #include "symtype.h"
 #include "scan.h"
+#include <stdlib.h>
 
 #ifndef          NO_FCNTL_H
 #include <fcntl.h>
@@ -325,8 +326,19 @@
    {
       /* move a partial line to front of buffer and try again */
       unsigned rr ;
-
-      p = (char *) memcpy(fin->buff, p, r = strlen(p)) ;
+      char *src, *dst, *srclast, *dstlast;
+      dst = fin->buff;
+      src = p;
+      r = strlen(p);
+      srclast = src + r - 1;
+      dstlast = dst + r - 1;
+      if (!(srclast < dst || dstlast < src))
+       {
+         fprintf (stderr, "overlapping memcpy (%lx, %lx, %u)\n", dst, src, r);
+         fflush (stderr);
+         abort ();
+       }
+      p = (char *)memcpy (fin->buff, p, r) ;
       q = p+r ;         rr = fin->nbuffs*BUFFSZ - r ;
 
       if ((r = fillbuff(fin->fd, q, rr)) < rr)
...

Replacing the memcpy with a memmove fixes the problem, and I think it's
a sufficient fix.

** Affects: mawk (Ubuntu)
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/955791

Title:
  Source and destination overlap in memcpy

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/mawk/+bug/955791/+subscriptions

-- 
ubuntu-bugs mailing list
ubuntu-bugs@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to