5

(original post was here)

Consider the following clearly buggy program:

#include <string.h>

int main()
{
  char string1[10] = "123456789";
  char *string2 = "123456789";

  strcat(string1, string2);
}

and suppose to compile it:

gcc program.c -ggdb

and run valgrind on it:

valgrind --track-origins=yes --leak-check=yes --tool=memcheck --read-var-info=yes  ./a.out

In the result, no error is shown:

==29739== Memcheck, a memory error detector
==29739== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==29739== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==29739== Command: ./a.out
==29739== 
==29739== 
==29739== HEAP SUMMARY:
==29739==     in use at exit: 0 bytes in 0 blocks
==29739==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==29739== 
==29739== All heap blocks were freed -- no leaks are possible
==29739== 
==29739== For counts of detected and suppressed errors, rerun with: -v
==29739== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

What am I missing?

Community
  • 1
  • 1

1 Answers1

6

It did not report anything wrong because you were using memcheck, which does not perform check on global or stack arrays, it only perform bounds checks and use-after-free checks for heap arrays. So in this case, you can use valgrind SGCheck to check stack arrays:

valgrind --tool=exp-sgcheck ./a.out

It indeed report the error for me.

For more information, refer the sgcheck docs:

http://valgrind.org/docs/manual/sg-manual.html

adding the log:

$ valgrind --tool=exp-sgcheck ./a.out
==10485== exp-sgcheck, a stack and global array overrun detector
==10485== NOTE: This is an Experimental-Class Valgrind Tool
==10485== Copyright (C) 2003-2015, and GNU GPL'd, by OpenWorks Ltd et al.
==10485== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==10485== Command: ./a.out
==10485==
==10485== Invalid read of size 1
==10485==    at 0x4C2A374: strlen (h_intercepts.c:131)
==10485==    by 0x4E9DD5B: puts (in /usr/lib64/libc-2.22.so)
==10485==    by 0x4005C8: main (v.c:11)
==10485==  Address 0xfff00042a expected vs actual:
==10485==  Expected: stack array "string1" of size 10 in frame 2 back from here
==10485==  Actual:   unknown
==10485==  Actual:   is 0 after Expected
==10485==
==10485== Invalid read of size 1
==10485==    at 0x4EA9BA2: _IO_default_xsputn (in /usr/lib64/libc-2.22.so)
==10485==    by 0x4EA7816: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.22.so)
==10485==    by 0x4E9DDF7: puts (in /usr/lib64/libc-2.22.so)
==10485==    by 0x4005C8: main (v.c:11)
==10485==  Address 0xfff00042a expected vs actual:
==10485==  Expected: stack array "string1" of size 10 in frame 3 back from here
==10485==  Actual:   unknown
==10485==  Actual:   is 0 after Expected
==10485==
123456789123456789
==10485==
==10485== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
fluter
  • 13,238
  • 8
  • 62
  • 100
  • which error do you get? I tried and obtained none: `ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)`. Perhaps, it is a consequence of this sentence in the doc link you posted: _Hence, the first access by an instruction to an array (in any given function instantiation) is not checked for overrun, since SGCheck uses that as the "example" of how subsequent accesses should behave._ – VeryHardCoder May 03 '16 at 08:31
  • 1
    @VeryHardCoder yes, but you will use the `string1` somehow in a real program. – fluter May 03 '16 at 08:35
  • Ok, I see, so this is the best valgrind can do... thanks! – VeryHardCoder May 03 '16 at 08:39