Analyzability (since C11)
Это дополнительное расширение языка C ограничивает потенциальные результаты выполнения некоторых форм неопределенного поведения, что повышает эффективность статического анализа таких программ. Гарантия включения анализируемости предоставляется только если предопределенная макроконстанта __STDC_ANALYZABLE__ определена компилятором.
Если компилятор поддерживает анализируемость, любая языковая или библиотечная конструкция с неопределённым поведением дополнительно классифицируется как критическое и ограниченное неопределённое поведение, при этом поведение всех случаев ограниченного UB ограничивается, как указано ниже.
Содержание |
Критическое неопределённое поведение
Критическое неопределенное поведение (UB) — это неопределенное поведение, которое может выполнить запись в память или чтение из энергозависимой памяти за пределами любого объекта. Программа, содержащая критическое неопределенное поведение, может быть уязвима для эксплуатации уязвимостей безопасности.
Только следующие неопределенные поведения являются критическими:
- доступ к объекту вне его времени жизни (например, через висячий указатель)
- запись в объект, объявления которого не являются совместимыми
- вызов функции через указатель на функцию, тип которого не совместим с типом функции, на которую он указывает
- lvalue выражение вычисляется, но не обозначает объект
- попытка модификации строкового литерала
- разыменование невалидного (null, неопределенного и т.д.) или указателя за пределами массива
- модификация константного объекта через неконстантный указатель
- вызов функции или макроса стандартной библиотеки с невалидным аргументом
- вызов вариативной функции стандартной библиотеки с неподдерживаемым типом аргумента (например, вызов printf с аргументом типа, не соответствующего спецификатору преобразования)
- longjmp при отсутствии setjmp в вызывающей области видимости, между потоками или из области видимости типа VM
- любое использование указателя, который был освобожден с помощью free или realloc
- любая функция библиотеки строк или широких строк обращается к массиву за его границами
Ограниченное неопределённое поведение
Ограниченное неопределённое поведение — это неопределённое поведение, которое не может выполнить незаконную запись в память, хотя может вызывать ловушки и может производить или сохранять неопределённые значения.
- Все неопределённое поведение, не указанное как критическое, является ограниченным, включая
-
- многопоточные гонки данных
- использование неопределенных значений с автоматической продолжительностью хранения
- нарушения строгого псевдониминга
- невыровненный доступ к объекту
- переполнение знакового целого числа
- неупорядоченные побочные эффекты изменяют один и тот же скаляр или изменяют и читают один и тот же скаляр
- переполнение при преобразовании плавающего в целое или указателя в целое
- побитовый сдвиг на отрицательное или слишком большое количество бит
- целочисленное деление на ноль
- использование void-выражения
- прямое присваивание или memcpy неточно перекрывающихся объектов
- нарушения restrict
- и т.д.. ВСЕ неопределенное поведение, не входящее в критический список.
Примечания
Ограниченное неопределённое поведение отключает определённые оптимизации: компиляция с включённой анализируемостью сохраняет причинность исходного кода, которая может нарушаться неопределённым поведением в противном случае.
Расширение анализируемости позволяет, в виде определяемой реализацией поведения, вызывать обработчик ограничений времени выполнения при возникновении ловушки.
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
-
- 6.10.10.4/1 Условные макросы возможностей (стр. 188-189)
-
- Приложение L Анализируемость (стр. 672-673)
- Стандарт C17 (ISO/IEC 9899:2018):
-
- 6.10.8.3/1 Условные макросы возможностей (стр: 128-129)
-
- Приложение L Анализируемость (стр: 473-474)
- Стандарт C11 (ISO/IEC 9899:2011):
-
- 6.10.8.3/1 Условные макросы возможностей (стр. 177)
-
- Приложение L Анализируемость (стр. 652-653)