2016-07-20 10 views
1

https://schweigi.github.io/assembler-simulator/でasmとスタックオーバーフローを理解しようとしています。 私は通常のスタックオーバーフローがスタック境界を超えてRAMにプッシュすることを理解していました。 スタックオーバーフローがRAM境界を超えてプッシュするとどうなるのですか?シミュレータでオペコードへのスタックオーバーフローPUSH(ASM)

あなたはコードでプログラムがある場合:

PUSH 53 ; 53 or 0x35 is opcode for PUSH 
JMP 0 ; loop it 

プログラムがRAMを超えてスタックをプッシュに自分自身を上書きし、スタックポインタは-1になります。 実際のシナリオ、実際のプログラムではどうなりますか?

+1

状況によっては、アーキテクチャやオペレーティングシステムなどによって異なります。通常はフォルトが発生し、プロセスは終了します。 – Jester

+1

x86では決して "__RAM境界を越えて押し込むことはできません"。スタックは、利用可能なアドレス空間(実アドレスモードの場合は64KB、保護モードの場合は4GB)でうまくラップアラウンドします。結果は悲惨です! – Fifoernik

+0

スタックは通常トラフレジスタ "スタックポインタ"(またはZ80やx86などの多くのCPU上の 'sp')で管理されます。スタックに何かを押すと、 'valueを[sp]、sub sp、value_size'に格納することを意味します。 'sub reg、#n'は通常単純に折り返されるので、' 0'から '1'を引いて' sp'を '0xFFFF'(16bプラットフォーム)とすると、16bメモリの上から始めます。 – Ped7g

答えて

2

ウィキペディアから非常に素晴らしい定義:コールスタックポインタが バインドスタックを超えた場合、ソフトウェアで

、スタックオーバーフローが発生します。呼び出しスタックは、限られた量の アドレス空間で構成されていることがあり、プログラムの開始時にしばしば決定されます。呼び出しスタックのサイズ は、プログラミング言語 の言語、マシンアーキテクチャ、マルチスレッド、および使用可能メモリ量が であるなど、多くの要素によって異なります。プログラムが呼び出しスタック上で利用できる よりも多くの領域を使用しようとすると(すなわち、呼び出しが呼び出しスタックの境界を超えて メモリにアクセスしようとすると、これは基本的にバッファオーバーフロー オーバーフローと呼ばれます)結果として プログラムがクラッシュします。

スタックバインドの定義は、スタックにどれだけのメモリがあるのか​​は普遍的なものではありません。いくつかの(古い)プロセッサには8または16のディープスタックが組み込まれていますが、リターンアドレスの場合にのみ表示されます。関数呼び出しが深すぎると、後で必要になる可能性のあるアドレスを上書きします。

仮想アドレス空間に配置され、割り当てられた領域外にさまよってしまうことのないようにするWindows/Linux/Macマシンでは、スタックをラムの保護されたBLOBとして割り当てることが可能な設計ソリューションの範囲内にあります(プログラム、データ、ヒープとは別に)、アクセスが許可されていない仮想アドレスを使ってデータアクセスをしようとすると、メモリ障害が発生します。

他の多くの興味深いケースは間違いありませんが、プログラムの通常のRAMベースのビューは、あなたのプログラムといくつかのデータを持っているより低いアドレスにあります。より高いアドレスには、真ん中にはヒープがありますが、その一部はスタックスペースをいくらか与えるヒープとして定義されています。通常、何が起こるかを無限に押すことで説明したことを実行しようとすると、スタックは実行中のループを上書きするまでその値でいっぱいになり、プロセッサの仕組みによってはキャッシュに格納されているか、またはキャッシュに書き込むバイトを実行しようとします。これらのバイトは、クラッシュする可能性があるかどうかによって異なります。これらのバイトを実行しようとすると、スタックベースでなければ、もはやキャッシュをジャンクに「充填」しなくなります。

多くのシステムで「スタックオーバーフロー」と表示されるのは、スタックとヒープまたはスタックとプログラムが衝突したことを意味します。ソフトウェアはスタックとデータの同じアドレスを使用しようとしています。誰が悪いデータを取得したのか、悪いリターンアドレスを使うのかを判断するときに書きます。ほとんどの場合、クラッシュが発生する可能性があります。クラッシュするまで再帰的に呼び出す再帰関数を使ってこれを非常に簡単にテストできます。

+0

実行しているシミュレータの事柄や命令セットは特別なものかもしれません。基本的にスタックが使用されるたびに定義されたヒープに掘り下げられているかどうかを確認するたびに、この衝突を防ぐために、ツールチェーンとライブラリの組み合わせなどを持たせることが可能です。 –

+0

私はvalgrindを使ってスタックオーバーフローを防ぐのではなく、メモリをいっぱいにして、ある時点でスタックの深さやヒープの高さを調べることができると思います。 –