0

Robert C Seaford による C および C++ の安全なコーディングの本を読んでいます。

int main(int argv, char* argv[]) {
  char a[16];
  char b[16];
  char c[32];

  strcpy(a, "0123456789abcdef");
  strcpy(b, "0123456789abcdef");
  strcpy(c, a);
  strcat(c, b);
  printf("a = %s\n", a);
  retrun 0;
}

3 つの文字配列の静的宣言は、null 終了文字用のストレージを割り当てることができません。

その結果、最初strcpy()は配列の末尾を超えてヌル文字を書き込みます。

コンパイラが記憶域を割り当てる方法によっては、このヌル バイトがstrcpy()次の行で上書きされる場合があります。この場合、aは 20 文字の配列をb指し、 は 10 文字の配列を指します。

私の質問は、著者の平均配列aに 20 文字が含まれ、配列bが 10 文字を指している方法を教えてください。

4

1 に答える 1

4

「10」は 16 進数の 0x10 (16) であり、「20」は 16 進数の 0x20 (32) であると想定する必要があります。

とにかく重要なのは、文字列操作コードが、配列に実際に割り当てられた文字数ではなく、null 文字の位置によって文字列の長さを決定することです。メモリが次のように割り当てられている場合:

<-------a------><-------b------><--------------c-------------->

すると1回目以降strcpyの記憶はこんな感じ。(null を示すために ! を使用します)。

<-------a------><-------b------><--------------c-------------->
0123456789abcdef!

すると2秒後strcpy、メモリはこんな感じ。

<-------a------><-------b------><--------------c-------------->
0123456789abcdef0123456789abcdef!

strcpy操作は、書き込みが想定されている配列をオーバーフローさせ、隣接するメモリを使用しています。これは非常に悪い習慣です。また、文字列のように操作する関数aには 32 (0x20) 文字が表示され (null はカウントされません) b、文字列のように操作する関数には 16 (0x10) 文字が表示されます (null はカウントされません)。各配列に 15 文字分のメモリしか割り当てていません (null は数えません)。

これがクラッシュしないという事実は、メモリがどのように配置されているかの偶然です。スペースよりも多くの文字を配列に書き込み、書き込まれている隣接するメモリが書き込み可能でない場合、クラッシュします。

そしてもちろん、安全なコーディングについて読んでいるので、他の何かを上書きしているという事実は、入力がどれほど信頼されているか、そして正確に何が上書きされるかによって、重大なセキュリティ上の問題になる可能性があります.

于 2013-04-10T11:35:52.420 に答える