1

数日前にバッファ オーバーフローの検出について質問しました ( sprintf バッファ グローバル データ オーバーフロー - Windows の検出方法)。問題は、標準機能の cppcheck によってのみ解決できます (セキュア _s バージョンではありません)。

私はより深く行き、コードをから変更しました

#include <stdio.h>
char buffer[2];
void main()
{
  sprintf(buffer,"12345");
}

#include <stdio.h>
void f( char *b )
{
   sprintf(b,"12345");
}

char buffer[2];
void main()
{
   f( buffer );
}

Visual Studio 2012 /RTC は、実行時にスタック割り当てバッファー オーバーフローを処理できますが、グローバル データは検出されません。

cppcheck を使用して詳細な分析を行うことはできないと思いますが、この問題は cppcheck-1.64 では検出されません。さらに、 AddressSanitizer ( Windows ) で clang を使用しようとしましたが、良い結果も得られませんでした。

Windows でこのような問題を防ぐことはできますか (できれば無料のツール)。

4

3 に答える 3

0

これらは、プログラムでグローバル変数を避けるべき理由の一部です。グローバル変数 (データ セグメント) の破損について報告するようなツールは存在しないと思います。スタックおよびヒープ セグメント メモリの破損/オーバーランを検出するための優れたツール セットがあります。

したがって、このようなシナリオを回避するには、プログラムでのグローバル変数の使用を最小限に抑える必要があります。それが不可能な場合は、これらを使用しながら、自分で防御的プログラミング アプローチを使用するようにしてください。これを説明するために、プログラムを次のように書き直すと、プログラムでグローバル メモリが破損するシナリオを回避できます。

#include <cstdio>

char buffer[2];


void f( char *b, size_t sz)
{
 // Now we have protected our global variable from overrun by
 // using the size information passed by caller.So even though
 // client "12345" has been passed, it would just copy 12.
 strncpy(b,"12345",sz);
}


int main() {
  size_t tmp = sizeof(buffer)/sizeof(buffer[0]);
  f( buffer, tmp);
  return 0;
}
于 2014-03-31T11:03:39.530 に答える
0

を使用する代わりに、 を使用sprintfすることを検討してくださいsnprintf。そのプロトタイプは (ヘッダーに含まれていますstdio.h) -

int snprintf(char *str, size_t size, const char *format, ...);

sizeこの関数は、終端の null バイトを含む最大バイト数を が指すバッファに書き込みますstr。したがって、関数fシグネチャを変更して、バッファーの長さも取得する必要があります。また、署名はmain次のいずれかである必要があることに注意してください -

int main(void);
int main(int argc, char *argv[]);

次の変更を提案します-

#include <stdio.h>

void f(char *b, size_t len) {
   sprintf(b, len, "12345");
}

char buffer[2];
int main(void) {
   f(buffer, sizeof buffer);
   return 0;
}
于 2014-03-31T11:01:34.257 に答える