Re: [ANNOUNCE] kmemcheck v7
From: Jeremy Fitzhardinge
Date: Sat May 10 2008 - 16:45:45 EST
Andi Kleen wrote:
It tracks changes to the stack pointer, and any memory below it is
considered uninitialized. But, yes, if you mean that if you use the
But it does not invalidate anything below the stack pointer as soon
as it changes right ?
Yeah, as soon as the stack pointer changes, everything below it is
invalidated (except if the stack-pointer change was actually determined
to be a stack switch).
variable (or slot) once in a function, then again later, it will still
be considered initialized. But that's no different from any other memory.
What I meant is e.g.
f1();
f2();
both f1 and f2 use the same stack memory, but f2 uses it uninitialized,
then I think valgrind would still think it is initialized in f2 from the
execution of f1. It would only detect such things in f1 (assuming there
were no other users of the stack before that)
No, it won't. If the stack pointer goes up then down between f1 and f2,
then f2 will get fresh values.
The big thing Valgrind hasn't traditionally helped with is overruns of
on-stack arrays. You may be thinking of that.
In theory it could throw away all stack related uninitizedness on each
SP change, but that would be likely prohibitively expensive and also
it might be hard to know the exact boundaries of the stack.
No, its not all that expensive compared the overall cost of valgrind and
the amount of diagnostic power it provides. Determining stack
boundaries has always been a bit fraught. Typically a stack switch has
been determined heuristically by looking for a "large" change in stack
pointer, but there's a callback to specifically mark a range of memory
as a stack, so that movements into and out of a stack can be determined
as a switch (added specifically to deal with small densely packed stacks
in uml).
BTW on running a test program here it doesn't seem to detect any uninitialized
stack frames here with 3.2.3. Test program is http://halobates.de/t10.c
(should be compiled without optimization)
Hm, I'd expect it to. Oh, your test program doesn't use the value.
Valgrind doesn't complain about uninitialized values unless they
actually affect execution (ie, a conditional depends on one, you use it
as an address for a dereference, or pass it to a syscall).
The attached version emits errors as I'd expect:
$ valgrind t10
==30474== Memcheck, a memory error detector.
==30474== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==30474== Using LibVEX rev 1804, a library for dynamic binary translation.
==30474== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==30474== Using valgrind-3.3.0, a dynamic binary instrumentation framework.
==30474== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==30474== For more details, rerun with: -v
==30474==
f1 set y to 1
==30474== Conditional jump or move depends on uninitialised value(s)
==30474== at 0x8048420: test (t10.c:22)
==30474== by 0x8048451: main (t10.c:29)
==30474==
==30474== Use of uninitialised value of size 4
==30474== at 0xB5C5B6: _itoa_word (in /lib/libc-2.8.so)
==30474== by 0xB5FF90: vfprintf (in /lib/libc-2.8.so)
==30474== by 0xB6769F: printf (in /lib/libc-2.8.so)
==30474== by 0x8048436: test (t10.c:23)
==30474== by 0x8048451: main (t10.c:29)
==30474==
==30474== Conditional jump or move depends on uninitialised value(s)
==30474== at 0xB5C5BE: _itoa_word (in /lib/libc-2.8.so)
==30474== by 0xB5FF90: vfprintf (in /lib/libc-2.8.so)
==30474== by 0xB6769F: printf (in /lib/libc-2.8.so)
==30474== by 0x8048436: test (t10.c:23)
==30474== by 0x8048451: main (t10.c:29)
==30474==
==30474== Conditional jump or move depends on uninitialised value(s)
==30474== at 0xB5EADE: vfprintf (in /lib/libc-2.8.so)
==30474== by 0xB6769F: printf (in /lib/libc-2.8.so)
==30474== by 0x8048436: test (t10.c:23)
==30474== by 0x8048451: main (t10.c:29)
==30474==
==30474== Conditional jump or move depends on uninitialised value(s)
==30474== at 0xB60828: vfprintf (in /lib/libc-2.8.so)
==30474== by 0xB6769F: printf (in /lib/libc-2.8.so)
==30474== by 0x8048436: test (t10.c:23)
==30474== by 0x8048451: main (t10.c:29)
==30474==
==30474== Conditional jump or move depends on uninitialised value(s)
==30474== at 0xB5EB88: vfprintf (in /lib/libc-2.8.so)
==30474== by 0xB6769F: printf (in /lib/libc-2.8.so)
==30474== by 0x8048436: test (t10.c:23)
==30474== by 0x8048451: main (t10.c:29)
f2 set y to 13123572
==30474==
==30474== ERROR SUMMARY: 20 errors from 6 contexts (suppressed: 13 from 1)
==30474== malloc/free: in use at exit: 0 bytes in 0 blocks.
==30474== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==30474== For counts of detected errors, rerun with: -v
==30474== All heap blocks were freed -- no leaks are possible.
J
#include <stdio.h>
int y;
void f1(void)
{
int x = 1;
y = x;
}
void f2(void)
{
int x;
y = x;
}
void test()
{
f1();
if (y)
printf("f1 set y to %d\n", y);
f2();
if (y)
printf("f2 set y to %d\n", y);
}
main()
{
char buf[16 * 1024];
test();
}