Using memory sanitizer with libstdc++

◇◆丶佛笑我妖孽 提交于 2019-11-27 02:38:10

问题


I wish to use the -fsanitize=memory flag in clang to analyse a program like the following:

#include <string>
#include <iostream>
#include <fstream>
using namespace std;

void writeToFile(){
    ofstream o;
    o.open("dum");
    o<<"test"<<endl; //The error is here.
                     //It does not matter if the file is opened this way,
                     //or with o("dum");
    o.close();
}
int main(){
    writeToFile();
}

As far as I know, this program is correct, but when I use clang++ san.cpp -fsanitize=memory It fails (at runtime) with:

UMR in __interceptor_write at offset 0 inside [0x64800000e000, +5)  
==9685== WARNING: MemorySanitizer: use-of-uninitialized-value  
    #0 0x7f48d0899ae5 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x7bae5)  
    #1 0x7f48d08d1787 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb3787)  
    #2 0x7f48d08d21e2 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb41e2)  
    #3 0x7f48d08cfd1e (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb1d1e)  
    #4 0x7f48d08b1f2d (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x93f2d)  
    #5 0x7f48d16d60f5 in writeToFile() /home/daniel/programming/test/santest.cpp:10  
    #6 0x7f48d16d61f4 in main /home/daniel/programming/test/santest.cpp:15  
    #7 0x7f48d0261de4 (/lib/x86_64-linux-gnu/libc.so.6+0x21de4)  
    #8 0x7f48d16d5e42 in _start (/home/daniel/programming/test/a.out+0x61e42)  

SUMMARY: MemorySanitizer: use-of-uninitialized-value ??:0 ??

How can I make this work properly?

Clang version 3.5, stdlibc++ version 6


回答1:


The code is fine, of course but many similar errors are cause by the following requirement of clang's memory sanitizer tool:

MemorySanitizer (without a dynamic component) requires that the entire program code including libraries, (except libc/libm/libpthread, to some extent), is instrumented.

from here

The cplusplus runtime you are using libstdc++ is unistrumented and causes errors. You will unfortunately have to follow a somewhat fiddly process as described at that link to rebuild an instrumented libstdc++ or switch to libc++ (easier-ish)




回答2:


There easiest way at this time is to build libc++ with memorysanitizer, then link your program against it.

This is how I did it some time ago, failing to handle libc++ build system: https://code.google.com/p/memory-sanitizer/source/browse/bootstrap/build_libcxx.sh

I heard there've been improvements on the libc++ side, maybe it would be possible to build it as usual (with something like CC=/path/to/clang CFLAGS=-fsanitize=memory).




回答3:


How can I make this work properly?

You can also unpoison the memory that's triggering the finding. But its not clear (to me) which variable that is based on the stack trace shown.

Here's how to unpoison the memory, but the example is for memory used with FD_SET and FD_ZERO. You will still need to find the name of the variable that's causing it (I'm not sure how well specifying an integral memory address works).

#include <sanitizer/msan_interface.h>
...

__msan_unpoison(&readfds, sizeof(readfds));
__msan_unpoison(&writefds, sizeof(writefds));

UMR in __interceptor_write at offset 0 inside [0x64800000e000, +5)  
==9685== WARNING: MemorySanitizer: use-of-uninitialized-value  
    #0 0x7f48d0899ae5 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x7bae5)  
    #1 0x7f48d08d1787 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb3787)  
    #2 0x7f48d08d21e2 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb41e2)  
    #3 0x7f48d08cfd1e (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb1d1e)  
    #4 0x7f48d08b1f2d (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x93f2d)  
    #5 0x7f48d16d60f5 in writeToFile() /home/daniel/programming/test/santest.cpp:10  
    #6 0x7f48d16d61f4 in main /home/daniel/programming/test/santest.cpp:15  
    #7 0x7f48d0261de4 (/lib/x86_64-linux-gnu/libc.so.6+0x21de4)  
    #8 0x7f48d16d5e42 in _start (/home/daniel/programming/test/a.out+0x61e42)  

You may be able to get more information about the offenders by running:

./myprog.exe 2>&1 | /usr/bin/asan_symbolize

For example, here's a program I'm trying to test that has output similar to yours:

$ ./cryptest.exe v 2>&1 | /usr/bin/asan_symbolize
==26988== WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x7f51903b2ca8 in _ZNSt8_Rb_treeISsSt4pairIKSsPvESt10_Select1stIS3_ESt4lessISsESaIS3_EE14_M_lower_boundEPSt13_Rb_tree_nodeIS3_ESC_RS1_ /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_tree.h:1260 (discriminator 1)
    ...

If you are up for some punishment, you can pipe the mangled name through c++filt and get a non-mangled name:

$ echo " _ZNSt8_Rb_treeISsSt4pairIKSsPvESt10_Select1stIS3_ESt4lessISsESaIS3_EE14_M_lower_boundEPSt13_Rb_tree_nodeIS3_ESC_RS1_" | c++filt
std::_Rb_tree<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, void*>, std::_Select1st<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, void*> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, void*> > >::_M_lower_bound(std::_Rb_tree_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, void*> >*, std::_Rb_tree_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, void*> >*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)

Finally, according to the Msan folks, you really need an instrumented build of the C++ Runtime. They also recommend you use LLVM's libc++ for the purpose. See Memory Sanitizer Libcxx HowTo and How to unpoison a C++ std::string? on the Memory Sanitizer mailing list.



来源:https://stackoverflow.com/questions/20617788/using-memory-sanitizer-with-libstdc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!