|
From: <dom...@fr...> - 2006-08-11 22:37:29
|
Hi,
Valgrind is great. Thanks for writing such a useful tool.
Valgrind currently does not check for pointer arithmetics
or pointer comparisons on unrelated pointers. I am not
sure whether it could be possible to detect such bugs
with valgrind.
Here is a short example to illustrate:
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
$ cat unrelated-ptr.c
/*
* Test case to illustrate possible bugs: pointer arithmetics
* or pointer comparisons on unrelated pointer (-> undefined
* result)
*
* Valgrind/memcheck currently does not detect such bug.
*/
#include <malloc.h>
#include <stdio.h>
int main()
{
int cmp1, cmp2;
int diff1, diff2;
char *buf1 =3D malloc(10);
char *buf2 =3D malloc(10);
const char *str =3D "hello";
/* Bug: comparing unrelated pointer (-> undefined result) */
cmp1 =3D (buf1 > str); /* compare pointer in heap & in text/bss sectio=
n */
cmp2 =3D (buf1 > buf2); /* compare 2 different malloc blocks -> undefin=
ed */
/* Bug: pointer arithmetics on unrelated pointer (-> undefined result) =
*/
diff1 =3D buf1 - str;
diff2 =3D buf1 - buf2;
fprintf(stderr, "cmp1=3D%d cmp2=3D%d diff1=3D%d diff2=3D%d\n",
cmp1, cmp2, diff1, diff2);
free(buf1); free(buf2);
return 0;
}
$ gcc -Wall unrelated-ptr.c
$ valgrind --tool=3Dmemcheck ./a.out
=3D=3D5860=3D=3D Memcheck, a memory error detector.
=3D=3D5860=3D=3D Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward=
et al.
=3D=3D5860=3D=3D Using LibVEX rev 1471, a library for dynamic binary tran=
slation.
=3D=3D5860=3D=3D Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP=
.
=3D=3D5860=3D=3D Using valgrind-3.1.0-Debian, a dynamic binary instrument=
ation
framework.
=3D=3D5860=3D=3D Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward=
et al.
=3D=3D5860=3D=3D For more details, rerun with: -v
=3D=3D5860=3D=3D
cmp1=3D0 cmp2=3D0 diff1=3D-65971588 diff2=3D-64
=3D=3D5860=3D=3D
=3D=3D5860=3D=3D ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 =
from 1)
=3D=3D5860=3D=3D malloc/free: in use at exit: 0 bytes in 0 blocks.
=3D=3D5860=3D=3D malloc/free: 2 allocs, 2 frees, 20 bytes allocated.
=3D=3D5860=3D=3D For counts of detected errors, rerun with: -v
=3D=3D5860=3D=3D No malloc'd blocks -- no leaks are possible.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
The value it prints for cmp1, cmp2, diff1 and diff2 depends
on how compiler & OS organises memory.
Notice that neither valgrind nor 'gcc -Wall' detect any bug.
-> could valgrind be able to detect such bugs?
Cheers
/Dominique
|
|
From: Nicholas N. <nj...@cs...> - 2006-08-12 00:43:17
|
On Sat, 12 Aug 2006 dom...@fr... wrote: > Valgrind currently does not check for pointer arithmetics > or pointer comparisons on unrelated pointers. I am not > sure whether it could be possible to detect such bugs > with valgrind. > > [...] > > -> could valgrind be able to detect such bugs? I suspect this would be both difficult to do, and not that useful. First the difficulty. The hard part of this is working out what is a pointer, and what is not. It's easy to do with pointers to heap blocks, because they're returned by malloc(). Addresses of stack and static variables are much harder to find -- basically you have to rely on debug info to find them. Another difficulty is that programs often use pointer differencing that is undefined according to the C standard, but almost always works. The classic example is something like memcpy or memcmp, where you find the difference between block1 and block2, and then increment block1 one byte at a time -- you can find the corresponding byte in block two by adding the difference to block1. This works on any typical machine. There may be other examples; in my experience real programs often do far stranger things than you might expect. Using the C spec as a guide for finding bugs is questionable anyway, since Valgrind is really operating at the binary level, where programs may not be written in C. As for the usefulness, I suspect this kind of thing is not a common source of bugs. Have you ever had a bug caused by this kind of operation? You might be interested in reading "Bounds-Checking Entire Programs Without Recompiling", a paper at http://www.valgrind.org/docs/pubs.html. It talks about a tool that does bounds-checking, and covers in more detail some issues related to this idea, such as finding pointers. One basic conclusion of this paper, although the paper doesn't say it as such, is that trying to do stuff that relies on pointers via binary instrumentation is pretty difficult, and would be better done via source-level instrumentation. Nick |
|
From: Behdad E. <bes...@re...> - 2006-08-14 01:06:56
|
On Sat, 2006-08-12 at 10:43 +1000, Nicholas Nethercote wrote: > As for the usefulness, I suspect this kind of thing is not a common sourc= e=20 > of bugs. Have you ever had a bug caused by this kind of operation? I've seen them a few times, while a pointer to string A was being compared to string B for example. This is one such bug that I found in glib a couple years ago: http://bugzilla.gnome.org/show_bug.cgi?id=3D126640 --=20 behdad http://behdad.org/ |