On 09/07/2016 04:52 AM, Mark Wielaard wrote:
If valgrind believes the memory isn't in valid memory then it will complain about an invalid access. But if the memory is accessible but uninitialised then it will just track the undefinedness complain later if such a value is used.
I think the former is what happened in Gnulib fts.c before Gnulib was fixed.
valgrind also has --partial-loads-ok (which in newer versions defaults to =yes): Controls how Memcheck handles 32-, 64-, 128- and 256-bit naturally aligned loads from addresses for which some bytes are addressable and others are not.
Although this helps in some cases, it does not suffice in general since the problem can occur with 16-bit aligned loads. I think that is what happened with fts.c.
Does anybody have an example program of the above issue compiled with gcc that produces false positives with valgrind?
Sure, attached. On Fedora 24 x86-64 (GCC 6.1.1 20160621, valgrind 3.11.0), when I compile with "gcc -O2 flexouch.c" and run with "valgrind ./a.out", valgrind complains "Invalid read of size 2". This is because GCC compiles "p->d[0] == 2 && p->d[1] == 3" into "cmpw $770, 8(%rax); sete %al", which loads the uninitialized byte p->d[1] simultaneously with the initialized byte p->d[0].
As mentioned previously, although flexouch.c does not conform to C11, this is arguably a defect in C11.
#include <stddef.h> #include <stdlib.h> struct s { struct s *next; char d[]; }; int main (void) { struct s *p = malloc (offsetof (struct s, d) + 1); p->d[0] = 1; return p->d[0] == 2 && p->d[1] == 3; }