アカウント名:
パスワード:
C言語は標準設定で、ポインタ・配列の境界チェックをしたり、セキュアな代替関数がある命令(snprintfとか)は、非セキュアなオリジナル命令を無効にするとかすればいいとおもう
もちろん、コンパイルオプションや、コード内で明示的に指定することでそれらを無効にして、高速なコードを書きたい人は書けるようにして
OSやlibc等速度が必要なコードはチェックを無効にしてビルド、一般アプリはチェックを有効にしてビルドとか
多分、真面目に考え出すと別の言語を新たに作った方が楽と言うぐらいの変更になるので、JavaとかC#とかSwiftとかRustとかが出来たんだと思う。
配列の境界チェックぐらいまでなら、トリッキーな書き方は全面禁止、ポインタは指している先の有効なメモリの範囲も覚えておく、とかでなんとか実現出来そうだけど。他にも、オブジェクトの寿命の管理が厄介で、ポインタが指している先がまだ存在するかどうかがC言語ではあやふやになってしまう。プログラマの注意に委ねられてる。
GCの付いてる言語は、ポインタが指している限りは指されているオブジェクトは開放されないという方針で寿命の問題を解決してる。Rustだと、あらゆる変数の寿命を自明な場合を除いて明示することになっていて、それによって、指している対象よりも寿命の長いポインタの類を禁止していて、ポインタが指している先が存在しなくなっている、というトラブルを排除している。
C言語のコンパイラに似たようなチェックを行うオプションを付けるアイデアもあり得そうだけど、多分無理。「危なそうなコードは却下するよう安全寄りに倒して、ちょっとでも駄目そうな可能性のあるプログラムはエラー。あるルールに従った明らかに安全なコードだけが許されるから、既存のコードもちゃんとルール通りに書き直せ」という感じにできれば良いんだけど。Rustがそんな感じのノリの言語なんだけど、プログラマがしばしば、寿命チェッカが厳しすぎる、あちこちに非自明な寿命の定義を書き加えないとコンパイルが通らない、と嬉し涙を流している。ので、言語仕様上その手の事を書けないC言語のコンパイラにやらせようとすると、ごく限られた書き方だけを使った効率の悪いプログラムしかコンパイル出来ないような、残念なコンパイラになってしまう。
何故今でもC言語を使う必要があるかというと、あえてそういうチェックを外す必要のある低レイヤーの実装に必要だからで、そんなお節介な仕様を標準化されても「C言語でなければならない人」にとっては迷惑なだけではないかと。逆にそうした保護を言語仕様でやってもらわなければならない用途には、今や他の言語を選ぶべきなんじゃないですかね。
トレードオフになるよね
Cの利便性を保ったまま、ちょっとしたコーディング規則を設ければそこそこ安全で、コンパイルオプションでセキュアの強制もできるというのはすでにC++で実現されてるから、変な制約のついた変形C言語は今から作る必要はないだろ。
昔はそういうチェックを自動でやってくれる言語(コンパイラがするか実行時チェックかは措くとして)がいろいろあったと思うが、今は猫も杓子もc言語、c言語を使わぬ者プログラマに非ず、という雰囲気でしてねえ。
K&Rの時代には、変数名関数名も極力短く(つまりはタイプ量を少なく)していたのが、その後はタイプ量など気にせず長い名前にするようになったし。
今そんなにc流行ってんすかあまりそんな気はしないですが、どこの業界なんでしょう
というかCはもう流行ったりはしないけど、かといって無くなれば困るって存在。自然言語に例えればラテン語みたいなもんだろ。
だいたいPythonやgoみたいな「流行りの言語」なんてのは結局Cの拡張だしね。
K&Rの時代を引き合いに出してるってことは、「今」=「C89以降」なんじゃね?
短い識別子はコンパイラとカリンカの制限のためでは
snprintf は sprintf よりはセキュアだけど、サイズを間違えたらバッファオーバランする。あと、strcpy とか strcmp とかの非セキュア関数の代替関数はどうしよう。
逆だったらCの評価も変わったんだろうな。標準関数はセキュアだけど、非セキュアなことをやりたい時に代替関数を使えば低レベルなところも触れるみたいな。
単なる例だと思うけれど、 snprintfで指定するサイズ間違える時点ですでに使い方がおかしい。
お作法無視して無頓着に簡略化してコード書くからおかしなことになるだけでC言語の脆弱性はプログラマがそういう書き方しているからとしかおもわないんだよなーC言語でのリソース管理はプログラマのお仕事ですよと。
セキュア関数って基本は、車輪の再開発程度にしか思えないんだけどNUL終端してない文字列とかあそこまで意識する必要があるのかね。。そういうのって文字列じゃなくてバイナリデータの扱いにするだけと思うのだけれど
snprintf の n が何のためにあるのか知らない人がいるのですよ。n に何を渡すか分かってないから、結果それで防止できるはずのバグが防止できないとかよくある。
snprintfはsprintfの相対的なセキュア版でしかないからね。意味がわからない方が良識的だと思う。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
アレゲは一日にしてならず -- アレゲ研究家
標準設定の問題? (スコア:0)
C言語は標準設定で、ポインタ・配列の境界チェックをしたり、
セキュアな代替関数がある命令(snprintfとか)は、非セキュアなオリジナル命令を無効にするとか
すればいいとおもう
もちろん、コンパイルオプションや、コード内で明示的に指定することでそれらを無効にして、
高速なコードを書きたい人は書けるようにして
OSやlibc等速度が必要なコードはチェックを無効にしてビルド、
一般アプリはチェックを有効にしてビルドとか
Re:標準設定の問題? (スコア:4, すばらしい洞察)
多分、真面目に考え出すと別の言語を新たに作った方が楽と言うぐらいの変更になるので、JavaとかC#とかSwiftとかRustとかが出来たんだと思う。
配列の境界チェックぐらいまでなら、トリッキーな書き方は全面禁止、ポインタは指している先の有効なメモリの範囲も覚えておく、とかでなんとか実現出来そうだけど。
他にも、オブジェクトの寿命の管理が厄介で、ポインタが指している先がまだ存在するかどうかがC言語ではあやふやになってしまう。プログラマの注意に委ねられてる。
GCの付いてる言語は、ポインタが指している限りは指されているオブジェクトは開放されないという方針で寿命の問題を解決してる。
Rustだと、あらゆる変数の寿命を自明な場合を除いて明示することになっていて、それによって、指している対象よりも寿命の長いポインタの類を禁止していて、ポインタが指している先が存在しなくなっている、というトラブルを排除している。
C言語のコンパイラに似たようなチェックを行うオプションを付けるアイデアもあり得そうだけど、多分無理。「危なそうなコードは却下するよう安全寄りに倒して、ちょっとでも駄目そうな可能性のあるプログラムはエラー。あるルールに従った明らかに安全なコードだけが許されるから、既存のコードもちゃんとルール通りに書き直せ」という感じにできれば良いんだけど。Rustがそんな感じのノリの言語なんだけど、プログラマがしばしば、寿命チェッカが厳しすぎる、あちこちに非自明な寿命の定義を書き加えないとコンパイルが通らない、と嬉し涙を流している。ので、言語仕様上その手の事を書けないC言語のコンパイラにやらせようとすると、ごく限られた書き方だけを使った効率の悪いプログラムしかコンパイル出来ないような、残念なコンパイラになってしまう。
Re: (スコア:0)
何故今でもC言語を使う必要があるかというと、あえてそういうチェックを外す必要のある低レイヤーの実装に必要だからで、そんなお節介な仕様を標準化されても「C言語でなければならない人」にとっては迷惑なだけではないかと。
逆にそうした保護を言語仕様でやってもらわなければならない用途には、今や他の言語を選ぶべきなんじゃないですかね。
Re: (スコア:0)
トレードオフになるよね
Re: (スコア:0)
Cの利便性を保ったまま、ちょっとしたコーディング規則を設ければそこそこ安全で、
コンパイルオプションでセキュアの強制もできるというのは
すでにC++で実現されてるから、変な制約のついた変形C言語は今から作る必要はないだろ。
Re: (スコア:0)
昔はそういうチェックを自動でやってくれる言語(コンパイラがするか実行時チェックかは措くとして)がいろいろあったと思うが、今は猫も杓子もc言語、c言語を使わぬ者プログラマに非ず、という雰囲気でしてねえ。
K&Rの時代には、変数名関数名も極力短く(つまりはタイプ量を少なく)していたのが、その後はタイプ量など気にせず長い名前にするようになったし。
Re:標準設定の問題? (スコア:2)
今そんなにc流行ってんすか
あまりそんな気はしないですが、どこの業界なんでしょう
Re: (スコア:0)
というかCはもう流行ったりはしないけど、かといって無くなれば困るって存在。
自然言語に例えればラテン語みたいなもんだろ。
だいたいPythonやgoみたいな「流行りの言語」なんてのは結局Cの拡張だしね。
Re: (スコア:0)
K&Rの時代を引き合いに出してるってことは、「今」=「C89以降」なんじゃね?
Re: (スコア:0)
短い識別子はコンパイラとカリンカの制限のためでは
Re: (スコア:0)
snprintf は sprintf よりはセキュアだけど、サイズを間違えたらバッファオーバランする。
あと、strcpy とか strcmp とかの非セキュア関数の代替関数はどうしよう。
Re: (スコア:0)
Re: (スコア:0)
逆だったらCの評価も変わったんだろうな。
標準関数はセキュアだけど、非セキュアなことをやりたい時に代替関数を使えば低レベルなところも触れるみたいな。
Re: (スコア:0)
単なる例だと思うけれど、 snprintfで指定するサイズ間違える時点ですでに使い方がおかしい。
お作法無視して無頓着に簡略化してコード書くからおかしなことになるだけで
C言語の脆弱性はプログラマがそういう書き方しているからとしかおもわないんだよなー
C言語でのリソース管理はプログラマのお仕事ですよと。
セキュア関数って基本は、車輪の再開発程度にしか思えないんだけど
NUL終端してない文字列とかあそこまで意識する必要があるのかね。。
そういうのって文字列じゃなくてバイナリデータの扱いにするだけと思うのだけれど
Re: (スコア:0)
snprintf の n が何のためにあるのか知らない人がいるのですよ。
n に何を渡すか分かってないから、結果それで防止できるはずのバグが防止できないとかよくある。
Re: (スコア:0)
snprintfはsprintfの相対的なセキュア版でしかないからね。
意味がわからない方が良識的だと思う。