Bug 326955

Summary: false positive : move depends on uninitialised value wcscpy
Product: [Developer tools] valgrind Reporter: David Dyck <david.dyck>
Component: memcheckAssignee: Julian Seward <jseward>
Status: RESOLVED DUPLICATE    
Severity: normal CC: david.dyck, philippe.waroquiers
Priority: NOR    
Version: 3.7.0   
Target Milestone: ---   
Platform: openSUSE   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: sample C program that demonstrates false positives
output from: g++ -m32 -Wall -O0 -g valgrind_bug_wcscpy.c && valgrind -v --track-origins=yes ./a.out

Description David Dyck 2013-10-31 17:28:52 UTC
Created attachment 83253 [details]
sample C program that demonstrates false positives

I've attached the sample program valgrind_bug_wcscpy.c
that shows false positives that get in the way of finding
real errors in our code.

The bug does not show up if compiled as a 32 bit program on linux,
or if I use memset() to pre-initialize the buffer.

The bug does not show up if the same program uses the <string.h> functions
 strcpy and strlen which is my main argument as to why this is a false positive.

---------------------
/*
  The following program causes valgrind to report an error ( false positive )
  Compile:
        gcc -m64 -Wall -O0 -g valgrind_bug_wcscpy.c
  Execute:
        valgrind --track-origins=yes ./a.out

  Unexpected and undesirable results (false positive):

==15062== Conditional jump or move depends on uninitialised value(s)
==15062==    at 0x4F75F05: __wcscpy_ssse3 (in /lib64/libc-2.15.so)
==15062==    by 0x4005B7: main (valgrind_bug.c:31)
==15062==  Uninitialised value was created by a stack allocation
==15062==    at 0x40058C: main (valgrind_bug.c:23)

*/

// #include <stdio.h>
#include <wchar.h>
#include <string.h>

int main()
{
        wchar_t stackbuf1[10];                     // if we init on allocation ( = { 0 }) no error

//        memset(stackbuf1, 0, sizeof(stackbuf1)); // if we pre-initialize the buffer, no error

        wcscpy(stackbuf1,L"hello");     // initialize (part of) stackbuf1

        wchar_t stackbuf2[10];
        wcscpy(stackbuf2, stackbuf1);   // valgrind reports stackbuf1 unitialized

        return wcslen(stackbuf2);
}
Comment 1 David Dyck 2013-10-31 22:21:37 UTC
removed the "64 bit" portion of the comment

The false positive returns when compiling with g++ instead of gcc

e.g. both
g++ -m32 -Wall -O0 -g valgrind_bug_wcscpy.c && valgrind --track-origins=yes ./a.out
 and
g++ -m64 -Wall -O0 -g valgrind_bug_wcscpy.c && valgrind --track-origins=yes ./a.out

yield errors like:
==15026== Conditional jump or move depends on uninitialised value(s)
==15026==    at 0x5789F05: __wcscpy_ssse3 (in /lib64/libc-2.15.so)
==15026==    by 0x400687: main (valgrind_bug_wcscpy.c:31)
==15026==  Uninitialised value was created by a stack allocation
==15026==    at 0x40065C: main (valgrind_bug_wcscpy.c:23)


gcc (SUSE Linux) 4.7.1 20120723 [gcc-4_7-branch revision 189773]
> ldd a.out
        linux-vdso.so.1 (0x00007fff10bff000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fd84dcda000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fd84e07f000)


g++ (SUSE Linux) 4.7.1 20120723 [gcc-4_7-branch revision 189773]
> ldd a.out
        linux-vdso.so.1 (0x00007ffff9790000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fb62ab54000)
        libm.so.6 => /lib64/libm.so.6 (0x00007fb62a85d000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fb62a647000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fb62a2a2000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fb62ae5b000)
Comment 2 David Dyck 2013-10-31 22:24:07 UTC
Created attachment 83258 [details]
output from: g++ -m32 -Wall -O0 -g valgrind_bug_wcscpy.c && valgrind -v --track-origins=yes ./a.out
Comment 3 David Dyck 2013-10-31 23:00:02 UTC
Interesting that the only difference between getting false positives or not is the
compiler

# no false positive
gcc -m32 -Wall -O0 -c  valgrind_bug_wcscpy.c && g++ -m32 valgrind_bug_wcscpy.o && valgrind -v --track-origins=yes ./a.out

# false positives
 g++ -m32 -Wall -O0 -c  valgrind_bug_wcscpy.c && g++ -m32 valgrind_bug_wcscpy.o && valgrind -v --track-origins=yes ./a.out

Maybe this is a red-herring - and more optimizations are happening in one of the compilers.

> diff -u valgrind_bug_wcscpy.s*
--- valgrind_bug_wcscpy.s.g++   2013-10-31 15:52:25.330401000 -0700
+++ valgrind_bug_wcscpy.s.gcc   2013-10-31 15:52:38.120528000 -0700
@@ -35,15 +35,15 @@
        andl    $-16, %esp
        subl    $96, %esp
        movl    $.LC0, 4(%esp)
-       leal    16(%esp), %eax
+       leal    56(%esp), %eax
        movl    %eax, (%esp)
        call    wcscpy
-       leal    16(%esp), %eax
-       movl    %eax, 4(%esp)
        leal    56(%esp), %eax
+       movl    %eax, 4(%esp)
+       leal    16(%esp), %eax
        movl    %eax, (%esp)
        call    wcscpy
-       leal    56(%esp), %eax
+       leal    16(%esp), %eax
        movl    %eax, (%esp)
        call    wcslen
        leave
Comment 4 David Dyck 2013-10-31 23:36:53 UTC
Also occurs with valgrind 3.8.1

> valgrind --version
valgrind-3.8.1

> g++ -Wall -O0 -g valgrind_bug_wcscpy.c && valgrind --track-origins=yes ./a.out
==9859== Memcheck, a memory error detector
==9859== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==9859== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==9859== Command: ./a.out
==9859==
==9859== Conditional jump or move depends on uninitialised value(s)
==9859==    at 0x42DC491: __wcscpy_ssse3 (in /lib/libc-2.15.so)
==9859==    by 0x41AF3D4: (below main) (in /lib/libc-2.15.so)
==9859==  Uninitialised value was created by a stack allocation
==9859==    at 0x8048522: main (valgrind_bug_wcscpy.c:23)
==9859==
==9859== Conditional jump or move depends on uninitialised value(s)
==9859==    at 0x42DC9E7: __wcscpy_ssse3 (in /lib/libc-2.15.so)
==9859==    by 0x41AF3D4: (below main) (in /lib/libc-2.15.so)
==9859==  Uninitialised value was created by a stack allocation
==9859==    at 0x8048522: main (valgrind_bug_wcscpy.c:23)
==9859==
==9859== Conditional jump or move depends on uninitialised value(s)
==9859==    at 0x42DC9EB: __wcscpy_ssse3 (in /lib/libc-2.15.so)
==9859==    by 0x41AF3D4: (below main) (in /lib/libc-2.15.so)
==9859==  Uninitialised value was created by a stack allocation
==9859==    at 0x8048522: main (valgrind_bug_wcscpy.c:23)
==9859==
==9859==
==9859== HEAP SUMMARY:
==9859==     in use at exit: 0 bytes in 0 blocks
==9859==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==9859==
==9859== All heap blocks were freed -- no leaks are possible
==9859==
==9859== For counts of detected and suppressed errors, rerun with: -v
==9859== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
Comment 5 David Dyck 2013-11-01 19:57:18 UTC
I will continue to investigate, but this test case does not seem to be reproducible with 3.9.0

> valgrind --version
valgrind-3.9.0

> valgrind --track-origins=yes ./a.out
==30515== Memcheck, a memory error detector
==30515== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==30515== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==30515== Command: ./a.out
==30515==
==30515==
==30515== HEAP SUMMARY:
==30515==     in use at exit: 0 bytes in 0 blocks
==30515==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==30515==
==30515== All heap blocks were freed -- no leaks are possible
==30515==
==30515== For counts of detected and suppressed errors, rerun with: -v
==30515== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Comment 6 Philippe Waroquiers 2013-11-02 16:44:15 UTC
(In reply to comment #5)
> I will continue to investigate, but this test case does not seem to be
> reproducible with 3.9.0
Thanks for verifying with 3.9.0.
I think this is a duplicate of 307828, which is fixed in 3.9.0 , so closing it.
Please re-open if needed.

*** This bug has been marked as a duplicate of bug 307828 ***