** Description changed:

  [Problem]
  mawk loses data due to an improperly constructed memcpy() call.
  
  [Impact]
  Data loss in a data processing utility.  Frequency of bugs affecting users is 
not known, but with the given test case occurs 100%.  lucid, maverick, natty, 
oneiric, and precise all carry mawk 1.3.3 and thus are affected.
  
  [Development Fix]
  Fixed upstream as of mawk-1.3.4-20100419.  We're carrying version 
1.3.3-16ubuntu2 in precise, which is affected by the bug.  Same patch as is 
proposed in this SRU was uploaded to Precise March 22nd (Since we're frozen for 
beta2, it is delayed for archive admin review).
  
  [Stable Fix]
  lp:~tjvries/ubuntu/natty/mawk/fix-for-955791 is a debdiff for natty that 
applies this 1-liner change.
  
- [Text Case]
+ [Test 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==
  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.

-- 
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