|
From: John R.
|
Valgrind 2.0.0 (memcheck) does not notice when a conditional jump
depends on an uninitialized bit.
-----jfrtest2.c
#include <stdio.h> /* printf */
int
test2()
{
unsigned const b = 2; /* has exactly one '1' bit; rest are '0' */
unsigned x; /* uninitialized */
/* Uncomment the following line to see complaints
* from memcheck about 'x' uninit as used by printf.
*/
/*printf("uninitialized x=%#x\n", x);*/
x &= 0x80808080; /* leaving 4 bits uninit */
x |= 0x11111111; /* each nibble now is either 1 or 9 */
/* (x % 15) adds the nibbles because 1==(16 mod 15) */
/* The possible values of (x % 15) are {1,2,8,9,10} only. */
if (b & (x % 15)) {
printf("uninit caught %#x\n", x);
}
return 0;
}
void
proof2() /* Prove "b & (x % 15)" can have both zero and non-zero value. */
{
unsigned const b = 2; /* has exactly one '1' bit; rest are '0' */
int seen = 0;
int summary = 0;
unsigned j = 0;
do { /* check all 2**32 possible values; takes 2.5 minutes @ 1.6GHz */
unsigned x = --j;
x &= 0x80808080; /* leaving 4 bits uninit */
x |= 0x11111111; /* each nibble is either 1 or 9 */
summary |= 1<<(x % 15);
if (0==((1<<1) & seen) && 0!=(b & (x % 15))) {
seen |= (1<<1);
printf("1 %#x %#x\n", j, x);
} else
if (0==((1<<0) & seen) && 0==(b & (x % 15))) {
seen |= (1<<0);
printf("0 %#x %#x\n", j, x);
}
if (0 && ((1<<1)|(1<<0))==seen) { /* enable for shortest both-ways examples */
break;
}
} while (0!=j);
printf("summary of possible bits = %#x\n", summary);
}
int
main()
{
int const r = test2();
/*proof2();*/ /* optional */
return r;
}
-----end jfrtest2.c
$ gcc -g -o jfrtest2 jfrtest2.c
$ valgrind ./jfrtest2
==7141== Memcheck, a.k.a. Valgrind, a memory error detector for x86-linux.
==7141== Copyright (C) 2002-2003, and GNU GPL'd, by Julian Seward.
==7141== Using valgrind-2.0.0, a program supervision framework for x86-linux.
==7141== Copyright (C) 2000-2003, and GNU GPL'd, by Julian Seward.
==7141== Estimated CPU clock rate is 1630 MHz
==7141== For more details, rerun with: -v
==7141==
==7141==
==7141== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$ gdb jfrtest2 ## generated assembly code looks OK
(gdb) x/23i test2
0x8048328 <test2>: push %ebp
0x8048329 <test2+1>: mov %esp,%ebp
0x804832b <test2+3>: sub $0x18,%esp
0x804832e <test2+6>: movl $0x2,0xfffffffc(%ebp)
0x8048335 <test2+13>: lea 0xfffffff8(%ebp),%eax
0x8048338 <test2+16>: andl $0x80808080,(%eax)
0x804833e <test2+22>: lea 0xfffffff8(%ebp),%eax
0x8048341 <test2+25>: orl $0x11111111,(%eax)
0x8048347 <test2+31>: mov 0xfffffff8(%ebp),%edx
0x804834a <test2+34>: mov %edx,%eax
0x804834c <test2+36>: mov $0xf,%ecx
0x8048351 <test2+41>: mov $0x0,%edx
0x8048356 <test2+46>: div %ecx
0x8048358 <test2+48>: mov %edx,%eax
0x804835a <test2+50>: and 0xfffffffc(%ebp),%eax
0x804835d <test2+53>: test %eax,%eax
0x804835f <test2+55>: je 0x8048374 <test2+76> ## should complain here
# uncomment the "proof2();" and re-run (2.5 minutes @ 1.6GHz)
$ ./jfrtest2
1 0xffffffff 0x91919191 ## so 0xffffffff results in !=0
0 0xffff7f7f 0x91911111 ## so 0xffff7f7f results in ==0
summary of possible bits = 0x706
$ ## 0x706 is bits 1,2,8,9,10
gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
glibc-2.3.2-27.9.6
System is Red Hat 9: 2.4.20-20.9.
--
John Reiser, jreiser@BitWagon.com
|
|
From: Dirk M. <dm...@gm...> - 2003-11-21 04:30:04
|
On Thursday 20 November 2003 22:58, John Reiser wrote:
> Valgrind 2.0.0 (memcheck) does not notice when a conditional jump
> depends on an uninitialized bit.
Oh it does notice. It just suppresses the error due to this commit:
revision 1.10
date: 2002/10/13 00:57:26; author: sewardj; state: Exp; lines: +40 -1
Incorporate horrible hack to workaround problem of emitting bogus
uninit-value errors on code with inlined strlen() et al from gcc-3.1
and above.
A simplified testcase is:
--- Cut
int main()
{
unsigned x;
x &= 0x8080;
if (x & 0x8000)
printf("uninit caught %#x\n", &x);
return 0;
}
---- Cut
Problem is that we suppress the uninit bits testing in basic blocks which
contain the magic literal 0x8080 or 0x80808080.
If you run valgrind with --avoid-strlen-errors=no the error is shown.
Switching the default does not cause a regression test failure (!!). Julian,
do you still have the original snipped that made you add this kludge? Maybe
it was obsoleted by other improvements.
|
|
From: Nicholas N. <nj...@ca...> - 2003-11-21 08:53:47
|
On Fri, 21 Nov 2003, Dirk Mueller wrote: > Problem is that we suppress the uninit bits testing in basic blocks which > contain the magic literal 0x8080 or 0x80808080. > > If you run valgrind with --avoid-strlen-errors=no the error is shown. > > Switching the default does not cause a regression test failure (!!). Julian, > do you still have the original snipped that made you add this kludge? Maybe > it was obsoleted by other improvements. I think this might only show up in code compiled with -O2? I think all the regtests are -O0. N |