Runtime AddressSanitizer
La biblioteca de runtime AddressSanitizer intercepta las funciones y las operaciones comunes de asignación de memoria para habilitar la inspección de los accesos a la memoria. Hay varias bibliotecas de runtime diferentes que admiten los distintos tipos de ejecutables que el compilador puede generar. El compilador y el enlazador vinculan automáticamente las bibliotecas runtime adecuadas, siempre y cuando pase la opción /fsanitize=address
en el tiempo de compilación. Se puede invalidar este comportamiento predeterminado mediante la opción /NODEFAULTLIB
en tiempo de vínculo. Para obtener más información, consulte la sección sobre la vinculación en la referencia sobre lenguaje, compilación y depuración de AddressSanitizer.
Al compilar con cl /fsanitize=address
, el compilador genera instrucciones para administrar y comprobar bytes de sombra. El programa usa esta instrumentación para comprobar los accesos a la memoria en la pila, en el montón o en el ámbito global. El compilador también genera metadatos que describen variables globales y de pila. Estos metadatos permiten que el runtime genere diagnósticos de errores precisos: nombres de función, líneas y columnas en el código fuente. En combinación, las comprobaciones del compilador y las bibliotecas del runtime pueden diagnosticar con precisión muchos tipos de errores de seguridad de memoria si se encuentran en el runtime.
A continuación se muestra la lista de bibliotecas en tiempo de ejecución para vincular al entorno de ejecución addressSanitizer, a partir de Visual Studio 17.7 Preview 3. Para obtener más información sobre las /MT
opciones (vincular estáticamente el tiempo de ejecución) y /MD
(vincular dinámicamente el redist at runtime), vea /MD, /MT, /LD (Usar biblioteca en tiempo de ejecución).
Nota:
En la tabla siguiente, {arch}
es i386
o x86_64
.
Estas bibliotecas usan convenciones de Clang para los nombres de arquitectura. Las convenciones de MSVC son normalmente x86
y x64
en lugar i386
de y x86_64
, pero hacen referencia a las mismas arquitecturas.
Opción de CRT | Biblioteca en tiempo de ejecución addressSanitizer (.lib) | Binario de tiempo de ejecución de direcciones (.dll) |
---|---|---|
/MT o /MTd |
clang_rt.asan_dynamic-{arch} , clang_rt.asan_static_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
/MD o /MDd |
clang_rt.asan_dynamic-{arch} , clang_rt.asan_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
En el diagrama siguiente se muestra cómo se vinculan las bibliotecas de Language Runtime para las /MT
opciones del compilador , /MTd
, /MD
y /MDd
:
La imagen muestra tres escenarios para vincular la biblioteca en tiempo de ejecución. La primera es /MT o /MTd. My_exe.exe y my_dll.dll se muestran con sus propias copias de los entornos de ejecución vcRuntime, Universal CRT y C++ vinculados estáticamente. Los escenarios muestran /MD en los que my_exe.exe y my_dll.dll comparten vcruntime140.dll, ucrtbase.dll y msvcp140.dll. El último escenario muestra /MDd en el que tanto my_exe.exe como my_dll.dll comparten las versiones de depuración de los entornos de ejecución: vcruntime140d.dll, ucrtbased.dll y msvcp140d.dll
En el diagrama siguiente se muestra cómo está vinculada la biblioteca de ASan para varias opciones del compilador:
La imagen muestra cuatro escenarios para vincular la biblioteca en tiempo de ejecución de ASan. Los escenarios son para /MT (vincular estáticamente el tiempo de ejecución), /MTd (vincular estáticamente el tiempo de ejecución de depuración), /MD (vincular dinámicamente el redist en tiempo de ejecución), /MDd (vincular dinámicamente el redist de depuración en tiempo de ejecución). En todos los casos, my_exe.exe vínculos y sus asociados my_dll.dll vínculo a una sola instancia de clang-rt.asan-dynamix-x86_64.dll.
Incluso cuando se vincula estáticamente, el archivo DLL del entorno de ejecución de ASan debe estar presente en tiempo de ejecución, a diferencia de otros componentes de C Runtime.
Versiones anteriores
Antes de Visual Studio 17.7 Preview 3, las compilaciones vinculadas estáticamente (/MT
o /MTd
) no usaron una dependencia dll. En su lugar, el tiempo de ejecución addressSanitizer se vinculó estáticamente al EXE del usuario. A continuación, los proyectos DLL cargarían exportaciones desde el EXE del usuario para acceder a la funcionalidad de ASan.
Los proyectos vinculados dinámicamente (/MD
o /MDd
) usaron bibliotecas y archivos DLL diferentes en función de si el proyecto se configuró para depurar o liberar. Para obtener más información sobre estos cambios y sus motivaciones, consulte MSVC Address Sanitizer : un archivo DLL para todas las configuraciones en tiempo de ejecución.
En la tabla siguiente se describe el comportamiento anterior de la vinculación de la biblioteca en tiempo de ejecución AddressSanitizer antes de Visual Studio 17.7 Preview 3:
Opción de CRT | DLL o EXE | DEBUG? | Biblioteca ASan (.lib ) |
Binario en tiempo de ejecución de ASan (.dll ) |
---|---|---|---|---|
/MT |
EXE | No | clang_rt.asan-{arch} , clang_rt.asan_cxx-{arch} |
None |
/MT |
Archivo DLL | No | clang_rt.asan_dll_thunk-{arch} |
Ninguno |
/MD |
O bien | No | clang_rt.asan_dynamic-{arch} , clang_rt.asan_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
/MT |
EXE | Sí | clang_rt.asan_dbg-{arch} , clang_rt.asan_dbg_cxx-{arch} |
None |
/MT |
Archivo DLL | Sí | clang_rt.asan_dbg_dll_thunk-{arch} |
None |
/MD |
Es posible usar el | Sí | clang_rt.asan_dbg_dynamic-{arch} , clang_rt.asan_dbg_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dbg_dynamic-{arch} |
En el diagrama siguiente se muestra cómo se vinculó la biblioteca de ASan para varias opciones del compilador antes de Visual Studio 2022 17.7 Preview 3:
La imagen muestra cuatro escenarios para vincular la biblioteca en tiempo de ejecución de ASan. Los escenarios son para /MT (vincular estáticamente el tiempo de ejecución), /MTd (vincular estáticamente el tiempo de ejecución de depuración), /MD (vincular dinámicamente el redist en tiempo de ejecución), /MDd (vincular dinámicamente el redist de depuración en tiempo de ejecución). Para /MT, my_exe.exe tiene una copia vinculada estáticamente del entorno de ejecución de ASan. my_dll.dll vínculos al entorno de ejecución de ASan en my_exe.exe. Para /MTd, el diagrama es el mismo, excepto que usa el entorno de ejecución de ASan vinculado estáticamente. Para /MD, tanto my_exe.exe como my_dll.dll vínculo al entorno de ejecución de ASan vinculado dinámicamente denominado clang_rt.asan_dynamic-x86_64.dll. Para /MDd, el diagrama es el mismo, excepto my_exe.exe y my_dll.dll vínculo al entorno de ejecución de ASan de depuración denominado clang_rt.asan_dbg_dynamic-x86_64.dll.
Interceptación de funciones
AddressSanitizer logra la interceptación de funciones a través de muchas técnicas de almacenamiento en caliente. Estas técnicas se documentan mejor dentro del propio código fuente.
Las bibliotecas de runtime interceptan muchas funciones comunes de administración de memoria y manipulación de memoria. Para obtener una lista, consulte Lista de funciones interceptadas de AddressSanitizer. Los interceptores de asignación administran metadatos y bytes paralelos relacionados con cada llamada de asignación. Cada vez que se llama a una función de CRT, como malloc
o delete
, los interceptores establecen valores específicos en la región de memoria paralela de AddressSanitizer para indicar si esas ubicaciones del montón están actualmente accesibles y cuáles son los límites de la asignación. Estos bytes paralelos permiten que las comprobaciones generadas por el compilador de los bytes paralelos determinen si una carga o almacén es válida.
No se garantiza que la interceptación se realice correctamente. Si un prólogo de función es demasiado corto para que se escriba un jmp
, se puede producir un error en la intercepción. Si se produce un error de interceptación, el programa arroja un debugbreak
y se detiene. Si adjunta un depurador, este permite que la causa de la incidencia de interceptación sea clara. Si tiene este problema, informe que hay un error.
Nota:
Opcionalmente, los usuarios pueden intentar continuar después de una interceptación errónea estableciendo la variable de entorno ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE
en cualquier valor. Continuar después de un error de interceptación puede dar lugar a informes de errores perdidos para esa función.
Asignadores personalizados y runtime de AddressSanitizer
El runtime de AddressSanitizer proporciona interceptores para interfaces comunes de asignador, malloc
/free
, new
/delete
,HeapAlloc
/HeapFree
(a través de RtlAllocateHeap
/RtlFreeHeap
). Muchos programas usan asignadores personalizados por un motivo u otro; un ejemplo sería cualquier programa que use dlmalloc
o una solución mediante la interfaz de std::allocator
y VirtualAlloc()
. El compilador no puede agregar automáticamente llamadas de administración de memoria paralela a un asignador personalizado. Es responsabilidad del usuario usar la interfaz contra "poisoning" manual proporcionada. Esta API permite que estos asignadores funcionen correctamente con las convenciones existentes de runtime de AddressSanitizer y bytes paralelos.
Interfaz manual contra "poisoning" de AddressSanitizer
La interfaz para la optimización es sencilla, pero impone restricciones de alineación al usuario. Los usuarios pueden importar estos prototipos al importar sanitizer/asan_interface.h
. Estos son los prototipos de función de interfaz:
void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
Para mayor comodidad, el archivo de encabezado de interfaz de AddressSanitizer proporciona macros contenedoras. Estas macros comprueban si la funcionalidad AddressSanitizer está habilitada durante la compilación. Permiten que el código fuente omita las llamadas de la función de "poisoning" cuando no sean necesarias. Estas macros se deben preferir en vez de llamar directamente a las funciones anteriores:
#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)
Requisitos de alineación para "poisoning" de AddressSanitizer
Cualquier "poisoning" manual de bytes paralelos debe tener en cuenta los requisitos de alineación. El usuario debe agregar relleno si es necesario para que los bytes paralelos finalicen en un límite de bytes en la memoria paralela. Cada bit de la memoria paralela de AddressSanitizer codifica el estado de un solo byte en la memoria de la aplicación. Esta codificación significa que el tamaño total de cada asignación, incluido cualquier relleno, debe alinearse con un límite de 8 bytes. Si no se cumple el requisito de alineación, puede provocar informes de errores incorrectos. Los informes incorrectos podrían manifestarse como informes que faltan (falsos negativos) o informes sobre falsos errores (falsos positivos).
Para obtener una ilustración del requisito de alineación y los posibles problemas, consulte los ejemplos de alineación de ASan proporcionados. Uno es un pequeño programa para mostrar lo que puede salir mal con el "poisoning" manual de la memoria paralela. El segundo es una implementación de ejemplo de "poisoning" manual mediante la interfaz de std::allocator
.
Opciones de runtime
Microsoft C/C++ (MSVC) usa un runtime basado en el runtime de Clang AddressSanitizer desde el repositorio llvm-project. Por este motivo, la mayoría de las opciones de runtime se comparten entre las dos versiones. Aquí encontrará una lista completa de las opciones públicas del runtime de Clang. Documentamos algunas diferencias en las secciones siguientes. Si detecta opciones que no funcionan según lo previsto, informe sobre un error.
Opciones de AddressSanitizer no admitidas
- detect_container_overflow
- unmap_shadow_on_exit
Nota:
La opción de runtime halt_on_error
de AddressSanitizer no funciona de la manera esperada. En las bibliotecas de runtime de Clang y de MSVC, muchos tipos de error se consideran no continuables, incluidos la mayoría de los errores de daños en la memoria.
Para obtener más información, consulte la sección Diferencias con Clang 12.0.
Opciones de runtime de AddressSanitizer específicas de MSVC
windows_hook_legacy_allocators
Boolean, establecido enfalse
para deshabilitar la interceptación deGlobalAlloc
los asignadores yLocalAlloc
.Nota:
La opción
windows_hook_legacy_allocators
no estaba disponible en el runtime público de llvm-project cuando se escribió este artículo. La opción puede contribuir finalmente al proyecto público; sin embargo, depende de la revisión de código y la aceptación de la comunidad.La opción
windows_hook_rtl_allocators
, anteriormente una característica de participación opcional mientras AddressSanitizer era experimental, ahora está habilitada de forma predeterminada. En versiones anteriores a la versión 17.4.6 de Visual Studio 2022, el valor de opción predeterminado esfalse
. En Visual Studio 2022, versión 17.4.6 y versiones posteriores, la opciónwindows_hook_rtl_allocators
tienetrue
como valor predeterminado .iat_overwrite
Cadena, establecida en"error"
de forma predeterminada. Otros valores posibles son"protect"
y"ignore"
. Algunos módulos pueden sobrescribir losimport address table
de otros módulos para personalizar las implementaciones de determinadas funciones. Por ejemplo, los controladores suelen proporcionar implementaciones personalizadas para hardware específico. Laiat_overwrite
opción administra la protección del entorno de ejecución addressSanitizer frente a sobrescrituras para funciones específicasmemoryapi.h
. Actualmente, el tiempo de ejecución realiza un seguimiento de lasVirtualAlloc
funciones ,VirtualProtect
yVirtualQuery
para la protección. Esta opción está disponible en Visual Studio 2022, versión 17.5, versión preliminar 1 y versiones posteriores. Los valores siguientesiat_overwrite
controlan cómo reacciona el tiempo de ejecución cuando se sobrescriben las funciones protegidas:- Si se establece en
"error"
(valor predeterminado), el tiempo de ejecución notifica un error cada vez que se detecta una sobrescritura. - Si se establece en
"protect"
, el tiempo de ejecución intenta evitar el uso de la definición sobrescrita y continúa. De hecho, la definición originalmemoryapi
de la función se usa desde dentro del tiempo de ejecución para evitar la recursividad infinita. Otros módulos del proceso siguen usando la definición sobrescrita. - Si se establece en
"ignore"
, el tiempo de ejecución no intenta corregir ninguna función sobrescrita y continúa con la ejecución.
- Si se establece en
windows_fast_fail_on_error
Boolean (false de forma predeterminada), se establece entrue
para permitir que el proceso finalice con un __fastfail(71) después de imprimir el informe de errores.
Nota:
Cuando abort_on_error valor se establece en true, en Windows el programa finaliza con una salida(3). Para no cambiar el comportamiento actual, decidimos introducir esta nueva opción en su lugar. Si tanto abort_on_error como windows_fast_fail_on_error son true, el programa se cerrará con el __fastfail.
Lista de funciones interceptadas de AddressSanitizer (Windows)
El tiempo de ejecución addressSanitizer admite muchas funciones para habilitar las comprobaciones de seguridad de memoria en tiempo de ejecución. Esta es una lista no exhaustiva de las funciones que supervisa el runtime de AddressSanitizer.
Interceptores predeterminados
__C_specific_handler
(solo x64)_aligned_free
_aligned_malloc
_aligned_msize
_aligned_realloc
_calloc_base
_calloc_crt
_calloc_dbg
(solo runtime de depuración)_except_handler3
(solo x86)_except_handler4
(solo x86) (sin documentar)_expand
_expand_base
(undocumented)_expand_dbg
(solo runtime de depuración)_free_base
(undocumented)_free_dbg
(solo runtime de depuración)_malloc_base
(undocumented)_malloc_crt
(undocumented)_malloc_dbg
(solo runtime de depuración)_msize
_msize_base
(undocumented)_msize_dbg
(solo runtime de depuración)_realloc_base
(undocumented)_realloc_crt
(undocumented)_realloc_dbg
(solo runtime de depuración)_recalloc
_recalloc_base
(undocumented)_recalloc_crt
(undocumented)_recalloc_dbg
(solo runtime de depuración)_strdup
atoi
atol
calloc
CreateThread
free
frexp
longjmp
malloc
memchr
memcmp
memcpy
memmove
memset
RaiseException
realloc
RtlAllocateHeap
RtlCreateHeap
RtlDestroyHeap
RtlFreeHeap
RtlRaiseException
RtlReAllocateHeap
(undocumented)RtlSizeHeap
(undocumented)SetUnhandledExceptionFilter
strcat
strchr
strcmp
strcpy
strcspn
strdup
strlen
strncat
strncmp
strncpy
strnlen
strpbrk
strspn
strstr
strtok
strtol
wcslen
wcsnlen
Interceptores opcionales
Los interceptores que se enumeran aquí solo se instalan cuando está habilitada una opción de runtime de AddressSanitizer. Establézcalo windows_hook_legacy_allocators
en false
para deshabilitar la interceptación del asignador heredado.
set ASAN_OPTIONS=windows_hook_legacy_allocators=false
GlobalAlloc
GlobalFree
GlobalHandle
GlobalLock
GlobalReAlloc
GlobalSize
GlobalUnlock
LocalAlloc
LocalFree
LocalHandle
LocalLock
LocalReAlloc
LocalSize
LocalUnlock
Consulte también
Introducción a AddressSanitizer
Problemas conocidos de AddressSanitizer
Referencia de lenguaje y compilación de AddressSanitizer
Bytes de sombra addressSanitizer
Pruebas distribuidas o en la nube addressSanitizer
Integración del depurador AddressSanitizer
Ejemplos de errores addressSanitizer