Mac解决方案“安全”替代“不安全”的C / C ++标准库函数?

什么是Mac上最好的一站式“安全”C库解决方案? 我在“安全”/“不安全”上使用引号,因为关于某些标准库函数或其推定改进的替代方案的好处存在很多争议。

由于可能存在缓冲区溢出或其他安全问题,许多传统的标准C库函数(例如, vfprintf )被认为是不安全的。

在Windows上,Microsoft C / C ++编译器提供 “_s”函数(例如, vfprintf_s )作为标准库调用的更安全的替代方法。 这些function不是直接替换,因为它们具有提供附加安全信息(例如,缓冲区长度)所必需的不同签名。 它们还提供其他function,例如无效的格式字符串检测,不同的文件安全性等。据我所知,这种实现在Mac上不可用。

Apple(或第三方)是否在OSX上提供与GCC类似的任何内容?

特别是,我正在寻找至少以下function的“安全”实现:

fopen vfprintf vsprintf sprintf strncpy strcpy strcat

请注意:这个问题与Mac有关。 我不是在征求你对微软实施的看法(除非它在Mac上可用。)虽然其中一些function可能很容易自己编写,但并非所有function都可以。 我不是在问自己如何写这些。 我不是要求有关如何使用STL类来做到这一点的提示。 我不是在问如何关闭警告。 我的特殊需求非常具体。 我正在尝试确定最佳实践Mac API,它与传统的C库调用尽可能相似,同时增加了安全性。 当然,在Mac和Windows(以及其他操作系统)上运行的便携式实现会更好。

首先,从MSDN打印有关“安全/不安全”function的文档并刻录它!

FOPEN

和fopen_s一样安全…无论你是白痴还是假设返回的指针不是NULL,或者提供NULL作为输入参数。

 vfprintf vsprintf sprintf 

只是MS不支持C99,请使用snprintf系列。

  strncpy 

如果您阅读本手册,则完全安全

 strcpy strcat 

使用strncpystrncat并读取规范。 (即strncpy可能不会以null结尾)

所以…再一次:

从MSDN打印有关“安全/不安全”function的文档并刻录它!

摘要:在Mac上,有几个API和编译器选项可以提供更安全的C标准库函数替代方案。 以下是其中一些与微软的“安全”API相比 :

    C MSVC提供商MAC解决方案
 -------------------------------------------------- -------------------------------
 fopen fopen_s C none,假设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 函数属性来启用对您自己的函数的格式字符串检查。

(2) vsnprintf和(3) snprintf来自C标准库的C99版本(在Mac上的GCC中可用,但在Windows上不在MSVC中)。

(4) strlcpy和(5) strlcat是BSD库函数,可在Mac上获得。

而不是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); 

有一个重要的方法是strl函数不能替换strn函数。 如果要复制非0终止的字符串,则strn函数允许您通过将长度设置为较小的复制量值和目标缓冲区的大小来实现。 strl函数不会这样做,仅在源字符串0终止时才起作用。

不确定fopen或vfprintf如何被认为是不安全的。

另见: SO 327980 。

标准C委员会已经创建了一份技术报告TR 24731-1 ,部分原因是微软的鼓励(我相信)。 它标准化了各种function的接口,例如vsnprintf_s() 。 但遗憾的是,标准定义的接口与Microsoft定义的接口不兼容,因此使标准在很大程度上无关紧要。

例如,TR 24731-1表示vsnprintf_s()的接口是:

 #define _ _STDC_WANT_LIB_EXT1_ _ 1 #include  #include  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’都有什么好处; 它看起来像两次相同的信息(或者,至少,代码通常用两个参数的相同值写入)。

由于OSX的用户空间基于FreeBSD ,因此你有一些更好的function,如strlcpy和strlcat 。

C标准已经有一套这些function的“安全”版本。
(对于术语“安全”的特定定义)

snprintf()(和系列)提供您正在寻找的安全function。 缓冲区溢出检查。
gcc编译器另外进行格式化字符串validation(但优于MS,因为validation是在编译时完成的)。

 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 

特别是,我正在寻找至少以下function的“安全”实现:fopen vfprintf vsprintf sprintf strncpy strcpy strcat …

我正在尝试确定最佳实践Mac API,它与传统的C库调用尽可能相似,同时增加了安全性。

这很简单。 查看Apple安全编码指南 。 Apple碰巧使用BSD“更安全”的function。

在此处输入图像描述


相关:虽然Apple和Microsoft提供更安全的function,但Linux却没有。 GNU C没有包含“边界检查接口”(ISO的TR24731),因为像Ulrich Drepper(GNU libc网守)这样的人反对。 他反对,因为只指定了目标缓冲区。 他称之为“更安全”的functionBSD 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并且忽略了最佳实践并丢弃了“更安全”的function。 我想知道即使在今天仍有数百万台路由器和网关尚未打补丁……

Google Summer of Code 2010:OpenAfs和Google赞助了Microsoft的String Safe库的端口。 见http://www.openafs.org/pages/gsoc.html 。