看看这个易受攻击的片段:
int main(int argc, char **argv) {
printf(argv[1], "bla");
return 0;
}
在没有优化的情况下进行编译会导致
./test "asd"
asd
./test "asd %s"
asd bla
./test "asd %0\$s"
asd %0$s
./test "asd %45\$s"
asd XDG_VTNR=7 <-- What the...
嗯,实际上好像&#34;%(数字)\ $ s&#34;尝试将(数字)参数解释为字符串,查看堆栈的上方,并且我遇到了我的环境变量。在任何地方都可以使用这种格式字符串,特别是使用好奇的&#34; \ $&#34; ?我找不到任何参考资料。
最后,通过优化进行编译会导致:
*** invalid %N$ use detected ***
asd zsh: abort ./test "asd %46\$s"
我之前从未见过这样的错误。它来自哪里?
(我使用的是Gentoo Linux / GCC 4.8.2 / glibc 2.18)
答案 0 :(得分:5)
当然,它是mentioned in the manual page,就像你期望的那样。它似乎来自Single Unix规范(即不是C99)。
它用于国际化,当你需要交换各种信息的顺序以适应翻译。该数字是参数索引:
还可以通过编写
开始索引"%m$"
而不是'%'
和"*m$"
而不是'*'
来明确指定在需要参数的每个地方采用哪个参数,其中十进制整数m表示所需参数的参数列表中的位置,从1
所以在一个更明智的计划中,这个:
printf("%2$d %1$d", 1, 2);
打印
2 1
启用优化后,可能会使编译器对代码执行更重量级的分析,以便它可以“更多地”了解实际参数列表并生成更好的错误。