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

时间:2010-01-30 18:55:15

标签: c macos gcc

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

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

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

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

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

fopen vfprintf vsprintf sprintf strncpy strcpy strcat

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

8 个答案:

答案 0 :(得分:16)

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

fopen

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

vfprintf vsprintf sprintf 

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

 strncpy

如果您阅读手册

,则完全安全
strcpy strcat

使用strncpystrncat并阅读规范。 (即strncpy可能不会以空值终止)

所以......再一次:

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

答案 1 :(得分:9)

摘要:在Mac上,有几个API和编译器选项可以提供更安全的C标准库函数替代方案。以下是其中一些与Microsoft's "safe" APIs比较的结果:

   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 function attribute来启用对您自己的函数的格式字符串检查。

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

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

答案 2 :(得分:5)

而是使用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如何被视为不安全。

答案 3 :(得分:4)

另请参阅:SO 327980

Standard C committee创建了一份技术报告TR 24731-1,部分原因是微软的鼓励(我相信)。它将接口标准化为各种功能,例如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'都有什么好处;它看起来像两次相同的信息(或者,至少,代码通常用两个参数的相同值写入)。

答案 4 :(得分:3)

由于OSX的用户空间基于FreeBSD,因此有一些更好的功能,如strlcpy and strlcat

答案 5 :(得分:3)

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

答案 6 :(得分:3)

  

特别是,我正在寻找&#34; safe&#34;至少实现以下功能:fopen vfprintf vsprintf sprintf strncpy strcpy strcat ...

     

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

这很容易。结帐Apple Secure Coding Guide。 Apple碰巧使用BSD&#34;更安全&#34;功能

enter image description here


相关:虽然Apple和Microsoft提供更安全的功能,但Linux却没有。 GNU C没有包括&#34; Bounds检查接口&#34; (ISO&#39; TR24731)因为像Ulrich Drepper(GNU libc看门人)这样的人反对。他反对,因为只指定了目标缓冲区。他打电话给'#34;更安全&#34;功能BSD废话。有关Drepper的引用,请参阅Sourceware邮件列表中的Re: PATCH: safe string copy and concetation

根据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并且忽略了最佳实践并且丢弃了更安全的&#34;功能。我想知道即使在今天仍有数百万台路由器和网关尚未打补丁......

答案 7 :(得分:1)

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