6.54 Проверка размера объектов встроенными функциями
GCC реализует ограниченный механизм защиты от переполнения буфера, который может предотвратить некоторые атаки с переполнением буфера.
является встроенной конструкцией, которая возвращает постоянное количество байтов от 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