Utilisation de sanitizer de mémoire avec libstdc ++

Je souhaite utiliser le drapeau -fsanitize=memory dans Clang pour parsingr un programme comme celui-ci:

 #include  #include  #include  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(); } 

Autant que je sache, ce programme est correct, mais lorsque j’utilise clang++ san.cpp -fsanitize=memory il échoue (au moment de l’exécution) avec:

 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 ?? 

Comment puis-je faire ce travail correctement?

Clang version 3.5, stdlibc ++ version 6

Le code est correct, bien sûr, mais de nombreuses erreurs similaires sont dues à l’exigence suivante de l’outil de désinfection de la mémoire de clang:

MemorySanitizer (sans composant dynamic) requirejs que tout le code du programme, y compris les bibliothèques (à l’exception de libc / libm / libpthread, dans une certaine mesure), soit instrumenté.

d’ici

Le runtime cplusplus que vous utilisez, libstdc ++, est unistrumented et provoque des erreurs. Vous devrez malheureusement suivre un processus quelque peu fastidieux, comme décrit sur ce lien, pour reconstruire une libstdc ++ instrumentée ou basculer vers libc ++ (easy-ish)

Le moyen le plus simple à ce stade est de comstackr libc ++ avec memorysanitizer, puis de lier votre programme à celui-ci.

Voici comment je l’ai fait il y a quelque temps, je n’ai pas réussi à gérer le système de construction libc ++: https://code.google.com/p/memory-sanitizer/source/browse/bootstrap/build_libcxx.sh

J’ai entendu dire qu’il y avait eu des améliorations du côté de la libc ++, peut-être qu’il serait possible de le construire comme d’habitude (avec quelque chose comme CC = / chemin / vers / clang CFLAGS = -fsanitize = mémoire).

Comment puis-je faire ce travail correctement?

Vous pouvez également unpoison la mémoire qui déclenche la découverte. Mais ce n’est pas clair (pour moi) quelle variable est basée sur la trace de stack montrée.

Voici comment supprimer la mémoire, mais l’exemple concerne la mémoire utilisée avec FD_SET et FD_ZERO . Vous aurez toujours besoin de trouver le nom de la variable qui l’a provoquée (je ne sais pas si la spécification d’une adresse de mémoire intégrale marche bien).

 #include  ... __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) 

Vous pourrez peut-être obtenir plus d’informations sur les délinquants en exécutant:

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

Par exemple, voici un programme que j’essaie de tester et dont le résultat est similaire au vôtre:

 $ ./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) ... 

Si vous êtes prêt pour une punition, vous pouvez diriger le nom mutilé via c++filt et obtenir un nom non mutilé:

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

Enfin, selon les responsables de Msan, vous avez vraiment besoin d’une construction instrumentée du C ++ Runtime. Ils vous recommandent également d’utiliser la libc++ LLVM à cette fin. Voir Memory Sanitizer Libcxx HowTo et Comment désempoisonner un std :: ssortingng en C ++? sur la liste de diffusion Memory Sanitizer.