ポインターの不適切な使用が引き起こす可能性のあるこれらのいわゆる「災害」とは何ですか? [閉まっている
-
12-10-2019 - |
質問
私は自分のプログラムでポインターをますます使用しており、ポインターについて読んでいる間、ポインターの誤った使用が「悲惨な」結果が得られる可能性があると発見したすべてのガイドまたはチュートリアルが発見しました。
今、私はいくつかの大きなメモリリークのいくつかのケースを持っています、そして、間違ったポインター変数を逆にさせ、間違った値を返すポインターがありますが、それ以外は「悲惨な」ことはこれまでに起こっていません。私のコンピューターや他のプログラムがクラッシュするように。
誰かが私に、おそらくそのコードを誤って使用したことがある場合に備えて、おそらく何が起こったのか、おそらく何らかのバックストーリーを使用して、間違いなく「悲惨な」結果をもたらす簡単なコードの例を教えてもらえますか? 「悲惨な」結果とは、他のプログラムやOSに干渉し、おそらくそれらをクラッシュさせる可能性のあるコードを意味します。
解決
誤ったポインター算術は災害につながる可能性があります。なぜなら、間違った範囲を取得するとバッファのオーバーフローにつながり、バッファーオーバーフローが破損したデータ、たとえばスタックスマッシングにつながるためです。
void test_fun(int i)
int x[5];
for (int *p = x; p < x+10; ++p) { // obvious error, some are more subtle
*p = i;
}
return; // execution may resume at address `i`, with entertaining results
}
もちろん、あなたは電話するだけで同じ間違いを犯すことができます strcpy
また memcpy
*]、ポインター算術を自分で行う必要はありません。攻撃者がの値を制御する場合 i
(おそらく、入力ファイルから読み取られ、攻撃者が悪意のあるファイルを作成しているため)、手のクラッシュよりも悪いことがあります。よりプラットフォーム固有のトリックと組み合わせて、攻撃者はその戻りを手配できるかもしれません i
最終的には、攻撃者が提供するコードを実行することになります。
*] また strncpy
, 、 また strlcpy
, 、 また strcpy_s
, 、 また std::copy
, 、誰もが始まる前に。どういうわけか間違っていると、バウンドチェック関数に縛られた間違ったものを提供することはまだ間違っています...
他のヒント
障害には、ぶら下がっているポインターとメモリリークの2つの主要な種類があります。
ダングリングポインターとは、ポインターがオブジェクトのアドレスではないアドレスを保存する場合です。
T* first;
T* second; //somewhere in another piece of code
first = new T();
second = first;
delete first;
first = 0; //second still stores the address of an already deleted object
メモリリークは、ヒープに割り当てられたオブジェクトのアドレスを保存するポインターがない場合です。
T* object;
for( int i = 0; i < 10; i++ ) {
object = new T();
}
delete object; // now the first nine objects are unreacheable
ぶら下がっているポインターは、それらを使用すると未定義の動作につながるため、プログラムは無関係なデータをクラッシュまたは変更する可能性があり、これは後で問題を引き起こす可能性があります。割り当てられたメモリを再利用できないため、メモリリークは悪いので、プログラムはしばらくしてメモリが不足する可能性があります。
いくつかのケースが思い浮かびます:
- free()/delete()dメモリまたはローカル変数がスコープを去った後もアクセスし続ける
- 不明確な所有権によるヒープメモリの漏れ
- 尖った値への変更がそれらに取り組んでいるいくつかのアルゴリズムを混乱させる可能性のあるデータへの意図しない共有アクセス
- 偶発的な浅いコピー
- 実際に他のデータへのポインターを含む想定されたポッドデータの素朴なバイナリライティングによる不完全/欠陥シリアル化
- ポインター(特に仮想ディスパッチポインター)がそれにアクセスする異なるプロセスで異なる必要がある共有メモリのマルチプロセスの安全でないデータ
- コードがループに固定されている原因となる周期的なデータリンケージ
- ポインターをデータに移動して、データの外側に誤って移動するようにします(問題は配列インデックスに似ていますが、必ずしも一定の参照と一貫して安全な相対インデックス範囲があるため、より複雑です)
- センチネルの値を正しくチェック /処理できない
- ポインターがポイントするデータの種類に関する問題
- 安全でない/誤ったキャストの使用(たとえば、ダイナミックキャストが必要な場合の再解釈キャスト)
- ポインターからのインデックス作成がポインタからタイプのサイズのユニットで行われることを理解できない
- ポインターから短い整数型からのポインターからの変換が無効な変換
私が見た中で最も厄介なのは、「遅延障害」です。誤って完了した書き込みアクセスが後で使用されるデータ構造に損害を与え、完全に無関係なコードの誤った出力を生成する場合です。デバッグ中に、「マシンの台頭」が観察されます。データ構造は、プログラマーに対して、割り当てられたことのない間違った値を神秘的に取得します。あなたは、それが実際にある場所から数千のloc離れているエラーを検索しているかもしれません。