我有两个字符串,两个字符串都可以由用户设置,例如
char *command = "vim $VAR";
char *myVar = "/tmp/something";
我想使用*command
*myVar
执行$VAR
。
我尝试将它们连接为环境变量(例如(伪代码)system("VAR=" + *myVar + "; " + *command)
,但是用户控制myVar
因此这将是非常不安全和错误。
我考虑过对空格进行标记以直接替换$var
并将结果传递给exec()
,但是担心正确地标记shell命令参数会让人感到尴尬。
我认为解决方案是通过执行类似system()
的操作来模拟exec("sh", "-c", command, "--argument", "VAR", myVar)
,但我无法在sh / dash / bash手册页中看到任何内容以允许设置环境变量就这样。
编辑:我刚看到execvpe(),它有一个参数用于设置key = value字符串的环境变量。使用不受信任的输入值是否安全?
我该如何安全地做到这一点?
答案 0 :(得分:2)
答案 1 :(得分:2)
正如Ben指出的那样,command
可能在运行时加载。
我认为最好的方法是标记command
,而不是标记myVar
。然后,您可以找到command
中的哪个词$VAR
,并将其替换为myVar
的值。然后,您可以按照以下方式使用posix_spawnp
。
如果您真的希望command
成为任意shell命令,那么您唯一的选择是在将myVar
分配给环境变量之前将其转义。否则shell将扩展空格和其他特殊字符,无论你如何设置它。
第三个选项是确保命令为vim "$VAR"
而不是vim $VAR
。在这种情况下,您可以使用setenv
将其分配给环境,然后调用system
,然后在之后取消设置。
案例command
中的旧答案是静态的:
看起来你真正想做的是
extern char *environ[];
posix_spawnp(NULL, "vim", NULL, NULL, (char*[]){"vim", myVar, NULL}, environ);
wait(NULL);
即。 exec vim直接没有任何shell,myVar
作为第一个参数。
答案 2 :(得分:2)
您可以对myVar
的值执行一些字符串替换 - 将其放在单引号内,并用四个字符的字符串'
替换所有单引号(字符'\''
) 。如果你没有犯一个实现错误,那就很安全但很安全。如果可能,use a library that does it for you。
如果你的程序是单线程的,我推荐一个不涉及繁琐引用的不同解决方案。你谈到设置环境变量......好吧,就这样做:make VAR
一个环境变量。
setenv("VAR", myVar, 1);
system(command);
unsetenv("VAR")
我省略了错误检查,我认为程序中的其他地方不需要VAR
(如果是,这个解决方案变得更加繁琐,因为你需要记住旧值)。
如果要对命令运行的环境进行精细控制,可以在system
,fork
(或execve
)和{{execvpe
之上重新实现waitpid
。 1}},或posix_spawn
(或posix_spawnp
)和waitpid
之上。这是更多的努力,但你获得了灵活性。
请注意,除了在C程序中对"vim $VAR"
执行字符串替换之外,您采用的任何解决方案都必须是vim "$VAR"
而不是vim $VAR
。这是因为在shell语法中,$VAR
仅表示“变量VAR
的值”,只有当它在双引号内时 - 否则,$VAR
表示“取VAR
的值,将其拆分为单词,并将每个单词扩展为文件名通配符模式“。
答案 3 :(得分:-2)
怎么样:
fork
(如果模仿system
或spawn
,请跳过此操作exec
)setenv("VAR", myVar)
exec
" sh -c" +命令