Bytes paralelos de AddressSanitizer
Hemos resumido brevemente el concepto de bytes paralelos y cómo se pueden usar en la implementación de runtime de /fsanitize=address
. Para obtener más información, le referimos a la investigación inicial AddressSanitizer - Serebryany, et al y a la documentación actual del algoritmo AddressSanitizer.
Concepto básico
Cada 8 bytes del espacio de direcciones virtuales de la aplicación se puede describir mediante un byte paralelo.
Un byte paralelo describe cuántos bytes son accesibles actualmente de la siguiente manera:
- 0 significa el total de los 8 bytes
- 1-7 significa de uno a siete bytes
- Los números negativos codifican el contexto para el runtime que se va a usar para los informes de diagnóstico.
Leyenda de los bytes paralelos
Tenga en cuenta esta leyenda de bytes paralelos en la que se definen todos los números negativos:
Asignación: descripción del espacio de direcciones
Cada 8 bytes del espacio de direcciones virtuales de la aplicación que es "0-mod-8" alineado se puede asignar al byte paralelo que describe esa ranura en el espacio de direcciones virtuales. Esta asignación se puede realizar con un simple procedimiento de desplazamiento y suma.
En x86:
char shadow_byte_value = *((Your_Address >> 3) + 0x30000000)
En x64:
char shadow_byte_value = *((Your_Address >> 3) + _asan_runtime_assigned_offset)
Generación de código: pruebas
Tenga en cuenta cómo podrían escribirse bytes paralelos específicos, ya sea mediante el código generado por el compilador, datos estáticos o el runtime. Este pseudocódigo muestra cómo es posible generar una comprobación que precede a cualquier carga o almacenaje:
ShadowAddr = (Addr >> 3) + Offset;
if (*ShadowAddr != 0) {
ReportAndCrash(Addr);
}
Al instrumentar una referencia de memoria inferior a 8 bytes de ancho, la instrumentación es ligeramente más compleja. Si el valor paralelo es positivo (lo que significa que solo se puede tener acceso a los primeros k bytes de la palabra de 8 bytes), es necesario comparar los últimos 3 bits de la dirección con k.
ShadowAddr = (Addr >> 3) + Offset;
k = *ShadowAddr;
if (k != 0 && ((Addr & 7) + AccessSize > k)) {
ReportAndCrash(Addr);
}
El runtime y el código generado por el compilador escriben bytes de paralelos. Estos bytes paralelos permiten o revocan el acceso cuando se finalizan los ámbitos o se libera almacenamiento. Las comprobaciones anteriores leen bytes paralelos que describen "ranuras" de 8 bytes en el espacio de direcciones de la aplicación, en un momento determinado en la ejecución del programa. Además de estas comprobaciones generadas explícitamente, el runtime también comprueba bytes paralelos después de interceptar (o "enlazar") muchas funciones de CRT.
Para obtener más información, consulte la lista de funciones interceptadas.
Establecer bytes paralelos
Tanto el código que genera el compilador como el runtime de AddressSanitizer pueden escribir bytes paralelos. Por ejemplo, el compilador puede establecer bytes paralelos para permitir el acceso de tamaño fijo a las variables locales de pila definidas en un ámbito interno. El runtime puede rodear variables globales en la sección de datos con bytes paralelos.
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
Pruebas distribuidas o en la nube addressSanitizer
Integración del depurador AddressSanitizer
Ejemplos de errores addressSanitizer