Теневые байты в AddressSanitizer
Кратко рассмотрим концепцию теневых байтов и способ их использования реализацией среды выполнения /fsanitize=address
. Дополнительные сведения см. в документации по первоначальному исследованию AddressSanitizer — Serebryany, et al и текущей документации по алгоритму AddressSanitizer.
Основная концепция
Каждый 8 байт в виртуальном адресном пространстве приложения можно описать с помощью одного байта тени.
Один теневой байт описывает, сколько байтов сейчас доступно следующим образом:
- 0 означает, что все 8 байт
- 1-7 означает от 1 до семи байтов
- Отрицательные числа кодируют контекст среды выполнения для создания отчетов диагностика.
Условные обозначения байтов тени
Рассмотрим эту легенду байтов тени, где определены все отрицательные числа:
Сопоставление — описание адресного пространства
Каждый 8 байт в виртуальном адресном пространстве приложения, выровненном "0-mod-8", можно сопоставить с теневым байтом, описывающим этот слот в виртуальном адресном пространстве. Это сопоставление можно выполнить с помощью простой смены и добавления.
В x86:
char shadow_byte_value = *((Your_Address >> 3) + 0x30000000)
В x64:
char shadow_byte_value = *((Your_Address >> 3) + _asan_runtime_assigned_offset)
Создание кода — тесты
Рассмотрим способ записи определенных теневых байтов, созданных компилятором кода, статических данных или среды выполнения. Этот псевдокод показывает, как можно создать проверку, которая предшествует любой нагрузке или хранилищу:
ShadowAddr = (Addr >> 3) + Offset;
if (*ShadowAddr != 0) {
ReportAndCrash(Addr);
}
При инструментировании ссылки на память, которая не превышает 8 байтов, инструментирование немного сложнее. Если теневое значение положительно (то есть только первые k байтов в 8-байтовом слове можно получить к доступу), необходимо сравнить последние 3 бита адреса с k.
ShadowAddr = (Addr >> 3) + Offset;
k = *ShadowAddr;
if (k != 0 && ((Addr & 7) + AccessSize > k)) {
ReportAndCrash(Addr);
}
Среда выполнения и созданный компилятором код записывают теневые байты. Эти теневые байты разрешают или отменяют доступ при освобождении областей или хранилища. Приведенные выше проверки считывают теневые байты, описывающие 8-байтовые "слоты" в адресном пространстве приложения в определенное время выполнения программы. Помимо этих явно созданных проверок среда выполнения также проверяет теневые байты после перехвата (или "перехватчиков") многих функций в CRT.
Дополнительные сведения см. в списке перехватанных функций.
Настройка теневых байтов
Код, который создает компилятор, и среда выполнения AddressSanitizer может записывать теневые байты. Например, компилятор может задать теневые байты, чтобы разрешить доступ фиксированного размера к локальным стекам, определенным в внутренней области. Среда выполнения может окружать глобальные переменные в разделе данных с теневыми байтами.
См. также
Обзор AddressSanitizer
Известные проблемы AddressSanitizer
Справочник по сборке и языку AddressSanitizer
Справочник по среде выполнения AddressSanitizer
Облачное или распределенное тестирование AddressSanitizer
Интеграция отладчика AddressSanitizer
Примеры ошибок AddressSanitizer