Spec-Zone.ru › GCC 14

6.60 Проверка размера объектов

  • Встроенные функции проверки размера объектов
  • Проверка размера объектов и укрепление исходного кода

6.60.1 Встроенные функции проверки размера объектов

GCC реализует ограниченный механизм защиты от переполнения буфера, который может предотвратить некоторые атаки переполнения буфера, определяя размеры объектов, в которые данные собираются для записи, и предотвращая записи, когда размер недостаточен. Встроенные функции, описанные ниже, дают лучшие результаты, когда используются вместе и при включенной оптимизации. Например, для определения размеров объектов через границы функций или для отслеживания присваиваний указателей через нетривиальные потоки управления они полагаются на различные оптимизационные проходы, включенные с -O2. Однако в ограниченной степени они могут использоваться и без оптимизации.

Встроенная функция: size_t __builtin_object_size (const void * ptr, int type)

является встроенной конструкцией, которая возвращает постоянное число байтов от ptr до конца объекта, на который указывает указатель ptr (если это известно на этапе компиляции). Для определения размеров динамически выделенных объектов функция полагается на функции выделения, вызываемые для получения хранилища, которое будет объявлено с атрибутом alloc_size (см. Общие атрибуты функций). __builtin_object_size никогда не оценивает свои аргументы для побочных эффектов. Если в них есть побочные эффекты, она возвращает (size_t) -1 для type 0 или 1 и (size_t) 0 для type 2 или 3. Если есть несколько объектов, на которые может указывать ptr, и все они известны на этапе компиляции, возвращаемое число является максимальным из оставшихся байтовых отсчетов в этих объектах, если type & 2 равно 0, и минимальным, если не равно нулю. Если невозможно определить, на какие объекты указывает ptr на этапе компиляции, __builtin_object_size должна вернуть (size_t) -1 для type 0 или 1 и (size_t) 0 для type 2 или 3.

type - это целочисленная константа от 0 до 3. Если младший бит сброшен, объекты представляют собой целые переменные, если он установлен, ближайший окружающий подобъект рассматривается как объект, на который указывает указатель. Второй бит определяет, вычисляется ли максимум или минимум оставшихся байтов.

struct V { char buf1[10]; int b; char buf2[10]; } var;
char *p = &var.buf1[1], *q = &var.b;

/* Here the object p points to is var.  */
assert (__builtin_object_size (p, 0) == sizeof (var) - 1);
/* The subobject p points to is var.buf1.  */
assert (__builtin_object_size (p, 1) == sizeof (var.buf1) - 1);
/* The object q points to is var.  */
assert (__builtin_object_size (q, 0)
        == (char *) (&var + 1) - (char *) &var.b);
/* The subobject q points to is var.b.  */
assert (__builtin_object_size (q, 1) == sizeof (var.b));
Встроенная функция: size_t __builtin_dynamic_object_size (const void * ptr, int type)

аналогична __builtin_object_size, поскольку она возвращает число байтов от ptr до конца объекта, на который указывает указатель ptr, за исключением того, что возвращаемый размер может не быть константой. Это приводит к успешной оценке оценок размера объектов в более широком диапазоне случаев использования и может быть более точным, чем __builtin_object_size, но это влечет за собой штраф производительности, поскольку оно может добавить задержку во время выполнения при вычислении размера. Семантика type, а также значения возврата в случае, если невозможно определить, на какие объекты указывает ptr на этапе компиляции, такие же, как в случае __builtin_object_size.

6.60.2 Проверка размера объектов и укрепление исходного кода

Усиление вызовов функций с помощью макроса _FORTIFY_SOURCE является одним из ключевых применений встроенных функций проверки размера объектов. Для повышения удобства реализации этих функций, улучшения оптимизации и диагностики были добавлены встроенные функции для многих распространенных функций работы со строками, например, для memcpy __builtin___memcpy_chk встроенная функция. Эта встроенная функция имеет дополнительный последний аргумент, который представляет собой количество оставшихся байтов в объекте, на который указывает аргумент dest, или (size_t) -1 если размер неизвестен.

Встроенные функции оптимизируются в обычные функции работы со строками, такие как memcpy, если последний аргумент (size_t) -1 или если на этапе компиляции известно, что объект назначения не будет переполнен. Если компилятор может определить на этапе компиляции, что объект всегда будет переполнен, он выдает предупреждение.

Предполагаемое использование, например:

#undef memcpy
#define bos0(dest) __builtin_object_size (dest, 0)
#define memcpy(dest, src, n) \
  __builtin___memcpy_chk (dest, src, n, bos0 (dest))

char *volatile p;
char buf[10];
/* It is unknown what object p points to, so this is optimized
   into plain memcpy - no checking is possible.  */
memcpy (p, "abcde", n);
/* Destination is known and length too.  It is known at compile
   time there will be no overflow.  */
memcpy (&buf[5], "abcde", 5);
/* Destination is known, but the length is not known at compile time.
   This will result in __memcpy_chk call that can check for overflow
   at run time.  */
memcpy (&buf[5], "abcde", n);
/* Destination is known and it is known at compile time there will
   be overflow.  There will be a warning and __memcpy_chk call that
   will abort the program at run time.  */
memcpy (&buf[6], "abcde", 5);

Такие встроенные функции предоставляются для memcpy, mempcpy, memmove, memset, strcpy, stpcpy, strncpy, strcat и strncat.

  • Проверка функций форматированного вывода

6.60.2.1 Проверка функций форматированного вывода

Встроенная функция: int __builtin___sprintf_chk (char *s, int flag, size_t os, const char *fmt, ...)
Встроенная функция: int __builtin___snprintf_chk (char *s, size_t maxlen, int flag, size_t os, const char *fmt, ...)
Встроенная функция: int __builtin___vsprintf_chk (char *s, int flag, size_t os, const char *fmt, va_list ap)
Встроенная функция: int __builtin___vsnprintf_chk (char *s, size_t maxlen, int flag, size_t os, const char *fmt, va_list ap)

Добавленный аргумент flag передается без изменений функциям __sprintf_chk и т. д. и может содержать флаги, специфичные для реализации, указывающие на дополнительные меры безопасности, которые может принять функция проверки, например, различное обращение с %n.

Аргумент os — это размер объекта, на который указывает s, как и в других встроенных функциях. Однако есть небольшое различие в поведении: если os равно (size_t) -1, встроенные функции оптимизируются в неопределяющие функции только если flag равно 0, в противном случае функция проверки вызывается с аргументом os, установленным в (size_t) -1.

Кроме того, существуют встроенные функции проверки __builtin___printf_chk, __builtin___vprintf_chk, __builtin___fprintf_chk и __builtin___vfprintf_chk. У них есть только один дополнительный аргумент flag перед строкой формата fmt. Если компилятор может оптимизировать их до fputc и т.д. функций, он это делает, в противном случае вызывается функция проверки, и аргумент flag передается ей.

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Object-Size-Checking.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API