C文字配列char buf[15]
があるとします。変数int set_me = 0
のデータは、char buf[15]
の直後のメモリ位置に格納されているとします。 buf
を文字列"aaabbbcccdddeee\xef\xbe\xad\xde"
でオーバーフローさせた場合、set_me
のデータ型は整数から文字配列に変更されますか?
番号。
変数の「データ型」は、ソースコードにのみ関連します(一部の言語にのみ関連します)。コンパイラに変数の処理方法を指示します。
これらの高レベルのデータ型は、コンパイルされた(ネイティブ)コードには存在しません。これらはコンパイラが生成する命令に影響を与える可能性がありますが、データが文字を表すのか数字を表すのかは命令自体は関係ありません。
変数はハードウェアには存在しません。ハードウェアでは、メモリの場所とそれらを操作する命令があります。
変数は、メモリの場所にあるデータのviewと見なされる可能性があります。同じメモリを少しだけ別の方法で見れば(同じ場所を参照する異なるタイプの異なる変数)、同じバイナリ値には別の意味があります。
たとえば、バイト0x41は、UTF-8でエンコードされた文字A
として解釈できます。また、1バイト整数65
として解釈される場合もあります。また、マルチバイト整数または浮動小数点数の1バイト、またはマルチバイト文字エンコードの1バイトとして解釈することもできます。ビットセット0b1000001
の可能性があります。同じメモリ位置の同じバイトからすべて。 C言語では、これらのさまざまなタイプにcastingでこの効果を確認できます。
「バッファオーバーフロー」があると、コンパイラや言語が期待する範囲を超えた何かをしていることになります。ただし、ハードウェアに関する限り1、メモリ位置にバイト(単一または複数)を書き込んでいます。メモリ位置には「タイプ」がありません。実際、ハードウェアは、特定のバイトセットがコード内の配列またはバッファーを作成することすら知りません。
次にコード内のそのメモリ位置にアクセスするときはいつでも、命令は最初に定義されたとおりに実行されます。例えばそこで数値を期待していた場合、それらはデータのバイトに作用しますまるでそれらは数値でした。
例を使用するには、int
が符号付き4バイト(32ビット)整数であると仮定します。
+-------------+--------------------------------------------+-----------+
| Source code | char[15] | int |
+-------------+--------------------------------------------------------+
| Memory |61|61|61|62|62|62|63|63|63|64|64|64|65|65|65|EF|BE|AD|DE|
+-------------+--------------------------------------------------------+
ビッグエンディアンシステムを想定すると、int
のメモリロケーションに0xEFBEADDE
が含まれていることがわかります。2。これは、署名された32ビットint -272716322
です。ここで、同じメモリをunsigned int(uint
)として解釈すると、代わりに4022250974
になります。メモリ内のまったく同じデータの場合、意味はデータの表示方法に完全に依存します。
1 メモリの保護された領域への書き込みを妨げるメカニズムがいくつかあり、そうしようとするとプログラムがクラッシュします。
2 x86は実際にはリトルエンディアンです。つまり、大きな値を構成するバイトを逆方向に解釈します。したがって、x86では、代わりに0xDEADBEEF
があり、署名された-559038737
または署名されていない3735928559
が与えられます。
Cの観点からは、答えは「誰が知っているのか?それは未定義の振る舞いです」です。
タイプはCの概念であり、ハードウェアではありません。ただし、プログラムに未定義の振る舞いがある場合、Cの規則は適用されません。これは、C標準における未定義の振る舞いの文字通りの意味です。そして、バッファオーバーフローはその一形態です。
私は最初に「Cルールは適用されなくなった」と書きましたが、実際には未定義の振る舞いは遡及的です。 Cルールは、将来未定義の振る舞いをするプログラムには適用されません。