次のようなコードを書くのに間違いはありますか?
char* sp=(char*)malloc(128);
int x=22;
wsprintf(sp,"%d",x);
cout<<sp;
私は特にセキュリティの間違いについて尋ねていますか?
ここには多くの「潜在的な」問題があり、それらのどれも実際には何も侵害していませんが、期待どおりに動作しないことがあるかもしれません。
まず、Win32 API(http://msdn.microsoft.com/en-us/library/windows/desktop/ms647550 (v=vs.85).aspx)としてのwsprintfは、次のようにプロトタイプ化されます。
int __cdecl wsprintf(
_Out_ LPTSTR lpOut,
_In_ LPCTSTR lpFmt,
_In_ ...
);
ここで、はシンボルのLPTSTR
定義として定義されているchar*
かどうかwchar_t*
に応じて定義されUNICODE
ます(プロジェクト設定および/またはビルドコマンドを確認してください)
これで、ANSIビルド(UNICODEなし)を使用している場合、すべてのタイプに一貫性がありますが、割り当てた128文字を超えるwsprintfの書き込みに関するチェックはありません。10進整数を書くだけなら問題ありませんが、後で「メッセージ」を変更してチェックを行わないと、いくつかの驚きが生じる可能性があります(wsprintf(sp,"This is the number I've been told I was supposed to be expected to be: %d",x);
これはまだ128文字に収まるのでしょうか?! ?)
UNICODEビルドを使用している場合は、128文字を割り当て、それに2バイト文字列を書き込みます。数値22は次のように記述されます\x32\x00\x32\x00\x00\x00
(3200は、「2」を表すUNICODE 50に対応するwchar_tである0x0032のリトルエンディアンコーディングです)。そのシーケンスをcout(つまり、wchar_tベースではなくcharベース)に指定すると、最初の\ x00が文字列ターミネータとして表示され、「2」だけが出力されます。
首尾一貫するために、あなたは次のいずれかを誓います:
char
ベースのタイプと関数を使用します(OK mallocとcout、ただしwsprintfA
代わりにwsprintf
)wchar_t
ベースのタイプと関数を使用します(malloc(128 * sizeof(wchar_t))、wchar_t *およびwsprintfW
)TCHAR
ベースタイプ(malloc(128 * sizeof(TCHAR))、TCHAR *、およびwsprintfを使用しますが、UNICODEとして定義するtcout
か、cout
それwcout
に応じて定義します)。C文字列に変換されたintが割り当てたサイズを超えることは決してないため、セキュリティ上の間違いはありません。
ただし、このスタイルのプログラミングには、セキュリティの問題が発生する可能性があります。そして歴史は、この種のコードが何度も実際のセキュリティ問題を引き起こしていることを示しています。それで、多分あなたはコーディングのより良いスタイルを学ぶべきですか?
あなたがwinapiを使用していると述べたことを考えると、彼らのドキュメントからこれを読んでください:
注使用しないでください。代わりに、StringCbPrintf、StringCbPrintfEx、StringCchPrintf、またはStringCchPrintfExのいずれかの関数を使用することを検討してください。セキュリティに関する考慮事項を参照してください。
したがって、使用しないでください。ただし、代わりに行うように指示されていることは無視します。
Cで記述し、C標準ライブラリの関数(sprintf、snprintfなど)を記述します。その場合、coutは使用できません。
C++で記述します。std :: stringを使用すると、新しいto_stringだけでなく、boost :: formatとostringstreamもあり、フォーマットされた文字列を作成するのに役立ちます。目的に非常に適している場合は、C標準ライブラリ関数を引き続き使用できますが、割り当てはライブラリに任せてください。
このMSDNリンクには、の使用に関するいくつかの懸念事項がリストされていますwsprintf
。それらはあなたの例には当てはまらないように見えますが、あなたが探求したいと思うかもしれないいくつかの選択肢を提供します。