staticanalysis / memory-sanitizer

Automatically exported from code.google.com/p/memory-sanitizer
0 stars 0 forks source link

False positives with qsort, std::stringstream, and AVX #54

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Compile libcxx & libcxxabi with msan
2. Compile test program with
clang++ -fsanitize=memory -O2 -fno-omit-frame-pointer -stdlib=libc++ 
-I$LIBCXX/include -L$LIBCXX/lib -Wl,-R$LIBCXX/lib -lc++abi

With a test like:
#include <sstream>
int main() {
    std::stringstream ss;
    ss<<1;
    return 0;
}

Let me know if you need a small test cases for qsort or AVX.

I get 
==13450== WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x7f86eb78ae7b in std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(int) (/home/rschulz/download/gromacs5.0/clang35.msan.sse/a.out+0x9be7b)
    #1 0x7f86eb78a5c1 in main (/home/rschulz/download/gromacs5.0/clang35.msan.sse/a.out+0x9b5c1)

What version of the product are you using? On what operating system?
This is both with 3.4.1 and trunk (http://llvm.org/git/clang.git 
d23fd9aa52efc751322fbf7a3fc125ce58d44e4c) (http://llvm.org/git/llvm.git 
fd76d8a72dac035a4e1963bc6fe635a3b688cfcd). libcxx/libcxxabi are also trunk 
(208925). This is without dynamic instrumentation on Linux.

Original issue reported on code.google.com by rol...@rschulz.eu on 15 May 2014 at 10:29

GoogleCodeExporter commented 9 years ago
stringstream is fine when using libstc++ instead of libc++.

Original comment by rol...@rschulz.eu on 16 May 2014 at 2:08

GoogleCodeExporter commented 9 years ago
More tests will never hurt! 
Also, did you try with -O1? I remember we had at least one problem with -O2... 

Original comment by konstant...@gmail.com on 16 May 2014 at 4:31

GoogleCodeExporter commented 9 years ago
Test case for qsort

#include <stdlib.h>
#include <stdio.h>

struct s {
    int a;
    int b;
};

int cmp(const void *a, const void* b)
{
    return *(const int*)a>*(const int*)b;
}

int main() {
    //struct s *d = malloc(sizeof(struct s)*3);                                                                                                                                                                                                                                
    struct s d[3];
    d[0].a=1;
    d[1].a=3;
    d[2].a=2;
    d[1].b=10; //if d[2] it assigned instead, it should warn but then it doesn't
    qsort(d, 3, sizeof(struct s), cmp);
    if (d[2].b>5)
        printf("%d %d\n", d[2].a, d[2].b);
}

Original comment by rol...@rschulz.eu on 16 May 2014 at 5:55

GoogleCodeExporter commented 9 years ago
Test case for AVX (needs to be compiled with -mavx):

#include <immintrin.h>
#include <stdio.h>
int main() {
    float f[8];
    f[0]=1;
    _mm256_storeu_ps(f, _mm256_broadcast_ss(f));
    if (f[5]<2)
        printf("%f\n", f[0]);
    return 0;
}

All 3 test-cases also report false positive with -O1.

While creating these test cases I noticed it doesn't report an error if a 
uninitialized value is passed to printf. Test case for that (should report 
initialized value but does not):

#include <stdio.h>
int main() {
    int i;
    printf("%d\n", i);
}

Original comment by rol...@rschulz.eu on 16 May 2014 at 6:32

GoogleCodeExporter commented 9 years ago
Another issue I just encountered: Is msan suppose to work for assembler files? 
If I call cpuid from inline-asm it seems OK. But if I have a function written 
in a assembler file calling cpuid (used in the Intel/LLVM OpenMP runtime), then 
it gives what seems to be a false positive.

Test case:
#include <stdint.h>
#include <stdio.h>

extern void __kmp_x86_cpuid( int mode, int mode2, void *cpuid_buffer ) 
__asm__("__kmp_x86_cpuid");
struct kmp_cpuid {
    uint32_t  eax;
    uint32_t  ebx;
    uint32_t  ecx;
    uint32_t  edx;
};

int main() {
    struct kmp_cpuid buf;
    __kmp_x86_cpuid(0, 0, &buf);
    if (buf.eax>1)
        printf("%u %u %u %u", buf.eax, buf.ebx, buf.ecx, buf.edx);
    return 0;
}

Plus: http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/z_Linux_asm.s

Compiled as:
clang cpuid.c -x assembler-with-cpp z_Linux_asm.s -Wall -DKMP_ARCH_X86_64 
-fsanitize=memory -O1 -fno-omit-frame-pointer -fsanitize-memory-track-origins

Original comment by rol...@rschulz.eu on 16 May 2014 at 6:54

GoogleCodeExporter commented 9 years ago
MSan support for inline assembly is limited to asm constraints. We are working 
on full support for both inline assembly and .s sources for all sanitizers, see 
https://code.google.com/p/address-sanitizer/issues/list?can=2&q=assembly+instrum
entation

Original comment by euge...@google.com on 19 May 2014 at 7:47

GoogleCodeExporter commented 9 years ago
The AVX issue is fixed in 3.5.0 and the sstream issue is fixed in latest 
version of libc++. But the qsort issue is still present in 3.6.0rc1.

Original comment by rol...@rschulz.eu on 27 Jan 2015 at 12:49

GoogleCodeExporter commented 9 years ago
printf issue is also not fixed.

qsort issue is not trivial:
 * array shadow must be reordered to match the order of the array elements after sort
 * ideally, this has to be done on-the-fly, i.e. comparison predicate (which can be instrumented) must observe matching shadow

We could require that the entire array is initialized before qsort(), but that 
would probably break your use case. We could unpoison the entire array before 
qsort() but that feels sloppy and would hide bugs.

Other than that, we could only re-implement qsort in the sanitizer runtime 
library.

Original comment by euge...@google.com on 27 Jan 2015 at 12:14