アカウント名:
パスワード:
図2●C++で作成した、入力された文字列を出力するプログラム(inout.cpp) [nikkeibp.co.jp]で挙げている筆者のコードだが、一目みて、sが最大何文字許容されるのか判断がつかない。結局、各クラスのメソッドが何文字まで許容されるのか覚えておくか、C++のライブラリの実装にまで踏み込んで確認することが必要になってしまうのであり、そこまでやるなら、最初からpure Cで書いたほうがコストが低い。
sが何文字許容されるか確認せず使うなんて、脆弱性を発生させる罠以外の何者でもない。C++が安全だというのは過信である。
int main(){ string s; while (getline(cin, s)){ cout << s << endl; } return 0;}
> 一目みて、sが最大何文字許容されるのか判断がつかない。そもそもテキストファイルの仕様に一行の長さの制限なんかないのに(メインフレーム時代のレコードに行を記録していたものならまだしも)プログラマの都合で勝手に長さを制限するほうが頭おかしい。> 各クラスのメソッドが何文字まで許容されるのか覚えておくか、C++のライブラリの実装にまで踏み込んで確認することが必要になってしまうのであり、C++の標準ライブラリではstringに文字数制限なんかない。他の言語(たとえばJavaのStringとかC#のStringとかJavaScriptのString)も同様。むしろいちいち長さを別途管理する必要のあるCのほうが(高級言語として)異常。> そこまでやるなら、最初からpure Cで書いたほうがコストが低い。Cでまともに任意長の行入力を受け付けるまともなプログラムを書くほうがどう考えてもコストが高い。
あなた、CとC++のこと分ってないでしょ?C++に詳しくない私がちょっと調べた限りでも、stringクラスで処理可能な最大文字列長はstring::max_size()で返されるサイズに制限されることくらいわかる。つまりは、Cで適当な固定長のバッファを確保して処理するのと同じということ。ちなみに、昨今の標準的なOSでは、malloc()でどれだけ大きいサイズのメモリを確保しても、実際にメモリを活用する段階にくるまでは、実際の物理メモリは消費されない。そんなに制限されるのが嫌なら、常に4GBのバッファを確保して文字列処理するようにしてみてはどうだろう?もっとも、この場合、Memory over commit するようにシステムを構成する必要があるが。
限界を意識せず、プログラムをC++で組んだところで、いざ過大な入力があったときはExceptionが飛んでプログラムが不正に終了するにすぎないのですよ、バッファオーバーフローになるよりいいかもしれないけど。;-)
それは移植性を考えないから言えること。max_size()はあくまで最大サイズなんだから、最初に割り当てられるバッファのサイズは本当の意味で処理系依存でしょ。で、処理系によって得意なバッファサイズを勝手に使ってくれるんだから、こんな楽なことないと思うんだけど。もちろん、コンパイラはそこら辺の事情を詳しく知る立場にいるんだし。
例えば、max_sizeが2GBだったとき、まさか2GBを先に確保するとかいわないよね?
だよね。
固定長の処理になっているかもしれないし、そうではないかもしれない。
1024バイトぐらいなら固定長にしてくれたほうが都合がいいけど、実際の実装では、常に大容量(例えば512MB)ものメモリを確保するというのはできない。となると、一定量の入力があった場合、リンクリストでつないでいくか、新たにもっと広い領域を作ってコピーするか、(こういう操作ができるOSはないだろうけど)PTEを操作して仮想メモリをつなぎあわせて1つの領域にしちゃうようなAPIを使うかということになるのだけど、C++のライブラリの中で実際にどんな操作が行なわれるのか仕様が定まっていない以上、これらの処理量が予測できないというのがプログラマからみると問題。
C++でなにも考えなくてもいい入力量のオーダーなら、Cである程度固定長の領域を取って処理したほうがいいし、それを越えるようならば、C++の汎用ライブラリで処理することはできず、結局自分で再設計することになるのでしょう。
だから、僕の感覚の中では、C++はやっぱり、いらない感じがするのですよね。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
Stableって古いって意味だっけ? -- Debian初級
C++の利用はセキュリティ上重大な懸念を残すことになる (スコア:1)
図2●C++で作成した、入力された文字列を出力するプログラム(inout.cpp) [nikkeibp.co.jp]で挙げている筆者のコードだが、一目みて、sが最大何文字許容されるのか判断がつかない。結局、各クラスのメソッドが何文字まで許容されるのか覚えておくか、C++のライブラリの実装にまで踏み込んで確認することが必要になってしまうのであり、そこまでやるなら、最初からpure Cで書いたほうがコストが低い。
sが何文字許容されるか確認せず使うなんて、脆弱性を発生させる罠以外の何者でもない。
C++が安全だというのは過信である。
Re: (スコア:0)
> 一目みて、sが最大何文字許容されるのか判断がつかない。
そもそもテキストファイルの仕様に一行の長さの制限なんかないのに(メインフレーム時代のレコードに行を記録していたものならまだしも)プログラマの都合で勝手に長さを制限するほうが頭おかしい。
> 各クラスのメソッドが何文字まで許容されるのか覚えておくか、C++のライブラリの実装にまで踏み込んで確認することが必要になってしまうのであり、
C++の標準ライブラリではstringに文字数制限なんかない。他の言語(たとえばJavaのStringとかC#のStringとかJavaScriptのString)も同様。むしろいちいち長さを別途管理する必要のあるCのほうが(高級言語として)異常。
> そこまでやるなら、最初からpure Cで書いたほうがコストが低い。
Cでまともに任意長の行入力を受け付けるまともなプログラムを書くほうがどう考えてもコストが高い。
Re:C++の利用はセキュリティ上重大な懸念を残すことになる (スコア:2)
あなた、CとC++のこと分ってないでしょ?
C++に詳しくない私がちょっと調べた限りでも、stringクラスで処理可能な最大文字列長はstring::max_size()で返されるサイズに制限されることくらいわかる。つまりは、Cで適当な固定長のバッファを確保して処理するのと同じということ。
ちなみに、昨今の標準的なOSでは、malloc()でどれだけ大きいサイズのメモリを確保しても、実際にメモリを活用する段階にくるまでは、実際の物理メモリは消費されない。
そんなに制限されるのが嫌なら、常に4GBのバッファを確保して文字列処理するようにしてみてはどうだろう?
もっとも、この場合、Memory over commit するようにシステムを構成する必要があるが。
限界を意識せず、プログラムをC++で組んだところで、いざ過大な入力があったときはExceptionが飛んでプログラムが不正に終了するにすぎないのですよ、バッファオーバーフローになるよりいいかもしれないけど。;-)
Re: (スコア:0)
それは移植性を考えないから言えること。max_size()はあくまで最大サイズなんだから、最初に割り当てられるバッファのサイズは本当の意味で処理系依存でしょ。で、処理系によって得意なバッファサイズを勝手に使ってくれるんだから、こんな楽なことないと思うんだけど。もちろん、コンパイラはそこら辺の事情を詳しく知る立場にいるんだし。
例えば、max_sizeが2GBだったとき、まさか2GBを先に確保するとかいわないよね?
Re: (スコア:0)
> C++のライブラリの実装にまで踏み込んで確認する
を見落としてますよ。
もしかしたら、ライブラリの中で
char buf[1024];
fgets(buf, sizeof(buf), fp);
s.assign(buf);
なんていう酷い実装になっているかもしれんぞ。
Re:C++の利用はセキュリティ上重大な懸念を残すことになる (スコア:2)
だよね。
固定長の処理になっているかもしれないし、そうではないかもしれない。
1024バイトぐらいなら固定長にしてくれたほうが都合がいいけど、実際の実装では、常に大容量(例えば512MB)ものメモリを確保するというのはできない。
となると、一定量の入力があった場合、リンクリストでつないでいくか、新たにもっと広い領域を作ってコピーするか、(こういう操作ができるOSはないだろうけど)PTEを操作して仮想メモリをつなぎあわせて1つの領域にしちゃうようなAPIを使うかということになるのだけど、C++のライブラリの中で実際にどんな操作が行なわれるのか仕様が定まっていない以上、これらの処理量が予測できないというのがプログラマからみると問題。
C++でなにも考えなくてもいい入力量のオーダーなら、Cである程度固定長の領域を取って処理したほうがいいし、それを越えるようならば、C++の汎用ライブラリで処理することはできず、結局自分で再設計することになるのでしょう。
だから、僕の感覚の中では、C++はやっぱり、いらない感じがするのですよね。
Re: (スコア:0)
ストリームをつかえば、勝手にに扱いたい部分のデータにメモリをスライドさせてくれます。
もし効率が気になるなら、streamクラスを自分で拡張してください!!
streamを適切に実装して、それをセキュリティ的に脆弱な場所で使うようにすれば、
バッファオーバーフローとか気にしなくていいと思うのですが・・・。
それとも、C++のプロのプログラマはstreamクラスの設計思想を理解していないんでしょうか・・・。