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