** Description changed:

+ [Impact]
+ <fill me in with explanation of severity and frequency of bug on users and 
justification for backporting the fix to the stable release>
+ 
+ [Development Fix]
+ <fill me in with an explanation of how the bug has been addressed in the 
development branch, including the relevant version numbers of packages modified 
in order to implement the fix. >
+ 
+ [Stable Fix]
+ <fill me in by pointing out a minimal patch applicable to the stable version 
of the package.>
+ 
+ [Text Case]
+ <fill me in with detailed *instructions* on how to reproduce the bug.  This 
will be used by people later on to verify the updated package fixes the 
problem.>
+ 1.
+ 2.
+ 3.
+ Broken Behavior: 
+ Fixed Behavior: 
+ 
+ [Regression Potential]
+ <fill me in with a discussion of likelihood and potential severity of 
regressions and how users could get inadvertently affected. 
+ 
+ [Original Report]
  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== 
+ ==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== 
+ ==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== 
+ ==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== 
+ ==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 ;
+    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 ;
+       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 ;
-    }
+       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 "field.h"
+  #include "symtype.h"
+  #include "scan.h"
  +#include <stdlib.h>
-  
-  #ifndef        NO_FCNTL_H
-  #include <fcntl.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 ;
+     {
+        /* 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)
+        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.

-- 
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
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to