Hmm, notice that lucid, maverick, natty, oneiric, precise all carry
1.3.3, so presumably this SRU is applicable to all of them.

** 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%.
+ 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 (TODO: Verify).  We're carrying 
version 1.3.3-16ubuntu2 in precise.  (TODO: Do we need to fix in precise as 
well?)
  
  [Stable Fix]
- lp:~tjvries/ubuntu/natty/mawk/fix-for-955791 is a debdiff for natty that 
applies this 1-liner change.  (TODO: Does oneiric need the fix too?)
+ lp:~tjvries/ubuntu/natty/mawk/fix-for-955791 is a debdiff for natty that 
applies this 1-liner change.  
  
  [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==
  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