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

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

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

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

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

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

fopen vfprintf vsprintf sprintf strncpy strcpy strcat

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

9 ответов

Решение

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

   C MSVC ПОСТАВЩИКИ MAC-РЕШЕНИЕ
-------------------------------------------------- -------------------------------
fopen fopen_s C нет, предположим, что fopen безопасен
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 Атрибут function для включения проверки форматной строки ваших собственных функций.

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

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

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

Еореп

Столь же безопасен, как и fopen_s... Если только вы не идиот и не предполагаете, что возвращаемый указатель не равен NULL, или укажите NULL в качестве входного параметра.

vfprintf vsprintf sprintf 

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

 strncpy

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

strcpy strcat

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

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

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

Вместо 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 считаются небезопасными.

Смотрите также: SO 327980.

Комитет по стандарту C создал технический отчет, 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 
);

параметры

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

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

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

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

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


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

Следование совету Дреппера приведет к зрелищным неудачам. 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'у, игнорировал лучшие практики и отбрасывал "более безопасные" функции. Интересно, сколько миллионов роутеров и шлюзов остаются не исправленными даже сегодня...

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

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

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

Google Summer of Code 2010: OpenAfs и Google спонсируют порт библиотеки Microsoft String Safe. См. http://www.openafs.org/pages/gsoc.html.

safeclib — это портативное решение. Реализация MS глючная и небезопасная, существуют и другие реализации, но они не переносимы и не слишком наивны.

https://github.com/rurban/safeclib

Другие вопросы по тегам