我有以下代码从C中具有getopt()
的用户获取字符串:
#include <stdio.h>
#include <getopt.h>
#include "util.h"
int main(int argc, char *argv[]) {
if (argc == 1) {
usage(); // from util.h
return 0;
}
char *argument = NULL;
char ch;
while ((ch = getopt(argc, argv, ":f:"))) {
switch (ch) {
case 'f':
argument = optarg;
break;
}
}
// ... use `argument` with other stuff ...
}
这是安全的,还是我应该使用strcpy()
复制字符串到argument
?如果我不小心更改了argument
的内容,攻击者会更改环境变量之类的东西吗?
这是安全的,还是我应该使用
strcpy()
将字符串复制到参数中?
这样做是安全的,并且getopt()
被设计为这样使用。更一般地说,提供给main的程序参数被指定为属于程序的可写字符串。
请注意,一些getopt()
的实现,特别是GNU的,可能会重新排列argv
的元素。
如果我不小心改变了参数的内容,攻击者会改变环境变量之类的东西吗?
实参字符串和程序中的其他对象一样容易发生边界溢出错误。如果由于编程错误或其他原因,您的程序试图编写超出任何对象边界的内容,则该行为是未定义的。环境变量的修改是UB可能表现的无界空间中比较可信的成员之一。
但是,请注意,在这方面,创建参数的副本并没有帮助。您还必须避免超出任何此类副本的边界,以免触发UB,并具有相同的无界空间的可能表现。如果你想确保程序参数不能通过变量argument
修改,那么习惯做法是将其声明为指向const char
的指针,而不是指向(可修改的)char
的指针。这不会影响将optarg
的值赋给它。
是的,这是"安全"的。
argv
的内容由主机环境提供,并且在整个过程中属于您的进程。
Onargv
:
字符串是可修改的,任何修改都将持续到程序终止,尽管这些修改不会传播回宿主环境:例如,它们可以与strtok一起使用。
也就是说,特权进程,比如ps
实用程序,通常能够访问argv
的当前值。对敏感信息使用argv
是不明智的。
参见:在Unix上隐藏命令行参数的秘密和argv是否可以在运行时更改(而不是应用程序本身)以考虑安全问题。
Aside:getopt
返回一个int
。这个区别很重要,因为如果char
是无符号的,它就不能表示终止值:
如果已经解析了所有命令行选项,那么getopt()返回-1。
您应该使用int
可靠地测试此值,否则循环将无限继续。
int ch;
while (-1 != (ch = getopt(argc, argv, ":f:")))