はじめに
- これまでの学習に続いて、今回は文字列の基本的な操作について学んだ結果をまとめてみました。
- 【C】初めてのC言語(1. Hello world)
- 【C】初めてのC言語(2. 四則演算とフォーマット指定子)
- 【C】初めてのC言語(3. ポインタ)
- 【C】初めてのC言語(4. 構造体)
- 【C】初めてのC言語(5. 関数)
- 【C】初めてのC言語(6. 配列)
- 【C】初めてのC言語(7. for文)
- 【C】初めてのC言語(8. 2次元配列)
- 【C】初めてのC言語(9. 関数のプロトタイプ宣言)
- 【C】初めてのC言語(10. 構造体配列)
- 【C】初めてのC言語(11. ヘッダファイル)
- 【C】初めてのC言語(12. 3つのからくり構文+ポインタ演算)
- 【C】初めてのC言語(13. メモリを扱う標準関数)
- 【C】初めてのC言語(14. ヒープの利用)
- 【C】初めてのC言語(15. sizeofの注意点)
- 【C】初めてのC言語(16. 文字列の基本)
- 【C】初めてのC言語(17. 文字列リテラル)
- 【C】初めてのC言語(18. 文字列の受け渡し)
学習環境
- 今回はpaiza.ioのC言語のエディタを使いました。
終端文字とバッファオーバーフロー(オーバーラン)
- 以下のように終端文字「\0」を上書きしてしまうと、
printf
関数は「\0」が現れるまで探し続けることになります。 - そのため、配列として確保していない領域(※100バイト目以降)にもアクセスしようとして、バッファオーバーフローを引き起こしてしまう可能性があります。
- paiza.ioの環境ではバッファオーバーフローは発生しませんでしたが...
Main.c
#include <stdio.h>
int main(void){
char str[100] = "Hello";
str[5] = '!'; // 終端文字「\0」が失われてしまう!
printf("%s\n", str);
return 0;
}
バッファオーバーフローを起こす例
- 以下のコードでは256バイトのバッファ
buff
を用意して、gets
関数で標準入力を受け取ってbuff
に読み込みます。-
gets
関数は、読み込んだ文字列の末尾に終端文字「\0」を加えます。
-
- この時、
gets
関数は読み込むバイト数に制限が無いため、256バイトを読み込んでも終端文字が現れないとバッファオーバーフローが発生します。- このような事故を防ぐため、現在では標準入力を受け取る場合は
fgets
関数を利用します。
- このような事故を防ぐため、現在では標準入力を受け取る場合は
- また、paiza.io上で以下のコードを実行すると、
warning: the 'gets' function is dangerous and should not be used.
というwarningが発生しますが、これは2011年に改訂されたC11規格以降の標準Cライブラリにおいてgets
関数が廃止されたことが原因です。- @SaitoAtsushi さん、コメント欄にてご指摘および丁寧な解説を頂き、ありがとうございました。
Main.c
#include <stdio.h>
int main(int argc, char *argv[])
{
char buff[256];
gets(buff); // 256バイトを超えても終端文字が現れないとバッファオーバーフローが発生する!
printf("入力値:%s\n", buff);
return 0;
}
参考URL
-
スッキリわかるC言語入門 第2版
- p.413~p.416
-
バッファオーバーラン - Wikipedia
- 「C言語特有の例」を参照。
- gets - Wikipedia