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

jwf*_*arn 11 c macos gcc

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

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

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

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

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

fopen vfprintf vsprintf sprintf strncpy strcpy strcat

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

Art*_*yom 16

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

FOPEN

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

vfprintf vsprintf sprintf 
Run Code Online (Sandbox Code Playgroud)

只是MS不支持C99,使用snprintf家庭.

 strncpy
Run Code Online (Sandbox Code Playgroud)

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

strcpy strcat
Run Code Online (Sandbox Code Playgroud)

使用strncpystrncat和读取规格.(即strncpy可能不会以null结尾)

所以...再一次:

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

  • @jwfearn - 关键是MS创建了自己的"安全"功能,而不是采用C99的安全功能.例如,fopen_s是完全"废话",sprintf_s也是 - 使用snprintf.等等.是的,strncpy和strncat是非常的,但仍然,保持标准然后更好...不要把你读到的关于"不安全的功能"的一切都写下来 (4认同)
  • strncpy/strncat是安全的,但使用正确是一种痛苦.strncpy要求调用者添加0终止符.strncat要求用户计算复制的数量,而不是目标缓冲区的大小. (3认同)

jwf*_*arn 9

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

   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来自C标准库的C99版本(在Mac上的GCC中可用,但在Windows上的MSVC中不可用).

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


R S*_*hko 5

而不是sprintf和vsprintf,你想使用:

snprintf(buffer, buffer_size, fmt_string, args, ...);
vsnprintf(buffer, buffer_size, fmt_string, valist);
Run Code Online (Sandbox Code Playgroud)

而不是strcpy,strncpy,strcat和strncat,你想要我们:

strlcpy(dest, src, dest_size);
strlcat(dest, src, dest_size);
Run Code Online (Sandbox Code Playgroud)

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

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


Jon*_*ler 5

另请参阅:SO 327980

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

例如,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);
Run Code Online (Sandbox Code Playgroud)

不幸的是,MSDN说接口vsnprintf_s()是:

int vsnprintf_s(
   char *buffer,
   size_t sizeOfBuffer,
   size_t count,
   const char *format,
   va_list argptr 
);
Run Code Online (Sandbox Code Playgroud)

参数

  • buffer - 输出的存储位置。
  • sizeOfBuffer - 输出缓冲区的大小。
  • count - 要写入的最大字符数(不包括终止 null)或 _TRUNCATE。
  • 格式 - 格式规范。
  • argptr - 指向参数列表的指针。

请注意,这不仅仅是类型映射的问题:固定参数的数量不同,因此是不可调和的。我也不清楚(大概标准委员会也不清楚)同时拥有“sizeOfBuffer”和“count”有什么好处;它看起来像是两次相同的信息(或者,至少,通常会使用两个参数的相同值编写代码)。