C言語の基礎
void save(const char *input) {
char name[8];
strcpy(name, input);
printf("%s\n", name);
}上の関数 save に、8文字の文字列 "ABCDEFGH" を渡した。起こることとして正しいものはどれか。
- A終端の '\0' を含めて9バイトが書き込まれ、name の外側の1バイトを壊す(未定義動作)
- Bちょうど8文字なので name に収まり、ABCDEFGH と正しく表示される
- Cstrcpy が name の大きさに合わせて7文字に切り詰め、最後の要素に終端の '\0' を入れる
答えと解説を見る
正解:A. 終端の '\0' を含めて9バイトが書き込まれ、name の外側の1バイトを壊す(未定義動作)
文字列 "ABCDEFGH" は、終端の '\0' を含めると9バイトです。strcpy は書き込み先の大きさを知らずに '\0' までをすべて写すので、8バイトの name の外側に1バイトはみ出して書き込みます(バッファオーバーフロー)。はみ出した分はスタック上のほかの変数や戻り先の番地を壊すことがあり、外から長い入力を与えて任意のコードを実行させる攻撃にも使われます。snprintf(name, sizeof name, "%s", input) のように、書き込む大きさを指定できる関数を使って防ぎます。
- A. 正しい。9バイト目の '\0' が配列の外に書き込まれます。
- B. 8文字の文字列には、終端の '\0' を含めて9バイトが必要です。
- C. strcpy は書き込み先の大きさを知らないので、切り詰めることはしません。