AddressSanitizer
Información general
Los lenguajes C & C++ son eficaces, pero pueden sufrir una clase de errores que afectan a la corrección del programa y la seguridad del programa. A partir de la versión 16.9 de Visual Studio 2019, el compilador de Microsoft C/C++ (MSVC) y el IDE admiten el saneador AddressSanitizer . AddressSanitizer (ASan) es un compilador y una tecnología en tiempo de ejecución que expone muchos errores difíciles de encontrar con cero falsos positivos:
- Incompatibilidades de asignación/desasignación e
new
/delete
incompatibilidades de tipos - Asignaciones demasiado grandes para el montón
calloc
desbordamiento y desbordamiento dealloca
- Doble libre y uso después de libre
- Desbordamiento de variables globales
- Desbordamiento del búfer del montón
- Alineación no válida de valores alineados
memcpy
y superposición de parámetrosstrncat
- Desbordamiento y subflujo del búfer de pila
- Uso de pila después de
return
y uso después del ámbito - Uso de la memoria después de estar afectado
Use AddressSanitizer para reducir el tiempo empleado en:
- Corrección básicas
- Portabilidad entre plataformas
- Seguridad
- pruebas de esfuerzo
- Integración de un código nuevo
AddressSanitizer, introducido originalmente por Google, proporciona tecnologías de búsqueda de errores en tiempo de ejecución que usan los sistemas de compilación existentes y los recursos de prueba existentes directamente.
AddressSanitizer se integra con el sistema de proyectos de Visual Studio, el sistema de compilación de CMake y el IDE. Los proyectos pueden habilitar AddressSanitizer estableciendo una propiedad de proyecto o usando una opción del compilador adicional: /fsanitize=address
. La nueva opción es compatible con todos los niveles de optimización y configuraciones de x86 y x64. Sin embargo, no es compatible con editar y continuar, la vinculación incremental y /RTC
.
A partir de la versión 16.9 de Visual Studio 2019, la tecnología AddressSanitizer de Microsoft permite la integración con el IDE de Visual Studio. Opcionalmente, la funcionalidad puede crear un archivo de volcado de memoria cuando el saneador encuentra un error en el tiempo de ejecución. Si establece la variable de entorno antes de ejecutar el ASAN_SAVE_DUMPS=MyFileName.dmp
programa, se crea un archivo de volcado de memoria con metadatos adicionales para una depuración posterior eficaz de errores diagnosticados con precisión. Estos archivos de volcado facilitan el uso extendido de AddressSanitizer para:
- Pruebas de máquinas locales
- Pruebas distribuidas locales
- Flujos de trabajo basados en la nube para pruebas
Instalar AddressSanitizer
Las cargas de trabajo de C++ en el Instalador de Visual Studio instalan las bibliotecas addressSanitizer y la integración del IDE de forma predeterminada. Sin embargo, si va a actualizar desde una versión anterior de Visual Studio 2019, use el Instalador para habilitar la compatibilidad con ASan después de la actualización. Puede abrir el instalador desde el menú principal de Visual Studio a través de Herramientas>Obtener herramientas y características... Elija Modificar en la instalación de Visual Studio existente en el Instalador de Visual Studio para ir a la pantalla siguiente.
Nota:
Si se ejecuta Visual Studio en la nueva actualización pero no se ha instalado ASan, se recibirá un error al ejecutar el código:
LNK1356: no se puede encontrar 'clang_rt.asan_dynamic-i386.lib'
Usar AddressSanitizer
Comience a compilar los ejecutables con la opción del compilador /fsanitize=address
mediante cualquiera de estos métodos de desarrollo comunes:
- Compilaciones de línea de comandos
- Sistema de proyectos de Visual Studio
- Integración de Visual Studio CMake
Vuelva a compilar y después ejecute el programa con normalidad. Esta generación de código expone muchos tipos de errores diagnosticados con precisión. Estos errores se notifican de tres maneras: en el IDE del depurador, en la línea de comandos o almacenados en un nuevo tipo de archivo de volcado para un procesamiento preciso fuera de línea.
Microsoft recomienda usar AddressSanitizer en estos tres flujos de trabajo estándar:
Bucle interno del desarrollador
- Visual Studio: Línea de comandos
- Visual Studio: Sistema de proyectos
- Visual Studio: CMake
CI/CD: integración continua/desarrollo continuo
- Informes de errores: Nuevos archivos de volcado de AddressSanitizer
Búsqueda aproximada: compilación con el contenedor libFuzzer
- Azure OneFuzz
- Equipo local
En este artículo se describe la información necesaria para habilitar los tres flujos de trabajo enumerados anteriormente. La información es específica de la implementación de Windows 10 dependiente de la plataforma (y versiones posteriores) de AddressSanitizer. Esta documentación complementa la excelente documentación de Google, Apple y GCC ya publicada.
Nota:
La compatibilidad se limita a x86 y x64 en Windows 10 y versiones posteriores. Envíenos sus comentarios sobre lo que le gustaría ver en futuras versiones. Sus comentarios nos ayudan a priorizar otros saneadores para el futuro, como /fsanitize=thread
, /fsanitize=leak
, /fsanitize=memory
, /fsanitize=undefined
o /fsanitize=hwaddress
. Puede notificar errores aquí si tiene problemas.
Uso de AddressSanitizer desde un símbolo del sistema para desarrolladores
Use la opción del compilador /fsanitize=address
en un símbolo del sistema para desarrolladores para habilitar la compilación del runtime de AddressSanitizer. La opción /fsanitize=address
es compatible con todos los niveles de optimización de C++ o C existentes (por ejemplo, /Od
, /O1
, /O2
, /O2 /GL
y PGO
). La opción funciona con CRT estáticos y dinámicos (por ejemplo, /MD
, /MDd
, /MT
y /MTd
). Funciona tanto si se crea un archivo EXE como un DLL. La información de depuración es necesaria para un formato óptimo de las pilas de llamadas. En el ejemplo siguiente, cl /fsanitize=address /Zi
se pasa en la línea de comandos.
Las bibliotecas AddressSanitizer (archivos.lib) se vinculan automáticamente. Para más información, consulte la Referencia de lenguaje, compilación y depuración de AddressSanitizer.
Ejemplo: desbordamiento de búfer global básico
// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
printf("Hello!\n");
x[100] = 5; // Boom!
return 0;
}
Con un símbolo del sistema para desarrolladores de Visual Studio 2019, compile main.cpp
con /fsanitize=address /Zi
Al ejecutar el resultado main.exe
en la línea de comandos, crea el informe de errores con formato siguiente.
Tenga en cuenta los cuadros rojos superpuestos que resaltan siete fragmentos clave de información:
Hay siete resaltados rojos que identifican fragmentos clave de información en el informe de errores. Se asignan a la lista numerada que sigue a esta captura de pantalla. Los cuadros numerados resaltan el texto siguiente: 1) global-buffer-overflow 2) WRITE de tamaño 4 3) basic-global-overflow.cpp 7 4) a la derecha de la variable global 'x' definida en 'basic-global-overflow.cpp:3:8' 5) de tamaño 400 6) 00 00[f9]f9 f9 f9 f9 7) Box está en el área de leyenda de bytes de sombra y contiene la zona roja global: f9
Resaltados rojos, de arriba a abajo
- El error de seguridad de la memoria es un desbordamiento global de búfer.
- Había 4 bytes (32 bits) almacenados fuera de cualquier variable definida por el usuario.
- El almacén tuvo lugar en la función
main()
definida en el archivobasic-global-overflow.cpp
en la línea 7. - La variable denominada
x
se define en basic-global-overflow.cpp en la línea 3, a partir de la columna 8 - Esta variable global
x
tiene un tamaño de 400 bytes - El byte de propiedad reemplazada exacto que describe la dirección de destino del almacén tenía un valor de
0xf9
- La leyenda de bytes de propiedad reemplazada dice que
0xf9
es un área de relleno a la derecha deint x[100]
Nota:
Los nombres de función de la pila de llamadas se generan a través del simbolizador LLVM invocado por el tiempo de ejecución tras el error.
Uso de AddressSanitizer en Visual Studio
AddressSanitizer se integra con el IDE de Visual Studio. Para activar AddressSanitizer para un proyecto de MSBuild, haga clic con el botón derecho en el proyecto en Explorador de soluciones y elija Propiedades. En el cuadro de diálogo Páginas de propiedades, seleccione Propiedades de configuración>C/C++>General y, a continuación, modifique la propiedad Activar AddressSanitizer. Elija Aceptar para guardar los cambios.
Para compilar desde el IDE, opte por no participar en las opciones incompatibles. Para un proyecto existente compilado mediante /Od
(o modo de depuración), es posible que tenga que desactivar estas opciones:
- Desactivar editar y continuar
- Desactivar
/RTC1
(comprobaciones en runtime) - Desactivar
/INCREMENTAL
(vinculación incremental)
Para compilar y ejecutar el depurador, presione F5. Aparece una ventana Excepción iniciada en Visual Studio:
Uso de AddressSanitizer desde Visual Studio: CMake
Para habilitar AddressSanitizer para un proyecto de CMake creado para Windows de destino, siga estos pasos:
Abra la lista desplegable Configuraciones en la barra de herramientas de la parte superior del IDE y seleccione Administrar configuraciones.
Que abre el editor configuración del proyecto de CMake, que refleja el contenido del archivo del
CMakeSettings.json
proyecto.Elija el vínculo Editar JSON en el editor. Esta selección cambia la vista a JSON sin formato.
Agregue el siguiente fragmento de código al
"windows-base"
valor preestablecido, dentro"configurePresets":
de para activar Address Sanitizer:"environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" }
"configurePresets"
parece algo parecido a esto, después:"configurePresets": [ { "name": "windows-base", "hidden": true, "generator": "Ninja", "binaryDir": "${sourceDir}/out/build/${presetName}", "installDir": "${sourceDir}/out/install/${presetName}", "cacheVariables": { "CMAKE_C_COMPILER": "cl.exe", "CMAKE_CXX_COMPILER": "cl.exe" }, "condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" }, "environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" } },
El saneador de direcciones no funciona si se especifica edit-and-continue (
/ZI
), que está habilitado de forma predeterminada para los nuevos proyectos de CMake. EnCMakeLists.txt
, convierta en comentario (prefijo con#
) la línea que comienza porset(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"
. Esa línea tiene un aspecto similar al siguiente:# set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
Escriba Ctrl+S para guardar este archivo JSON.
Borre el directorio de caché de CMake y vuelva a configurar eligiendo en el menú de Visual Studio: Project Delete cache (Eliminar caché del proyecto>) y Reconfigure (Volver a configurar). Elija Sí cuando aparezca el mensaje para borrar el directorio de caché y volver a configurarlo.
Reemplace el contenido del archivo de origen (por ejemplo,
CMakeProject1.cpp
) por lo siguiente:// CMakeProject1.cpp : Defines the entry point for the application #include <stdio.h> int x[100]; int main() { printf("Hello!\n"); x[100] = 5; // Boom! return 0; }
Elija F5 para volver a compilar y ejecutar en el depurador.
Esta captura de pantalla registra el error de la compilación de CMake.
Volcados de memoria de AddressSanitizer
Se introdujo una nueva funcionalidad en AddressSanitizer para su uso con flujos de trabajo distribuidos y en la nube. Esta funcionalidad permite la visualización sin conexión de un error AddressSanitizer en el IDE. El error se superpone que se encuentra en su origen, tal como lo experimentaría en una sesión de depuración en directo.
Estos nuevos archivos de volcado de memoria pueden provocar eficiencias al analizar un error. No es necesario volver a ejecutar o buscar datos remotos o buscar una máquina que se haya desactivado.
Para generar un nuevo tipo de archivo de volcado de memoria que se pueda ver en Visual Studio en otro equipo en una fecha posterior:
set ASAN_SAVE_DUMPS=MyFileName.dmp
A partir de Visual Studio 16.9, se puede mostrar un error de diagnóstico preciso, almacenado en el archivo *.dmp
, sobre el código fuente.
Esta nueva funcionalidad de volcado de memoria permite flujos de trabajo basados en la nube o pruebas distribuidas. También se puede usar para archivar un error detallado y accionable en cualquier escenario.
Errores de ejemplo
AddressSanitizer puede detectar varios tipos de errores del uso incorrecto de memoria. Estos son muchos de los errores en runtime notificados al ejecutar los archivos binarios compilados mediante la opción del compilador AddressSanitizer (/fsanitize=address
):
alloc-dealloc-mismatch
allocation-size-too-big
calloc-overflow
double-free
dynamic-stack-buffer-overflow
global-buffer-overflow
heap-buffer-overflow
heap-use-after-free
invalid-allocation-alignment
memcpy-param-overlap
new-delete-type-mismatch
stack-buffer-overflow
stack-buffer-underflow
stack-use-after-return
stack-use-after-scope
strncat-param-overlap
use-after-poison
Para obtener más información sobre los ejemplos, consulte Ejemplos de errores de AddressSanitizer.
Diferencias con Clang 12.0
MSVC actualmente difiere de Clang 12.0 en dos áreas funcionales:
- stack-use-after-scope: esta configuración está activada de forma predeterminada y no se puede desactivar.
- stack-use-after-return: esta funcionalidad requiere una opción de compilador adicional y no está disponible estableciendo solo
ASAN_OPTIONS
.
Estas decisiones se tomaron para reducir la matriz de pruebas necesaria para entregar esta primera versión.
Las características que podrían provocar falsos positivos en Visual Studio 2019 16.9 no se incluyeron. Esa disciplina ha reforzado la integridad de las pruebas efectivas necesarias al considerar la interoperabilidad con décadas de código existente. Es posible que se consideren más capacidades en versiones posteriores:
- Fracasos de orden de inicialización
- Desbordamiento de objetos intra
- Desbordamiento del contenedor
- Resta/comparación de puntero
Para obtener más información, consulte Building for AddressSanitizer with MSVC (Compilación de addressSanitizer con MSVC).
Documentación del sector existente
Ya existe una amplia documentación sobre estas implementaciones dependientes del lenguaje y de la plataforma de la tecnología AddressSanitizer.
Este documento seminal sobre addressSanitizer (externo) describe la implementación.
Consulte también
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