Fehler: stack-use-after-return
Adress-Sanitizer-Fehler: Verwendung des Stapelspeichers nach der Rückgabe
Diese Überprüfung erfordert die Codegenerierung, die von einer zusätzlichen Compileroption aktiviert wird, /fsanitize-address-use-after-return
und indem Sie die Umgebungsvariable ASAN_OPTIONS=detect_stack_use_after_return=1
festlegen.
Diese Überprüfung kann Ihre Anwendung erheblich verlangsamen. Betrachten Sie die Clang-Zusammenfassung des Algorithmus, der die Verwendung nach der Rückgabe unterstützt, und die größeren Leistungskosten.
Wichtig
Wenn Sie eine Objektdatei mithilfe der zusätzlichen Compileroption /fsanitize-address-use-after-return
erstellen, trifft der vom Compiler generierte Code eine Laufzeitentscheidung darüber, wie ein Stapelframe zugewiesen werden soll. Wenn die Umgebungsvariable ASAN_OPTIONS
nicht festgelegt detect_stack_use_after_return
ist, ist der Code immer noch langsamer als die Verwendung /fsanitize=address
selbst. Es ist langsamer, da es noch zusätzlichen Aufwand von einigen Stapelframes gibt, die Platz für Teile eines Frames mithilfe von .alloca()
Es ist am besten, diese Objektdateien zu löschen, wenn Sie die Verarbeitung von Use-after-Return-Fehlern abgeschlossen haben.
Beispiel – Einfaches C
// example1.cpp
// stack-use-after-return error
char* x;
void foo() {
char stack_buffer[42];
x = &stack_buffer[13];
}
int main() {
foo();
*x = 42; // Boom!
return 0;
}
Um dieses Beispiel zu erstellen und zu testen, führen Sie diese Befehle in einer Visual Studio 2019, Version 16.9 oder einer späteren Entwickler-Eingabeaufforderung, aus:
cl example1.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example1.exe
Resultierender Fehler – Einfaches C
Beispiel : C++ und Vorlagen
// example2.cpp
// stack-use-after-return error
#include <stdlib.h>
enum ReadOrWrite { Read = 0, Write = 1 };
struct S32 {
char x[32];
};
template<class T>
T* LeakStack() {
T t[100];
static volatile T* x;
x = &t[0];
return (T*)x;
}
template<class T>
void StackUseAfterReturn(int Idx, ReadOrWrite w) {
static T sink;
T* t = LeakStack<T>();
if (w)
t[100 + Idx] = T();
else
sink = t[100 + Idx];
}
int main(int argc, char* argv[]) {
if (argc != 2) return 1;
int kind = atoi(argv[1]);
switch (kind) {
case 1: StackUseAfterReturn<char>(0, Read); break;
case 2: StackUseAfterReturn<S32>(0, Write); break;
}
return 0;
}
Um dieses Beispiel zu erstellen und zu testen, führen Sie diese Befehle in einer Visual Studio 2019, Version 16.9 oder einer späteren Entwickler-Eingabeaufforderung, aus:
cl example2.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example2.exe 1
Resultierender Fehler – C++ und Vorlagen
Siehe auch
Übersicht über AddressSanitizer
Bekannte Probleme von AddressSanitizer
Kompilierungs- und Sprachreferenz für AddressSanitizer
Runtimereferenz für AddressSanitizer
AddressSanitizer-Schattenbytes
AddressSanitizer-Tests in der Cloud oder verteilten Umgebungen
Integration des AddressSanitizer-Debuggers
AddressSanitizer-Fehlerbeispiele