volatile
変数の他のすべての使用にも影響を与えるため、時にはやり過ぎかもしれません。
使用memset_s
(C11 以降): http://en.cppreference.com/w/c/string/byte/memset
memset は、この関数によって変更されたオブジェクトがその存続期間中に再びアクセスされない場合、(as-if ルールの下で) 最適化されて取り除かれます。そのため、この関数を使用してメモリをスクラブすることはできません (たとえば、パスワードを格納した配列をゼロで埋めるなど)。この最適化は memset_s では禁止されています。メモリ書き込みの実行が保証されています。
int secret_foo(void)
{
int key = get_secret();
/* use the key to do highly privileged stuff */
....
memset_s(&key, sizeof(int), 0, sizeof(int));
return result;
}
ここで、さまざまなプラットフォーム/C 標準の他のソリューションを見つけることができます: https://www.securecoding.cert.org/confluence/display/c/MSC06-C.+Beware+of+compiler+optimizations
補遺:他の問題を指摘するこの記事を参照してください(実際のバッファーをゼロにする以外に):
少し注意を払い、協調的なコンパイラーを使用すれば、バッファーをゼロにすることができますが、それは私たちが必要としているものではありません。私たちがしなければならないことは、機密データが保存されている可能性のあるすべての場所をゼロにすることです。そもそも機密情報をメモリに保持していたのは、それを使用できるようにするためだったことを思い出してください。そして、その使用により、ほぼ確実に、機密データがスタックとレジスターにコピーされました。
コンパイラkey
によって値が別の場所 (レジスタまたは一時的なスタック/メモリの場所など) にコピーされた可能性があり、その場所をクリアするための制御がありません。