web-dev-qa-db-ja.com

「 'getenv':この関数または変数は安全でない可能性があります。」 - 本当に?

私はMSVCを使用して、getenv()sprintfなどの標準ライブラリ関数を使用するCコードをコンパイルしています。警告には/W3が設定されています。私はMSVCから次のように言われています:

'getenv':この関数または変数は安全でない可能性があります。代わりに_dupenv_sの使用を検討してください。非推奨を無効にするには、_CRT_SECURE_NO_WARNINGSを使用します

質問:

  • 他のプラットフォームでの使用とは対照的に、理論的にはこれが安全でないのはなぜですか?
  • 実際にはWindowsでは安全ではありませんか?
  • 私がセキュリティ指向のコードを書いていないと仮定すると、この警告を無効にするか、実際に一連の標準ライブラリ関数のエイリアスを開始する必要がありますか?
7
einpoklum

getenv()は、同じ関数への後続の呼び出しが以前に返されたポインターを無効にする可能性があるため、潜在的に安全ではありません。その結果、

_char *a = getenv("A");
char *b = getenv("B");
/* do stuff with both a and b */
_

aがその時点でまだ使用可能であるという保証がないため、破損する可能性があります。

getenv_s() --C11以降のC標準ライブラリで使用可能-値を呼び出し元が提供するバッファーにすぐにコピーすることでこれを回避します。呼び出し元はバッファーの存続期間を完全に制御できます。 dupenv_s()は、割り当てられたバッファーの存続期間を管理する責任を呼び出し元に持たせることにより、これを回避します。

ただし、_getenv_s_の署名はやや物議を醸すものであり、関数はある時点でC標準から削除されることさえあります...を参照してください。 このレポート

8
user743382

getenvは、文字列バッファの長さを制限しないことにより、従来のC標準ライブラリの多くと同じように苦しんでいます。これは、バッファオーバーランなどのセキュリティバグが頻繁に発生する場所です。

getenv_sを見ると、返される文字列の長さに明示的な境界が設定されていることがわかります。 セキュリティ開発ライフサイクル のベストプラクティスによるすべてのコーディングに推奨されます。そのため、Visual C++は安全性の低いバージョンに対して非推奨の警告を発します。

[〜#〜] msdn [〜#〜] および このブログ投稿 を参照してください。

マイクロソフトは、C/C++ ISO標準ライブラリにSecureCRTを含めるように努力しました ここ 、その一部は、前述のようにC11 Annex Kで承認されました ここ 。これは、getenv_sが参照によりC++ 17標準ライブラリの一部であることも意味します。とは言うものの、Annex Kは、適合性のために公式にはオプションと見なされています。これらの関数の_s境界チェックバージョンも、C/C++コミュニティでまだいくつかの 討論 の対象となっています。

0
Chuck Walbourn