Bytes paralelos de AddressSanitizer

Resumimos brevemente el concepto de bytes de sombra y cómo los puede usar la implementación en tiempo de ejecución de /fsanitize=address . Para obtener más información, nos referimos al documento sédico y al algoritmo AddressSanitizer.

Concepto básico

Cada 8 bytes del espacio de direcciones virtuales de la aplicación se puede describir con un byte de sombra.

Un byte de sombra describe cuántos bytes son accesibles actualmente de la siguiente manera:

  • 0 significa los 8 bytes
  • 1-7 significa de uno a siete bytes
  • Los números negativos codifican el contexto del tiempo de ejecución que se usará para los diagnósticos de informes.

Leyenda de bytes de sombra

Considere esta leyenda de bytes de sombra donde se definen todos los números negativos:

Captura de pantalla de la leyenda de shadow-byte addressSanitizer.

Asignación: descripción del espacio de direcciones

Cada 8 bytes del espacio de direcciones virtuales de la aplicación alineado con "0-mod-8" se puede asignar al byte de sombra que describe esa ranura en el espacio de direcciones virtuales. Esta asignación se puede realizar con un desplazamiento simple y agregar.

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 se pueden escribir bytes de sombra específicos, ya sea por el código generado por el compilador, los datos estáticos o el tiempo de ejecución. Este pseudocódigo muestra cómo es posible generar una comprobación que precede a cualquier carga o almacén:

ShadowAddr = (Addr >> 3) + Offset;
if (*ShadowAddr != 0) {
    ReportAndCrash(Addr);
}

Al instrumentar una referencia de memoria de menos de 8 bytes de ancho, la instrumentación es ligeramente más compleja. Si el valor de la sombra es positivo (lo que significa que solo se puede acceder 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);
}

Tanto el tiempo de ejecución como el código generado por el compilador escriben bytes de sombra. Estos bytes de sombra permiten o revocan el acceso cuando los ámbitos finalizan o se libera el almacenamiento. Las comprobaciones anteriores leen bytes de sombra que describen "ranuras" de 8 bytes en el espacio de direcciones de la aplicación, en un momento determinado de la ejecución del programa. Además de estas comprobaciones generadas explícitamente, el tiempo de ejecución también comprueba los bytes de sombra después de interceptar (o "enlazar") muchas funciones de CRT.

Para obtener más información, vea la lista de funciones interceptadas.

Establecimiento de bytes de sombra

Tanto el código que genera el compilador como el tiempo de ejecución addressSanitizer pueden escribir bytes de sombra. Por ejemplo, el compilador puede establecer bytes de sombra para permitir el acceso de tamaño fijo a las locales de pila definidas en un ámbito interno. El tiempo de ejecución puede rodear variables globales en la sección de datos con bytes de sombra.

Vea también

Información general de AddressSanitizer
Problemas conocidos de AddressSanitizer
Referencia de lenguaje y compilación de AddressSanitizer
Referencia del entorno de ejecución de AddressSanitizer
Nube o pruebas distribuidas de AddressSanitizer
Integración del depurador de AddressSanitizer
Ejemplos de errores de AddressSanitizer