如何确定snprintf dest缓冲区大小

时间:2014-09-04 18:20:17

标签: c

由于sprintf会导致一些缓冲区溢出,我需要在项目中将所有sprintf更改为snprintf。但是我遇到了一些麻烦:

void foo( char *a, uchar *string)
{
    sprintf(string, 'format', src_str);
}

问题是当目标字符串是函数的参数时,如何在我们更改为snprintf之后决定缓冲区大小或字符串的最大长度。

3 个答案:

答案 0 :(得分:2)

如果您可以自己分配目标缓冲区,则可以使用strlen()检查源字符串的长度,以防它为null-terminatd并为其分配足够大的缓冲区并终止null -字符。您也可以直接使用asprintf(如果可用)。 如果没有该选项,则必须将目标缓冲区的大小作为参数传递,因为如果只有指向它的指针,则无法从函数内部可靠地确定其大小(除非目标缓冲区始终在唯一可识别的方式)。

答案 1 :(得分:1)

调用_scprintf(...)会告诉你字符串的大小,而不是实际使用缓冲区。

然后分配该大小的缓冲区,并调用snprintf。

答案 2 :(得分:0)

如果您无法使用正确的参数调用sprintf,则只需为snprintf更改snprintf即可获得任何好处。您的foo函数还需要额外的参数,就像snprintf需要额外参数sprintf一样。由于数组在用作函数的参数时会衰减为指针,因此任何大小的信息都会丢失。

如果你在整个程序中调用foo数百次,这可能会很麻烦,但是如果你想确保避免缓冲区溢出,你需要确保在数组上运行的任何函数完全了解它们的大小。

如果您正在使用GCC或clang,您可以通过将其原型更改为 1 foo函数上添加弃用警告:

void __attribute__((deprecated)) foo(char *a, uchar *string);

然后,您可以创建一个新功能,例如foo_n,其中包含大小的额外参数。编译代码时,GCC会针对函数foo的每次使用发出警告,因此您知道将其替换为foo_n

1。在{/ em>参数列表之后,__attribute__((deprecated))部分可能会>,但clang似乎接受了它,如上所示。