Code Fix

中級

Segmentation fault(strcpyによるバッファオーバーフロー)

コピー先のchar配列より長い文字列をstrcpyでコピーすると、確保した領域を超えて書き込みが起こります。隣接するメモリを破壊し、クラッシュにつながります。

エラーメッセージの読み方

Segmentation fault
(エラーメッセージなし)
これはプログラム自身の出力ではありません。プログラムは何も言わずに落ちています
Segmentation fault
シェルが検知した異常終了の種類 — OSが「不正なメモリアクセス」などを検出しプロセスを強制終了させました
見つけ方
このメッセージだけでは行番号すら分かりません。原因はコードを読んで特定するしかありません

このエラーが出る典型パターン

パターン1

 1  #include <stdio.h>
 2  #include <string.h>
 3  
 4  int main(void) {
 5      char buf[8];
 6      strcpy(buf, "AAAAAAAAAAAAAAAAAAAAAAAA");
                                 ^
 7      printf("%s\n", buf);
 8      return 0;
 9  }
Segmentation fault

buf[8]は8バイトしか確保されていません。それより長い文字列をstrcpyでコピーすると、確保した領域を超えて書き込みが起こり、隣接するメモリ(戻り先のアドレスなど)を破壊してクラッシュします。

直し方: "AAAAAAAAAAAAAAAAAAAAAAAA""hi" にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  #include <stdio.h>
 2  #include <string.h>
 3  
 4  int main(void) {
 5      char name[6];
 6      strcpy(name, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
                                   ^
 7      printf("%s\n", name);
 8      return 0;
 9  }
Segmentation fault

確保したバッファのサイズより長い文字列を渡すと、strcpyはコピー先の限界を無視してそのまま書き込み続けます。

直し方: "ABCDEFGHIJKLMNOPQRSTUVWXYZ""Al" にします。

この問題を解いてみる →

パターン3

 1  #include <stdio.h>
 2  #include <string.h>
 3  
 4  int main(void) {
 5      char code[4];
 6      strcpy(code, "1234567890123456789012");
                                 ^
 7      printf("%s\n", code);
 8      return 0;
 9  }
Segmentation fault

小さいバッファほど、少し長い文字列を渡しただけでも重要な領域まで書き潰しやすくなります。安全に使うにはstrncpyや十分なサイズのバッファ確保が必要です。

直し方: "1234567890123456789012""AB" にします。

この問題を解いてみる →

よくある誤解

「多少長くてもコピーはできる」というのは大きな誤解です。strcpyはコピー先のサイズをまったく知らないため、渡された文字列の長さだけ書き込もうとします。書き込んだ先が戻り先のアドレスなど重要な情報を破壊すると、その場でクラッシュします。安全に使うにはstrncpyや十分なバッファサイズの確保が必要です。

まとめ

Segmentation fault(strcpyによるバッファオーバーフロー)は中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)