Error: stack-use-after-return
Error del sanitizador de direcciones: Uso de la memoria de la pila después del retorno
Esta comprobación requiere la generación del código que se activa por una opción del compilador adicional, /fsanitize-address-use-after-return
y estableciendo la variable de entorno ASAN_OPTIONS=detect_stack_use_after_return=1
.
Esta comprobación puede ralentizar considerablemente la aplicación. Considere el resumen de Clang del algoritmo que admite el uso después de la devolución y los mayores costos de rendimiento.
Importante
Si crea un archivo de objeto mediante la opción del compilador /fsanitize-address-use-after-return
adicional, el código generado por el compilador toma una decisión en tiempo de ejecución sobre cómo asignar un marco de pila. Si la variable de entorno ASAN_OPTIONS
no está establecida en detect_stack_use_after_return
, el código sigue siendo más lento que al usarse /fsanitize=address
por sí mismo. Es más lento porque todavía hay sobrecarga adicional de algunos marcos de pila que asignan espacio para las partes de un marco mediante alloca()
. Es mejor eliminar estos archivos de objeto cuando haya terminado de procesar los errores de uso después de la devolución.
Ejemplo: C simple
// example1.cpp
// stack-use-after-return error
volatile char* x;
void foo() {
char stack_buffer[42];
x = &stack_buffer[13];
}
int main() {
foo();
*x = 42; // Boom!
return (*x == 42);
}
Para compilar y probar este ejemplo, ejecute estos comandos en un símbolo del sistema para desarrolladores de Visual Studio 2019 versión 16.9 o posterior:
cl example1.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example1.exe
Error resultante: C simple
Ejemplo: C++ y plantillas
// 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;
}
Para compilar y probar este ejemplo, ejecute estos comandos en un símbolo del sistema para desarrolladores de Visual Studio 2019 versión 16.9 o posterior:
cl example2.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi /Od
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example2.exe 1
ASAN es una forma de análisis dinámico, lo que significa que solo puede detectar código incorrecto que realmente se ejecuta. Un optimizador puede determinar que el valor de t[100 + Idx]
o sink
nunca se usa y se ha elide de la asignación. Como resultado, este ejemplo requiere la /Od
marca .
Error resultante: C++ y plantillas
Consulte también
Introducción a AddressSanitizer
Problemas conocidos de AddressSanitizer
Referencia de lenguaje y compilación de AddressSanitizer
Referencia del entorno de ejecución addressSanitizer
Bytes de sombra addressSanitizer
Pruebas distribuidas o en la nube addressSanitizer
Integración del depurador AddressSanitizer
Ejemplos de errores addressSanitizer