Mac для "безопасных" альтернатив "небезопасным" функциям стандартной библиотеки C/С++?

Какое лучшее одноразовое "безопасное" решение для библиотеки C на Mac? Я использую кавычки на "безопасном" / "небезопасном", потому что много дискуссий относительно преимуществ определенных функций Стандартной библиотеки или их предположительно улучшенных альтернатив.

Многие традиционные функции стандартной библиотеки C (например, vfprintf) считаются небезопасными из-за возможности переполнения буфера или других проблем безопасности.

В Windows компиляторы Microsoft C/С++ предоставляют функции "_s" (например, vfprintf_s) как более безопасную альтернативу стандартные вызовы библиотеки. Эти функции не являются заменой на вставку, поскольку они имеют разные сигнатуры, необходимые для обеспечения дополнительной информации о безопасности (например, длина буфера). Они также предоставляют другие функции, такие как неверное определение строки формата, различная защита файлов и т.д. Насколько мне известно, эта реализация недоступна на Mac.

Обеспечивает ли Apple (или сторонняя сторона) что-либо подобное для использования с GCC на OSX?

В частности, я ищу "безопасные" реализации, по крайней мере, следующих функций:

fopen vfprintf vsprintf sprintf strncpy strcpy strcat

Обратите внимание: этот вопрос касается Mac. Я НЕ прошу вашего мнения о реализации Microsoft (если только он не доступен на Mac.) Хотя некоторые из этих функций могут быть легко написаны сами, не все. Я НЕ спрашиваю, как писать их сам. Я не прошу советов о том, как использовать классы STL для этого. Я не спрашиваю, как отключить предупреждения. Мои особые потребности очень специфичны. Я пытаюсь идентифицировать Mac API с лучшей практикой, который по возможности похож на традиционные вызовы библиотеки C при одновременном добавлении безопасности. Конечно, портативная реализация, которая работает на Mac и Windows (и других операционных системах), будет еще лучше.

Ответ 1

РЕЗЮМЕ: на Mac существует несколько API и параметры компилятора, которые обеспечивают более безопасные альтернативы функциям C стандартной библиотеки. Вот некоторые из них по сравнению с "безопасными" API-интерфейсами Microsoft:

   C        MSVC      PROVIDERS  MAC SOLUTION
---------------------------------------------------------------------------------
fopen     fopen_s     C          none, assume fopen is safe
vfprintf  vfprintf_s  GCC        GCC_WARN_TYPECHECK_CALLS_TO_PRINTF(1)
vsprintf  vsprintf_s  GCC, C99   GCC_WARN_TYPECHECK_CALLS_TO_PRINTF, vsnprintf(2)
sprintf   sprintf_s   GCC, C99   GCC_WARN_TYPECHECK_CALLS_TO_PRINTF, snprintf(3)
strncpy   strncpy_s   BSD        strlcpy(4)
strcpy    strcpy_s    BSD        strlcpy
strcat    strcat_s    BSD        strlcat(5)

(1) GCC_WARN_TYPECHECK_CALLS_TO_PRINTF - это параметр конфигурации XCode, который соответствует опции командной строки GCC -Wformat. Этот параметр предоставляет предупреждения компилятора о несогласии между типами аргументов и строками статического формата. Существует множество других опций для контроля обработки строк в формате GCC. Вы можете даже использовать GCC format атрибут функции, чтобы включить проверку строки формата на свои собственные функции.

(2) vsnprintf и (3) snprintf из C99-версии стандартной библиотеки C (доступно в GCC на Mac, но не в MSVC в Windows).

(4) strlcpy и (5) strlcat - это функции библиотеки BSD, доступные на Mac.

Ответ 2

Прежде всего, распечатайте документацию о "безопасных/небезопасных" функциях из MSDN и запишите его!

fopen

Безопасен как fopen_s... Uless вы идиот и считаете, что возвращаемый указатель не является NULL или предоставляет NULL в качестве входного параметра.

vfprintf vsprintf sprintf 

Просто MS не поддерживает C99, используйте семейство snprintf.

 strncpy

Совершенно безопасно, если вы читаете руководство

strcpy strcat

Используйте strncpy и strncat и прочитайте спецификации. (т.е. strncpy может не иметь нулевого завершения)

Итак... еще раз:

Распечатайте документацию о "безопасных/небезопасных" функциях из MSDN и запишите ее!

Ответ 3

Вместо sprintf и vsprintf вы хотите использовать:

snprintf(buffer, buffer_size, fmt_string, args, ...);
vsnprintf(buffer, buffer_size, fmt_string, valist);

Вместо strcpy, strncpy, strcat и strncat вы хотите:

strlcpy(dest, src, dest_size);
strlcat(dest, src, dest_size);

Существует один важный способ, что функции strn не могут быть заменены функциями strl. Если вы хотите скопировать строки, отличные от 0, функции strn позволяют это сделать, установив длину на меньшее значение объема копии и размера целевого буфера. Функции strl этого не делают и работают только тогда, когда исходная строка заканчивается 0.

Не знаете, как fopen или vfprintf считаются небезопасными.

Ответ 4

См. также: SO 327980.

Standard C Committee создал технический отчет TR 24731-1, частично в поддержку Microsoft (я считаю). Он стандартизирует интерфейсы для различных функций, таких как vsnprintf_s(). Однако, к сожалению, интерфейс, определенный стандартом, несовместим с интерфейсом, определенным Microsoft, что делает стандарт в значительной степени несущественным.

Например, TR 24731-1 говорит, что интерфейс vsnprintf_s():

#define _ _STDC_WANT_LIB_EXT1_ _ 1
#include <stdarg.h>
#include <stdio.h>
int vsnprintf_s(char * restrict s, rsize_t n,
                const char * restrict format, va_list arg);

К сожалению, MSDN говорит, что интерфейс vsnprintf_s():

int vsnprintf_s(
   char *buffer,
   size_t sizeOfBuffer,
   size_t count,
   const char *format,
   va_list argptr 
);

Параметры

  • buffer - место хранения для вывода.
  • sizeOfBuffer - размер буфера для вывода.
  • count - Максимальное количество символов для записи (не включая завершающий нуль) или _TRUNCATE.
  • формат - спецификация формата.
  • argptr - указатель на список аргументов.

Обратите внимание, что это не просто вопрос отображения типов: количество фиксированных аргументов различно и, следовательно, непримиримо. Мне также непонятно (и, по-видимому, комитету по стандартам), какая польза от наличия "sizeOfBuffer" и "count"; он похож на ту же информацию дважды (или, по крайней мере, код обычно записывается с тем же значением для обоих параметров).

Ответ 5

Так как пользовательский интерфейс OSX основан на FreeBSD, у вас есть несколько более приятных функций, таких как strlcpy и strlcat.

Ответ 6

В стандарте C уже есть набор "безопасной" версии этих функций.
(Для конкретного определения термина safe)

snprintf() (и семья) предоставляют функции безопасности, которые вы ищете. Проверка переполнения буфера.
Компилятор gcc дополнительно выполняет проверку строки строки (но лучше, чем MS, потому что проверка выполняется во время компиляции).

fopen()             Not sure how you make that safer?
vfprintf            --  These are low level functions
vsprintf            --  These are low level functions
sprintf             snprintf
strncpy             Already the safe version
strcpy              strncpy
strcat              strncat

Ответ 7

В частности, я ищу "безопасные" реализации, по крайней мере, следующих функций: fopen vfprintf vsprintf sprintf strncpy strcpy strcat...

Я пытаюсь определить лучший API-интерфейс Mac, который как можно более похож на традиционные вызовы библиотеки C при добавлении безопасности.

Это легко. Ознакомьтесь с Руководство по безопасному кодированию Apple. Apple использует BSD более безопасные функции.

enter image description here


Связано: в то время как Apple и Microsoft обеспечивают более безопасные функции, Linux не работает. GNU C не включал "Интерфейсы проверки границ" (ISO TR24731), потому что возражали такие люди, как Ульрих Дреппер (GNK libc gatekeeper). Он возражал, потому что был указан только целевой буфер. Он назвал "безопасную" функцию BSD Crap. Для цитаты Drepper см. Re: PATCH: безопасная копия и конкатрация строк в списке рассылки Sourceware.

Следуя советам Drepper, вы получите впечатляющие неудачи. CVE-2012-5958 CVE-2012-5959 CVE-2012-5960 CVE-2012-5961 CVE-2012-5962 CVE-2012-5963 CVE-2012-5964 CVE-2012-5965 (также известный как множественное переполнение буфера в libupnp) для победы! Его слишком плохой libupnp следовал за Drepper и игнорировал лучшие практики и отбрасывал "более безопасные" функции. Интересно, сколько миллионов маршрутизаторов и шлюзов осталось непроверенным даже сегодня...