看看这个易受攻击的片段:
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...
好吧,实际上似乎"%(number)\ $ s"试图将(数字)参数解释为字符串,查看堆栈的上方,我遇到了我的环境变量.在任何地方都使用这种格式字符串,特别是使用好奇的"\ $"?我找不到任何参考资料.
最后,通过优化编译启用它会导致:
*** invalid %N$ use detected *** asd zsh: abort ./test "asd %46\$s"
我以前从未见过这样的错误.它从何而来?
(我使用的是Gentoo Linux/GCC 4.8.2/glibc 2.18)
当然,它在手册页中提到过,就像你期望的那样.它似乎来自Single Unix规范(即不是C99).
它用于国际化,当你需要交换各种信息的顺序以适应翻译.该数字是一个参数索引:
人们也可以明确地指定的参数被在每次在需要的参数,通过写入地方
"%m$"
代替'%'
和"*m$"
代替'*'
,其中十进制整数m表示在期望的参数的自变量列表中的位置,从1开始索引
所以在一个更明智的计划中,这个:
printf("%2$d %1$d", 1, 2);
版画
2 1
启用优化后,可能会使编译器对代码执行更重量级的分析,以便它可以"了解"有关实际参数列表的更多信息并生成更好的错误.