前回の記事の続き。

CppCheckでC言語/C++のメモリリーク(解放漏れ)を静的解析で検出する

Cppcheckを利用して、バッファオーバーランを検出したい。

バッファオーバーランとは、バッファオーバーフロー、メモリ破壊、メモリ不正番地アクセスとも言われていて、組込みエンジニアを一瞬のうちに恐怖に戦かせる魔法のぽぽぽぽーんだ。

いろんなパターンのメモリ破壊をCppCheckで検出できるか、遊んでみた。

メモリ解放したあとにアクセスしてしまうパターン

void buffer\_over\_run(void)
  
{
  
char *p;

p = (char *)malloc(1);
  
free(p);

*p = 3;
  
}
$ cppcheck -enable=all memory_leak.c
  
Checking memory_leak.c
  
[memory_leak.c:21]: (error) Dereferencing 'p' after it is deallocated / released
  
[memory_leak.c:21]: (error) Uninitialized variable: p
  
Checking usage of global functions..

関係ないメモリ領域に勝手にデータを書き込んでしまう領域破壊パターン

void buffer\_over\_run(void)
  
{
  
char *p;

p = (char *)malloc(1);
  
memset(p,"c",2);
  
free(p);
  
}
$ cppcheck -enable=all memory_leak.c
  
Checking memory_leak.c
  
[memory_leak.c:11]: (error) Buffer is accessed out of bounds.
  
Checking usage of global functions..

配列で宣言した領域をオーバーするパターン

void buffer\_over\_run(void)
  
{
  
char c[5];
  
c[5] = 3;
  
}
$ cppcheck -enable=all memory_leak.c
  
Checking memory_leak.c
  
[memory_leak.c:8]: (style) Variable 'c' is assigned a value that is never used
  
[memory_leak.c:21]: (error) Array 'c[5]' accessed at index 5, which is out of bounds.
  
Checking usage of global functions..

インクリメントすることで、知らないうちに不正番地アクセス

void buffer\_over\_run(void)
  
{
  
char *p;

p = (char *)malloc(1);

p++;
  
*p = 1;
  
printf(“%x”,p);

free(p);

}
$ cppcheck -enable=all memory_leak.c
  
Checking memory_leak.c
  
Checking usage of global functions..

あれ、検出してくれない・・・・そして

$ ./a.exe *p = 800482a8 Aborted (コアダンプ)

ちょ・・・・なんとかしてよ。

おまけ

ネットを徘徊していたら、メモリ破壊についての面白い詩をみつけた。

直接引用はチョッと気が引けるので、参考リンクとしてリンク貼っておく。

諸君、私はC言語が好きだ