C语言 使VLA略长于argv[1]是否安全?



示例代码,将argv[1]视为文件路径,将其扩展名替换为.png,如果没有找到则将其附加:

#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
if (argc != 2)
return 1;
char *lastdot = strrchr(argv[1], '.');
size_t len = lastdot ? (lastdot - argv[1]) : strlen(argv[1]);
char outpath[len + sizeof(".png")];
// ^ this is the important part
memcpy(outpath, argv[1], len);
memcpy(outpath + len, ".png", sizeof(".png"));
printf("%sn", outpath);
}

我这里主要关心的是argv[1]可能只是小到不会引起操作系统本身的错误,但随后".png"串联添加的额外4字节将导致分配VLA时堆栈溢出?

问题是,我不太确定argv成员或VLA成员的大小是如何限制的。

显然,PATH_MAX等常量对于静态数组大小是不可信的,所以它要么是这个,要么是malloc

您的担心是真实的:C标准中没有任何内容保证您的程序可用的堆栈空间足以为非常长的命令行参数加上4个字节分配一个大的VLA。在实践中,在现代操作系统上,堆栈空间通常至少为1兆字节,命令行参数被限制在大约100 KB…所以你应该很安全。

还要注意,有些编译器根本不支持vla,因此从堆中分配是一种更可移植的方法。

顺便说一下,你可以修改你的程序来完全避免这个问题:

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc != 2)
return 1;
char *lastdot = strrchr(argv[1], '.');
int len = lastdot ? lastdot - argv[1] : strlen(argv[1]);
printf("%.*s.pngn", len, argv[1]);
return 0;
}

相关内容

  • 没有找到相关文章

最新更新