VC++ 2005 セキュリティーコード
普段プログラムはMicrosoftのVisual C++ 2003で組んでいるけど、ノートパソコンにはMicrosoft Visual C++ 2005 Express Edition + Microsoft Platform SDKをインストールして使っている。
※VC++ 2005 Express Edition と PlatformSDK は 「タダ・無料・フリー」 昔じゃ考えられないな。あぁけどLSI-C86試食版とか使ったっけ。
ところが新しいだけあって(2008の宣伝をどっかでちらっとみたけど)2002や2003で組んだコードだと警告(warning)やエラー(error)がどっちゃりと出てくる。
系統的には2種類で文字コードの問題とセキュリティーコードの問題らしい。
今回はそのセキュリティーコードの話をしようと思う。
こんなソースコードがあったとしよう。
めんどくさかったのでウィーザードから生成したため、_tmain とか stdafx.hとかインクルードしているが、_tmain は通常のmain関数、stdafx.hはstdlib.hとかstring.hとかをインクルードしているという感じに置き換えて見て欲しい。
このソースコードを今までの2002や2003でビルドしても警告やエラーは出ない。
ところが2005(Express Editionも含む)はこんな警告を出す。
英語は苦手なんだが、この関数(ここではsprintfとstrcpy)にはセキュリティに対応した新しい関数があるんでそっち使ってね…もしあれだったら_CRT_SECURE_NO_WARNINGSを有効にすればセキュリティ関係の警告は出さないようにするね…。ってことらしい。
セキュリティに対応したコードは大抵文句を言われた関数名に_sをつけたものらしい。
実際にやってみてビルドしてみる。
セキュリティーコードってのはきっと転送先バッファあふれを防止することなんだと思う。
だからもし転送先バッファ以上のデータをコピーしたり、書き込んだりするとアサートでダイアログでも出して止まる仕組みにでもなってるんだろう。
そこでたぶん文句を言われるであろうソースコードに書き換える。
配列だとsizeofとかでサイズがわかるけど、mallocなんかで確保した動的な領域のサイズはわかんないわな。
じゃーそーするのかというとこうする。
セキュリティーコード版の関数はオーバーロードされてこの2種類の引数が対応されているようだ(例外はあるかも)。
ところがこのコード、正直やってはこまることをやってくれる。
※私のプログラム作法が悪いのかもしれないが。
デバック中のメモリ状態だ。
黄色い矢印の行を実行する寸前といったところでプログラムが停止している。
メモリ1のウィンドウの先頭がbuf1のアドレス。メモリ2がpBufだ。
両方の領域ともmemsetで0クリアされているのがわかるだろうか。
ここでsprintf_sでbuf1の領域に"abcdefg"という文字列を書き込む。
※文字列終端には当然\0(0x00)
無事文字列が書き込まれているのがわかるが\0以降に注目してもらいたい。
0xfdがbuf1の残り領域いっぱいに書き込まれているのだ。
ということはstrcpy_sの方も…

あぁぁぁ0xfdで犯されていくぅ・・・。汚れちゃったよぅぅぅぅ。僕の大切なメモリ空間がぁぁぁ。
マニュアルにはしっかりと第2引数は「転送先のバッファサイズ」とある。
くぅぅぅ。セキュリティが強固でもメモリを汚されるのはいやだなぁ…。
転送先のバッファサイズが最低こんだけ絶対あるの保障するよ~とかいってプログラマが確認の意味で第2引数を決め付けちゃうってんであれば
ってだめじゃーーーん。
ちっともセキュリティコードじゃないよぅぅぅ。
もともとの私のプログラム作法が悪いのかしら?
ちなみに_sがついた関数はおそらく2002や2003にはないのでプリコンパイル時に切り替える仕組みを書くか、きっぱりセキュリティに対応した関数は使わないで_CRT_SECURE_NO_WARNINGSを有効にするべきだろう。
_CRT_SECURE_NO_WARNINGSを2005のときだけ簡単に有効にするには2005用のプロジェクトでソリューションエクスプローラからプロジェクトのプロパティを開いて(太字のプロジェクト名を右クリックしてのメニュー一番下)
構成プルダウンメニューの「Debug」「Release」両方の構成に対して[構成プロパティ]-[C/C++]-[プリプロセッサ]の「プリプロセッサ定義」横にある[...]ボタンを押して_CRT_SECURE_NO_WARNINGSを追加すればOK。
いきなり「すべての構成」で設定してしまうともともと設定されている定義が消えちゃうようなので注意。
残ったメモリ空間を汚してしまうセキュリティコードってひどくないかぁ?
すでに大切な情報が書き込まれている場合とかも…きっと破壊するよねぇ…。
デバックビルドの時だけかとも思ったけど、実は別のプログラムのとき、リリースビルドでこれが原因で不具合が出たので、おんなじだろうと予想する。
私の根本的なプログラム作法を考え直すべきなんだろうか?
| 固定リンク
「プログラミング」カテゴリの記事
- フォント(2008.04.10)
- Silverlight実習 その2(2008.03.04)
- Silverlight実習(2008.03.04)
- 開発ラッシュ(2008.02.23)
- VC++ 2005 セキュリティーコード(2007.09.20)
「プログラム」カテゴリの記事
- フォント(2008.04.10)
- VC++ 2005 セキュリティーコード(2007.09.20)
- SOFTIMAGE_XNAViewer(2007.08.24)
- [XNA]:XSI 6 Mod Tool(2007.08.18)
- C言語のmain関数について(2006.08.28)



























コメント