Spec-Zone.ru › GCC 4

6.54 Проверка размера объектов встроенными функциями

GCC реализует ограниченный механизм защиты от переполнения буфера, который может предотвратить некоторые атаки с переполнением буфера.

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

является встроенной конструкцией, которая возвращает постоянное количество байтов от ptr до конца объекта, на который указывает указатель ptr (если это известно на этапе компиляции). __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));

Для многих распространённых функций работы со строками добавлены встроенные функции, например, для 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.

Также существуют встроенные функции проверки для функций форматированного вывода.

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-4.9.4/gcc/Object-Size-Checking.html

Spec-Zone.ru

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