当我尝试在Ubuntu上编译fprintf(stderr,Usage)
,我得到这个错误:
error: format not a string literal and no format arguments [-Werror=format-security
但是当我在编译成功的其他Linux发行版(RedHat,Fedora,SUSE)上编译时。
任何人有一个想法?
你应该使用fputs(Usage, stderr);
如果您没有格式化,则不需要使用fprintf。 如果你想使用fprintf,使用fprintf(stderr, "%s", Usage);
Ubuntu上的默认编译器标志包括-Wformat -Wformat-security
,这是什么给了这个错误。
该标志被用作防范引入安全相关错误的预防措施,想象如果您以某种方式执行此操作,会发生什么情况:
char *Usage = "Usage %s, [options] ... "; ... fprintf(stderr, Usage);
这与fprintf(stderr, "Usage %s, [options] ... ]");
这是错误的。
现在Usage
字符串包含一个格式说明符%s
,但是您不会将该参数提供给fprintf
,导致未定义的行为,可能会导致程序崩溃或被攻击。 如果您传递给fprintf的字符串来自用户输入,则这更为相关。
但是,如果你做fprintf(stderr,"%s", "Usage %s, [options] ... ]");
没有这样的问题。 2. %s
不会被解释为格式说明符。 gcc可以对此提出警告,并且默认的Ubuntu编译器标志使其成为编译器错误。
使用fputs(Usage)
或fprintf(stderr, "%s", Usage)
。 将消息字符串传递给printf
family函数的习惯是很危险的,因为除非知道不包含格式说明符,否则将解释字符串中的任何可能的格式说明符并导致未定义的行为(因为它们没有与它们相对应的参数),这几乎总是会转化为安全漏洞。