質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.52%

【C言語】scanfでは何文字まで入力可能?

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 956
退会済みユーザー

退会済みユーザー

バッファオーバーフローを出そうと思って、以下のコードを実行したところ「a」を13文字入力するとプログラムが停止します。
12文字入力すると入力した文字がそのまま出力されますが、何故13文字入力するとプログラムが停止するのでしょうか?

#include <stdio.h>

int main(void)
{
    char str[1];
    scanf("%s", str);
    printf("%s", str);
    return 0;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+4

C言語でバッファオーバーフローが発生した場合の動作は未定義です。未定義な動作とは、どのような動作が起きるかはわからないことを意味します。OS、コンパイラ、コンパイル時のオプション、実行時の環境、OSを含む各種設定、等々によって、そのまま正常に動いたり、動作自体が無視されり、エラーになったり、任意のコマンドが実行できたり、等の予測不可能な現象が発生します。12文字では正常っぽい動作で、13文字でエラーになったのは、ただの偶然です。あなたの環境はたまたまそのような動作をするようにコンパイルされていて実行されたに過ぎません。OSを変えたり、コンパイラを変えたり、コンパイル時のオプションを変えたり、実行するタイミングを変えたりしたら、5文字でエラーになるとか、逆に100文字でも出力できるとか、いろいろと変わる可能性があります。「バッファオーバーフローは何文字まで大丈夫か?」という問いには、C言語の規格としては「0文字までは大丈夫だけど、1文字でも溢れたら、何が起きるかは予測は不可能」と答えるしかありません。

それでも、なぜ12文字と13文字で変わるのかを知りたいのであれば、どのような環境でどのようにコンパイルされてどのように動作するのかを細かく分析しないとわかりません。OS(細かいバージョンまでです。Windows 10ではなくWindows 10 Pro, バージョン: 1703, OSビルド: 15063.483と言ったところまで知る必要があります)、コンパイラ(単にVC++とかではなく、こちらもバージョンやアップデートも含めてです)、コンパイル時のオプション(コンパイルそのものへの設定があれば、それも含めて)、実行環境(データ実行防止(DEP)の有無、ウィルススキャンソフトの有無、その他のセキュリティ関係のポリシー)を知る必要があります。コンパイルされたバイナリを逆アセンブラで解析し、スタックへの書き込みをエミュレートしながら、バッファオーバーフロー時にどのようにメモリが変更され、問題があるかないかを見る必要があります。かなり高度な知識が要求されますが、よくあるバッファオーバーフローをついて任意コマンド実行を行う方法(いわゆるバッファオーバーフローに起因する脆弱性というものです)を調べる場合は必須の技術ですので、セキュリティー分野に進みたいのであれば身につけておいて損はありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/17 09:24

    とてもご丁寧がご説明ありがとうございます!
    勉強になります!

    キャンセル

0

12とかの数字はたまたまです。手元のLinux/64bitのgccでやってみましたが、8まででした。
規格がどうなっているかという話じゃなくて、実際がどうかという話をします。

これは、コンパイラによって異なる部分です。また同じgccでも、32bitのコードを生成するのか64bitのコードを生成するのかによって異なります。

停止の原因は、スタック上の「呼び出し元への戻りアドレス」の破壊でしょう。

mainが呼び出された時点で、スタックトップには、呼び出し元への戻りアドレスが入っています。
呼び出された後に、BPレジスタの値がスタックにPUSHされます。64bitコードだとこれが8バイト。
char str[1];の1バイトの変数はその直下です。

入力したのが8文字までだと、最後のNULバイトを含めて9文字なので、変数の1バイトと、BPレジスタの値の8バイトの範囲で収まり、呼び出し元への戻りアドレスは無傷です。なので、呼び出し元に戻ることが出来ます。
ただし、呼び出し元へ戻ったあとのBPレジスタは文字列の値で上書きされていますので、呼び出し元が処理続行する場合は、その後の処理がおかしくなる可能性があります(後述)。

入力したのが9文字以上だと、呼び出し元への戻りアドレスを壊してしまいますので、mainからの戻りの時点でおかしなアドレスに戻ろうとして、ほとんどの場合、未割り当てアドレスへのアクセスとなり、セグメンテーション違反の例外になります。
戻りアドレス部分に書き込む値を調整すると、存在するアドレスに戻ることが出来、これがバッファーオーバーフロー攻撃です。

BPを破壊した場合どうなるか

質問の例のように、mainプログラムで、プログラム終了=プロセス終了の場合は、影響ないようです。
これが、サブルーチンだとすると、呼び出し元で処理が続行できません。

サンプル:

#include <stdio.h>

int sub(void)
{
    char str[1];
    scanf("%s", &str);
    printf("%s", &str);
    return 0;
}

int main(void)
{
    printf("Before\n");
    sub();
    printf("After\n");
    return 0;
}
~


これだと、1文字の入力で、"After"を表示の後にセグメンテーション違反になりました。0文字入力(入力行の行頭でctrl-D)の場合はstr[0]NULが入るだけなのでOKです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/17 11:10

    ご回答ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る