Анализируемость
Это необязательное расширение языка C, ограничивающее потенциальные результаты выполнения некоторых форм неопределенного поведения, что повышает эффективность статического анализа таких программ. Анализируемость гарантируется только при включении предопределенной макроконстанты макроконстанты __STDC_ANALYZABLE__(C11) в компиляторе.
Если компилятор поддерживает анализируемость, любое языковое или библиотечное конструктор, поведение которого неопределено, дополнительно классифицируется как критическое и ограниченное неопределенное поведение, и поведение всех ограниченных случаев неопределенного поведения ограничено, как указано ниже.
Критическое неопределенное поведение
Критическое неопределенное поведение — это неопределенное поведение, которое может выполнить запись в память или чтение из памяти с модификатором volatile за пределами границ любого объекта. Программа, имеющая критическое неопределенное поведение, может быть уязвимой для эксплойтов.
Только следующие неопределенные поведения являются критическими:
- доступ к объекту за пределами его жизни (например, через висячий указатель)
- запись в объект, объявление которого не совместимо
- вызов функции через указатель на функцию, тип которого не совместим с типом функции, на которую он указывает
- вычисление выражения типа lvalue, но оно не обозначает объект
- попытка модификации строковой константы
- разыменование некорректного (нулевой, неопределенный и т. д.) или выходящего за пределы указателя
- модификация константного объекта через неконстантный указатель
- вызов стандартной библиотечной функции или макроса с некорректным аргументом
- вызов вариадической функции стандартной библиотеки с неожиданным типом аргумента (например, вызов
printfс аргументом типа, который не соответствует его спецификатору преобразования) -
longjmpпри отсутствииsetjmpв вызывающей области, между потоками или из области типа виртуальной машины. - любое использование указателя, который был освобожден
freeилиrealloc - любой доступ к массиву за пределами границ в функции библиотеки строк или широких строк
Ограниченное неопределенное поведение
Ограниченное неопределенное поведение — это неопределенное поведение, которое не может выполнить незаконную запись в память, хотя может вызвать ловушку и может произвести или сохранить неопределенные значения.
- Все неопределенные поведения, не перечисленные как критические, являются ограниченными, включая
- гонки данных в многопоточных программах
- использование неопределенных значений с автоматическим сроком жизни
- нарушения строгого алиасинга
- доступ к невыровненному объекту
- переполнение знакового целого
- неупорядоченные побочные эффекты, изменяющие один и тот же скаляр или изменяющие и читающие один и тот же скаляр
- переполнение при преобразовании из плавающей точки в целое или из указателя в целое преобразования
- побитовое сдвиг на отрицательное или слишком большое количество бит
- деление на ноль
- использование выражения void
- непосредственное присваивание или
memcpyнеточно перекрывающихся объектов - нарушения restrict
- и т.д. ВСЕ неопределенные поведения, отсутствующие в критически списке.
Примечания
Ограниченное неопределенное поведение отключает некоторые оптимизации: компиляция с включенной анализируемостью сохраняет причинно-следственную связь исходного кода, которая может быть нарушена неопределенным поведением в противном случае.
Расширение анализируемости позволяет, как форму реализации, определённого поведения, для обработчика ограничений времени выполнения вызываться при возникновении ловушки.
Ссылки
- Стандарт C11 (ISO/IEC 9899:2011):
- 6.10.8.3/1 Условные макросы (с. 177)
- Приложение L Анализируемость (с. 652-653)
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/analyzability