の考え方 メモリセーフ言語 が最近ニュースになっています。 C/C++ は、(ほとんどのものを実行する) 世界のシステム言語であることで有名ですが、 安全でない. 多くの人がこれを解決したいと考えています ハードフォーク C/C++ をメモリセーフなものに変更するか、すべてを書き直すことによって、世界のシステム コード さび.
フォークはばかげた考えです。 コンピューター サイエンスの中核となる原則は、レガシーを放棄するのではなく、レガシーと共存する必要があるということです。
そして、必要はありません。 最新の C コンパイラには、メモリセーフになる機能が既に備わっています。これを有効にするには、マイナーな (互換性のある) 変更を加えるだけで済みます。 これは、レガシー システムを放棄するハード フォークの代わりに、新しいシステムのメモリ セーフを可能にするソフト フォークになります。
OpenSSL の最新のメモリ安全性の問題を考えてみましょう。 彼らは最初に追加することでそれを修正しました メモリ境界、次にメモリへのすべてのアクセスをマクロの背後に置きます PUSH() メモリ境界をチェックします:
より良い (ただし現在は仮説的な) 修正は、次のようなものです。
size_t 最大サイズ CHK_SIZE(アウトポイント) =アウト? *outlen: 0;
これにより、メモリ境界がリンクされます 最大サイズ 記憶とともに アウトプット. コンパイラは、バッファ オーバーフローを防ぐためにすべての境界チェックを行うことができます。残りのコードを変更する必要はありません。
さらに良い (そして仮説的な) 修正は、次のように関数宣言を変更することです。
int ossl_a2ulabel(const char *in, char *out, size_t *outlen CHK_INOUT_SIZE(アウト));
とにかくそのつもりです、それは *outlen のメモリ境界です。 アウト 入力で、出力でより短い境界を受け取ります。
この特定の機能はコンパイラにはありません。 標的 gcc と 一族 すでに他の同様の機能があります。 それらはまだ半分しか実装されていません。 この機能は比較的簡単に追加できます。 現在、コードを調べて、自分で追加する方法を確認しています。 私はほとんどのことをコピーすることができました 割り当てサイズ 属性。 しかし、かなりの学習曲線があります。既存の開発者を説得したいだけです gcc 金 一族 私のために新しい属性を追加します。
上記の解決策のようなメモリの安全性の問題を修正する機能をプログラマに与えたら、有効にすることができます。 警告 アンセーフ コード用。 コンパイラは、上記のコードが安全でないことを認識していましたが、それを修正する実際的な方法がないため、プログラマにそれについてしつこく言っても無意味です。 この新機能には、使用しないことに関する警告が表示されます。
つまり、コンパイラガイドになります。 リファクタリング. コードのフォークは難しく、リファクタリングは簡単です。
上記の関数が示すように、OpenSSL コードは、勤勉なプログラマーに依存するという欠陥のある原則に基づいて、すでにある程度メモリ セーフになっています。 それを強制するにはコンパイラが必要です。 このような機能を使用すると、ギャップは比較的小さく、ほとんどの場合、関数パラメーター リストとデータ構造を変更して、ポインターをそのメモリ境界にリンクするだけです。 リファクタリングの労力は、大幅な書き直しではなく、わずかです。
これは ソフトフォーク. メモリ境界は、新しいコンパイラでコンパイルされた場合にのみ機能します。 古いシステムではマクロは無視されます。
この メモリの安全性 問題です。 C/C++ を放棄するという考えは解決策ではありません。 私たちはすでに現代の解決策の始まりを持っています gcc と 一族 コンパイル。 そのソリューションを拡張する必要があるだけです。
*** これは、Robert Graham が執筆した Errata Security の Security Bloggers Network シンジケート ブログです。 元の投稿を読む: https://blog.erratasec.com/2023/02/c-can-be-memory-safe.html