c - 可以在字符串中间将空字符传递给 argv 吗?
问题描述
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
write(STDOUT_FILENO, argv[1], atoi(argv[2]));
return 0;
}
以下输出(在 Ubuntu 上以 bash 运行)显示 'xyz' 未在 argv 中传递。我想确保这是操作系统的限制,而不是外壳的限制。所以不可能在 argv 的字符串中间传递一个空字符。有人可以确认吗?谢谢。
$ ./main.exe $'abc\000xyz' 7 | xxd
00000000: 6162 6300 3700 53 abc.7.S
解决方案
所有程序都是从exec
调用开始的,尽管有操作系统实现,让我们看看 POSIX 标准对exec
函数的描述。
int execve(const char *path, char *const argv[], char *const envp[]);
argv
是传递给程序的参数,envp
是环境变量。
argv 和 environ 数组均由空指针终止。终止 argv 数组的空指针不计入 argc。
参数 argv 是指向以空字符结尾的字符串的字符指针数组。
因此,很容易得出结论:
- 可以将空(零长度)字符串传递给
argv
NULL
string 不能传递给 argv,它将终止argv
,并丢弃所有后续参数。- 中的任何字符串
argv
都不能包含\x0
字符,\x0
将终止当前参数字符串。
解释运行时发生了什么
python -c 'print "\x30\x00\x31"' | xargs --null prog
尝试:
python -c 'print "\x30\x00\x31"' | strace -f xargs --null echo
我们可以找:
...
...
...
read(0, "0\0001\n", 4096) = 4
...
...
...
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f09f46d9850) = 21232
strace: Process 21232 attached
...
...
...
[pid 21232] execve("/bin/echo", ["echo", "0", "1\n"], 0x7ffe5ccd7638 /* 74 vars */ <unfinished ...>
它表明在xargs
调用. 不是由 shell 完成的,不是由 OS、libc 完成的,而是\x0
prog
xargs
推荐阅读
- javascript - 在反应中显示两个日期
- android - 片段中的 initUI() 在图像视图中给出错误
- python - Pytorch:如何创建不来自衍生品的更新规则?
- php - 下载属性在 chrome 上不起作用
- python-3.x - 有没有办法从数据框中提取构造数据框的代码?
- php - 如何使用 Composer 安装最新的 PHP 次要分支版本
- javascript - Else 语句不会触发修复 d3.js 中的节点
- android - 在 RecyclerView 适配器点击事件中使用 fragmentManager
- css - 为什么 Angular 会自动添加不必要的标签?
- visual-studio-code - Visual Studio Code Nuget 自动完成失败,原因:无法验证第一个证书