bug-grep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

valgrind warns of regexec.c/memmove buffer read overrun


From: Jim Meyering
Subject: valgrind warns of regexec.c/memmove buffer read overrun
Date: Thu, 15 Mar 2012 13:04:45 +0100

I'll write this to the grep list, since it arose from a valgrind alert
against one of grep's regression tests, but it's mainly to say that
this is *not* a problem with grep/regexec/memmove.

On F17/x86_64, I ran these commands:

    s=$(printf '\304\215y\304\215')                                            :
    echo "x $s" > in                                                           :
    LC_ALL=cs_CZ.UTF-8 valgrind grep --color=always -Ei "$s" in

and valgrind warned about an 8-byte read starting just 4 bytes from the
end of a regexec.c-internal heap buffer.  That means memmove has read
four bytes beyond the end of that buffer:

   Invalid read of size 8
      at 0x3FD448E38D: _wordcopy_fwd_dest_aligned (wordcopy.c:205)
      by 0x3FD4487F93: __GI_memmove (memmove.c:76)
      by 0x3FD44C4525: re_string_reconstruct (regex_internal.c:675)
      by 0x3FD44D3D87: re_search_internal (regexec.c:829)
      by 0x3FD44D5474: re_search_stub (regexec.c:463)
      by 0x3FD44D5D17: re_search (regexec.c:326)
      by 0x404287: ??? (in /usr/bin/grep)
      by 0x405BF2: ??? (in /usr/bin/grep)
      by 0x4062AF: ??? (in /usr/bin/grep)
      by 0x406409: ??? (in /usr/bin/grep)
      by 0x406BE8: ??? (in /usr/bin/grep)
      by 0x4038DC: ??? (in /usr/bin/grep)
    Address 0x4c3bcb8 is 24 bytes inside a block of size 28 alloc'd
      at 0x4A0884D: malloc (vg_replace_malloc.c:263)
      by 0x4A089CF: realloc (vg_replace_malloc.c:632)
      by 0x3FD44D3A37: re_search_internal (regex_internal.c:143)
      by 0x3FD44D5474: re_search_stub (regexec.c:463)
      by 0x3FD44D5D17: re_search (regexec.c:326)
      by 0x404287: ??? (in /usr/bin/grep)
      by 0x405BF2: ??? (in /usr/bin/grep)
      by 0x4062AF: ??? (in /usr/bin/grep)
      by 0x406409: ??? (in /usr/bin/grep)
      by 0x406BE8: ??? (in /usr/bin/grep)
      by 0x4038DC: ??? (in /usr/bin/grep)

And if you dig into regexec.c (already rather deep), and from there
into glibc's wordcopy.c and memmove.c (deep enough to make even Roland
cringe), you see that this is deliberate.  For an memmove use like the
one in regexec.c, char *buf = malloc(28); ... memmove (buf, buf+4, 24);
where the destination pointer, "buf", is 8-byte aligned, but the source
pointer is not, the underlying code reads 32 bytes (four 8-byte op_t's) in
order to write the three 8-byte-aligned op_t's.  Since it reads beyond end
of buffer only when the source pointer is not aligned to an op_t boundary,
I've convinced myself that there is no way reading those extra bytes
(up to 7) could cross a page boundary.

Now that I'm convinced this is not a bug, the question is whether we
can avoid the false positive.  I.e., can valgrind be taught that when a
memmove call appears to read a few bytes beyond end of the source buffer,
that it is ok, as long the overrun is consistent with the alignment of
the source pointer?

For the record, the memmove use is here:

Breakpoint 1, re_string_reconstruct (address@hidden,
    address@hidden, address@hidden) at regex_internal.c:675
675                     memmove (pstr->wcs, pstr->wcs + offset,
(gdb) p pstr->wcs
$1 = (wint_t *) 0x8222a0

And the offending read happened here:

#0  _wordcopy_fwd_dest_aligned (dstp=<optimized out>, srcp=<optimized out>,
    len=3) at wordcopy.c:205
205           a3 = ((op_t *) srcp)[3];



reply via email to

[Prev in Thread] Current Thread [Next in Thread]