由于sprintf会导致一些缓冲区溢出,我需要在项目中将所有sprintf更改为snprintf。但是我遇到了一些麻烦:
void foo( char *a, uchar *string)
{
sprintf(string, 'format', src_str);
}
问题是当目标字符串是函数的参数时,如何在我们更改为snprintf之后决定缓冲区大小或字符串的最大长度。
答案 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似乎接受了它,如上所示。