すべての警告を有効にしてコンパイルするのが良いスタートです:
chqrlie@mac ~/dev/stackoverflow > clang -O3 -std=c11 -Weverything -lm -o 35996676 35996676.c
35996676.c:9:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
main(int argc, char *args[])
^
35996676.c:12:19: warning: implicit conversion changes signedness: 'unsigned int' to 'int' [-Wsign-conversi
a.ii = a.jj = 0xdeadbeef;
~ ^~~~~~~~~~
35996676.c:15:5: warning: implicitly declaring library function 'sprintf' with type 'int (char *, const cha
sprintf(a.buff2, "ABCDEFGH");
^
35996676.c:15:5: note: include the header <stdio.h> or explicitly provide a declaration for 'sprintf'
35996676.c:9:10: warning: unused parameter 'argc' [-Wunused-parameter]
main(int argc, char *args[])
^
35996676.c:9:22: warning: unused parameter 'args' [-Wunused-parameter]
main(int argc, char *args[])
^
35996676.c:7:3: warning: no previous extern declaration for non-static variable 'a' [-Wmissing-variable-dec
} a;
^
6 warnings generated.
これらを簡単なパッチで修正し、明らかなバグを追加します:
#include <stdio.h>
#include <string.h>
static struct A {
char buff1[8];
unsigned int jj;
char buff2[8];
unsigned int ii;
char buff3[8];
} a;
int main(void) {
// Set intermediate fields to known flag value
a.ii = a.jj = 0xdeadbeef;
// Write 8 char string into 8 byte buffer - null will overflow into neighboring int field. ERROR
sprintf(a.buff1, "ABCDEFGH");
strcpy(a.buff2, "ABCDEFGH");
sprintf(a.buff3, "%s", "ABCDEFGH");
return 0;
}
警告なしでコンパイルされ、単純化された静的解析で発見されるべき明白なバグにsprintf
もかかわらずです。strcpy
gcc
with-Wall -W -Wextra
も何も問題はありません。
snprintf
の代わりにを使用することをお勧めしますsprintf
が、それで問題が回避されるわけではありませんstrcpy
。strcpy
一般的なケースでは安全ではありませんが、文字列リテラルをソースとして使用すると、コンパイラは間違いなく文句を言うはずです。
Frama-c は、http://frama-c.com/からオープン ソースで入手できる強力なソース コード分析フレームワークです。