【问题标题】:warning: format string contains '\0' within the string body [-Wformat]警告:格式字符串在字符串主体 [-Wformat] 中包含“\0”
【发布时间】:2016-01-27 19:51:16
【问题描述】:

我的代码中有一个使用 awk 的 system() 命令。我不知道如何解决\x00 十六进制值的问题。显然他们需要以不同的方式终止,但这超出了我所知道的范围。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {

    char command[128];
    snprintf(command, sizeof(command), "awk '{ gsub (/\xAB\x00\x00\xBC/,\"\xBC\x00\x00\xAB\") ; print }' %s", argv[1]);
    system(command);

}

警告/错误:

>  test.c:8:56: warning: format string contains '\0' within the string body [-Wformat]
>  snprintf(command, sizeof(command), "awk '{ gsub (/\xAB\x00\xBC/,\"\xBC\x00\x00\xAB\") ; print }' %s", argv[1]);
>  /usr/include/secure/_stdio.h:57:62: note: expanded from macro 'snprintf'
>  __builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)
                                                              ^
  1 warning generated.
  sh: -c: line 0: unexpected EOF while looking for matching `''
  sh: -c: line 1: syntax error: unexpected end of file

抱歉,如果之前有人问过这个问题,我在搜索如何解决这个问题时找不到任何相关信息,谢谢...

【问题讨论】:

  • 它可以从命令行运行,尽管我不需要像 C 中那样转义 "
  • \\x替换\x的每个实例。
  • 我在终端awk '{ gsub (/\xAB\x00\x00\xBC/,"\xBC\x00\x00\xAB") ; print }' file这样使用
  • C 字符串中不能有空字符。 \x00 表示空字符,与 \0 相同。但是,如果您对反斜杠进行转义,则可以将 \x00 放入您的 C 字符串中(如反斜杠、ex、零、零,而不是空字符)。

标签: c string system quoting


【解决方案1】:

考虑 C 字符串文字 "\xAB"。此字符串文字包含一个字节,而不是 4 个。类似地,"\x00" 是包含一个字节的字符串文字,该字节为空字节。 Clang 会警告您这一点,因为空字节结束 C 字符串 - 它后面的每个字符都将被库函数(例如 snprintf)忽略。

在您的 awk 代码中,有一个 awk 字符串文字,用双引号括起来。你写了…\"\xBC\x00\x00\xAB\"…,在双引号前加上反斜杠,否则双引号将被解释为结束 C 字符串文字。同样,如果您想在 awk 代码中(更准确地说,在 shell 命令中)以反斜杠结尾,则需要在其前面再添加一个反斜杠。换句话说,您需要将反斜杠加倍。

snprintf(command, sizeof(command), "awk '{ gsub (/\\xAB\\x00\\x00\\xBC/,\"\\xBC\\x00\\x00\\xAB\") ; print }' %s", argv[1]);

请注意,您的程序还有另一个引用问题:它将其参数解释为 shell 代码的 sn-p,而不是文件名。仅当文件名不包含任何 shell 特殊字符时,两者才会重合。例如,./your_program Jack.txt 可以使用,但./your_program "O'Leary.txt" 不行。要使其工作,您需要对参数进行按摩以保护 shell 特殊字符。

(另一个问题是您没有检查 snprintf 是否成功。它可能会溢出——您应该根据参数的长度动态分配必要的大小(如果参数包含特殊字符)。)

【讨论】:

  • 谢谢!对于建议,我将执行您提到的文件名检查。令人惊讶的是,运行一个 shell 命令最终会不会像开始时那么简单。
【解决方案2】:

C 字符串文字中的字符序列 '\''x''0''0' 表示单个 char,其数值为零。因此,由两个字符串文字"\x00""\0" 表示的char 数组具有相同的大小和内容:两个chars(包括终止符),均为零。当用作 C 字符串时,两者都等效于空字符串,因为索引零处的零字符用作字符串终止符。

您的编译器警告您传递给snprintf() 的字符串文字包含内部空字节(实际上它有两个),这可能会导致它没有按您的预期进行解释。如果您的意思是将字符串中的 \xhh 序列视为四个文字字符的序列,那么您必须将反斜杠加倍:

    snprintf(command, sizeof(command), "awk '{ gsub (/\\xAB\\x00\\x00\\xBC/,\"\\xBC\\x00\\x00\\xAB\") ; print }' %s", argv[1]);

【讨论】:

  • 非常感谢您的回答,这对我很有帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-01
  • 2022-11-22
相关资源
最近更新 更多