c array - warning:format不是字符串文字

big*_*igl 40 c compiler-warnings

我正在尝试学习C,但我已经遇到了问题.我认为它是微不足道的,但我需要知道它.我已经写了:

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

int main() 
{
    char str_a[20];

    strcpy(str_a, "Hello, world!\n");
    printf(str_a);
}
Run Code Online (Sandbox Code Playgroud)

一旦我尝试使用以下命令编译它:gcc -g -o char_array2 char_array2.c我收到错误说:

char_array2.c: In function ‘main’:
char_array2.c:9:2: warning: format not a string literal and no format arguments [-Wformat-security]
Run Code Online (Sandbox Code Playgroud)

有人可以帮忙吗?

MBy*_*ByD 68

使用printf时,格式字符串最好是字符串文字而不是变量:

printf("%s", str_a);
Run Code Online (Sandbox Code Playgroud)

  • @CiroSantilli六四事件法轮功包卓轩 - 不是必需的,因为API本身允许传递变量字符串,但使用字符串文字要好得多,因为使用碰巧有格式说明符的变量字符串会导致错误(主要是内存)从安全的角度来看,这是一个明确而简单的漏洞(如果攻击者可以控制输入) (7认同)
  • 更好还是需要?为什么? (3认同)

Bla*_*ear 18

只是为了给其他答案添加一些东西,你最好这样做是因为(很久以前)人们写了这样的printf,黑客找到了一种读取和写入堆栈的方法,更多的是这里.
例如,一个像这样的简单程序:

blackbear@blackbear-laptop:~$ cat format_vul.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char text[1024];
    static int test_var = -1;

    if(argc < 2) {
        printf("Use: %s <input>\n", argv[0]);
        exit(-1);
    }

    strcpy(text, argv[1]);

    printf("The correct way:\n");
    printf("%s", text);

    printf("\nThe wrong way:\n");
    printf(text);

    printf("\n[*]: test_var @ %8p = %d ( 0x%x )\n", &test_var, test_var, test_var);
}
blackbear@blackbear-laptop:~$ ./format_vul AAAA
The correct way:
AAAA
The wrong way:
AAAA
[*]: test_var @ 0x804a024 = -1 ( 0xffffffff )
Run Code Online (Sandbox Code Playgroud)

可用于将test_var的值从0xffffff更改为其他值,如0xaabbccdd:

blackbear@blackbear-laptop:~$ ./format_vul $(printf "\x24\xa0\x04\x08JUNK\x2
5\xa0\x04\x08JUNK\x26\xa0\x04\x08JUNK\x27\xa0\x04\x08").%8x.%8x.%8x.%8x.%8x.
%8x.%8x.%8x.%8x.%110x.%n%239x%n%239x%n%239x%n
The correct way:
$?JUNK%?JUNK&?JUNK'?.%8x.%8x.%8x.%8x.%8x.%8x.%8x.%8x.%8x.%110x.%n%239x%n%239
x%n%239x%n
The wrong way:
$?JUNK%?JUNK&?JUNK'?.bfffefec.  154d7c.  155d7c.  155d7c.      f0.      f0.b
ffff4a4.       4.       4.                                                  
                                                     174.                   


                                                50415243                    


                                               50415243                     


                                              50415243
[*]: test_var @ 0x804a024 = -1430532899 ( 0xaabbccdd )
Run Code Online (Sandbox Code Playgroud)


Mar*_*lon 6

该警告是由编译器希望第一个参数为printf字符串文字引起的.它要你写这个:

printf("%s\n", str_a);
Run Code Online (Sandbox Code Playgroud)

这是因为第一个参数printf是格式字符串.之后传递格式参数.

注意:您实际上可以使用变量作为格式字符串,但您可能不应该这样做.这就是编译器发出警告而不是错误的原因.