問題タブ [integer-overflow]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - Cの算術アンダーフローとオーバーフローとは何ですか?
Cプログラミングにおける算術アンダーフローとオーバーフローの意味は何ですか?
c - クイックソートの例 (K&R C 本) のバグ?
このクイックソートは、「v[左]...v[右] を昇順で」ソートすることになっています。K&R の C プログラミング言語 (第 2 版) からコピー (コメントなし):
にバグがあると思います
左 = INT_MAX - 1、右 = INT_MAX とします。これにより、整数オーバーフローが原因で未定義の動作が発生することはありませんか?
c++ - C/C++ で整数オーバーフローを検出する便利で信頼できる方法はありませんか?
いいえ、これは整数オーバーフローを検出する方法の複製ではありませんか? . 問題は同じですが、質問は異なります。
gcc コンパイラは、(-O2 を使用して) オーバーフロー チェックを最適化して取り除くことができます。次に例を示します。
gcc の人々は、これはバグではないと主張しています。C 標準によれば、オーバーフローは未定義の動作であり、コンパイラは何でも実行できます。どうやら、オーバーフローが発生しないことを前提としたものは何でも含まれているようです。残念ながら、これにより、コンパイラはオーバーフロー チェックを最適化できなくなります。
オーバーフローをチェックする安全な方法は、最近のCERT 論文に記載されています。この論文では、2 つの整数を加算する前に次のようなことを行うことを推奨しています。
どうやら、結果が有効であることを確認したい場合、一連の計算で +、-、*、/ およびその他の操作の前に、このようなことを行う必要があるようです。たとえば、配列インデックスが範囲外でないことを確認したい場合。これは非常に面倒なので、実際に誰も行っていません。少なくとも、これを体系的に行う C/C++ プログラムは見たことがありません。
さて、これは根本的な問題です:
配列にアクセスする前に配列インデックスをチェックすることは便利ですが、信頼性は高くありません。
CERT 法による一連の計算のすべての操作をチェックすることは信頼できますが、役に立ちません。
結論: C/C++ でオーバーフローをチェックする便利で信頼できる方法はありません!
標準が書かれたときにこれが意図されていたとは信じられません。
問題を解決できる特定のコマンド ライン オプションがあることは知っていますが、標準またはその現在の解釈に根本的な問題があるという事実は変わりません。
ここで私の質問は次のとおりです。gcc の人々は、オーバーフロー チェックを最適化して取り除くことを許可するときに「未定義の動作」の解釈を取りすぎているのでしょうか、それとも C/C++ 標準が壊れているのでしょうか?
追加された注: 申し訳ありませんが、私の質問を誤解している可能性があります。私は問題を回避する方法を尋ねているのではありません - それはすでに他の場所で回答されています。C 標準について、より基本的な質問をしています。オーバーフローをチェックする便利で信頼できる方法がない場合、言語自体が怪しいです。たとえば、境界チェックを使用して安全な配列クラスを作成した場合、安全であるはずですが、境界チェックを最適化して取り除くことができる場合はそうではありません。
規格がこれを可能にする場合、規格を改訂する必要があるか、規格の解釈を改訂する必要があります。
注 2 を追加: ここにいる人々は、「未定義の動作」という疑わしい概念について議論したがらないようです。C99 標準に 191 種類の未定義の動作がリストされているという事実 (リンク) は、ずさんな標準を示しています。
多くのプログラマーは、「未定義の動作」により、ハードディスクのフォーマットを含め、あらゆることを行うライセンスが得られるという声明をすぐに受け入れます。標準が整数オーバーフローを配列境界外への書き込みと同じ危険なカテゴリに分類しているのは問題だと思います。
これら 2 種類の「未定義の動作」が異なるのはなぜですか? なぜなら:
多くのプログラムは、整数のオーバーフローが無害であることに依存していますが、何があるか分からない場合に、配列境界の外側に書き込むことに依存するプログラムはほとんどありません。
配列の境界外に書き込むと、実際にはハードディスクをフォーマットするのと同じくらい悪いことをする可能性があり (少なくとも DOS のような保護されていない OS では)、ほとんどのプログラマーはこれが危険であることを知っています。
整数オーバーフローを危険な「なんでもあり」カテゴリに入れると、コンパイラが何をしているのかについて嘘をつくことを含め、コンパイラが何でもできるようになります (オーバーフロー チェックが最適化されていない場合)。
配列境界外への書き込みなどのエラーはデバッガーで見つけることができますが、最適化は通常デバッグ時にオフになっているため、オーバーフロー チェックを最適化して取り除くエラーは発見できません。
gcc コンパイラーは、整数オーバーフローの場合に「なんでもあり」ポリシーを明らかに控えています。オーバーフローが不可能であることを確認できない限り、ループなどの最適化を控える場合が多くあります。なんらかの理由で、gcc 関係者は、ここで「なんでもあり」ポリシーに従えばエラーが多すぎることを認識していましたが、オーバーフロー チェックを最適化して除外するという問題に対しては異なる態度をとっています。
たぶん、ここはそのような哲学的な問題を議論するのに適切な場所ではありません. 少なくとも、ここでのほとんどの回答は的外れです。これを議論するためのより良い場所はありますか?
c# - ASP.NETでの整数オーバーフローの停止
Acunetixを使用して、アプリケーションのセキュリティスキャンを実行します。最近、以下の整数の脆弱性エラーに遭遇しました。
私の知る限り、レポートはクエリ文字列内の整数オーバーフロー攻撃を阻止していないことを示しているようです。最終的に整数に解決されるクエリ文字列を使用しますが、使用する前に、最初に暗号化され、次に復号化され、intを使用してintに変換されConvert.ToInt32()
ます。代わりに使用する必要があることはわかっていますTryParse()
が、ハッカーがmaxより大きい整数値を入力したとしても、整数に変換しようとする前に復号化しようとすると失敗します。これは、私の意見では整数オーバーフローが発生する場所です。それは、復号化が失敗したときにエラーが発生しない限りですか?
私はこれについてかなり混乱していて、Google検索はc#やasp.netではなくc++のような管理されていない言語にほとんど関係しているのであまり役に立ちませんでした。どんな助けでも大歓迎です。
c - 意図的な値のオーバーフローは安全ですか?
この質問はおそらく愚かまたはパラノイダルですが、とにかく:-)。次のコードが与えられます:
定期的にオーバーフローし、そのような状況が適切に処理されることがわかっている場合hiRes
、このコードに何か問題がありますか?
更新:hiRes
答えはC標準で定義されている(符号付きまたは符号なし)
のタイプに依存するため、結果は私にとって非常に驚くべきものです(たとえばを参照)。
c++ - unsigned int と int の間で安全に static_cast するにはどうすればよいですか?
string
16 進数を表す8 文字があり、それをint
. この変換では、文字列"80000000"
以上のビット パターンを保持する必要があります。つまり、これらの数値は負になるはずです。残念ながら、素朴な解決策:
私のコンパイラでは動作しませんval > MAX_INT
(戻り値が 0 の場合)。val のタイプを に変更してint
も、大きい数値は 0 になります。SO に関するさまざまな回答からいくつかの異なるソリューションを試しましたが、まだ成功していません。
私が知っていることは次のとおりです。
- OpenVMS で HP の C++ コンパイラを使用しています (Itanium プロセッサを使用していると思います)。
sizeof(int)
私のコードが実行されるすべてのアーキテクチャで少なくとも 4 になります。- 数値 > INT_MAX から int へのキャストは実装定義です。私のマシンでは、通常は 0 になりますが、興味深いことに、値が大きすぎる場合にfrom
long
をキャストするとint
結果が返されます。INT_MAX
これを正しく行うのは驚くほど難しいか、少なくとも私にとってはそうでした。これに対するポータブルなソリューションを知っている人はいますか?
アップデート:
に変更static_cast
するreinterpret_cast
と、コンパイラ エラーが発生します。上記のコードでC スタイルのキャストを試すように促されたコメントreturn (int)val
で、うまくいきました。 このマシンで。 それは他のアーキテクチャでも安全ですか?
python - Python で整数オーバーフローをシミュレートする
Python 2 には と の 2 つの整数データ型がint
ありlong
、特に整数オーバーフローを回避するために、必要に応じてそれらの間で自動的に変換されます。
Python で C 関数をシミュレートしていますが、整数オーバーフローを再度有効にする標準的な方法があるかどうか疑問に思っています。ナンスについては、私は使用しました
同じことを行うためのより標準的な方法はありますか?
php - 64 ビットから 32 ビットへの PHP 非シリアル化整数
64 ビット サーバーでシリアル化されたオブジェクトを 32 ビット サーバーでシリアル化解除しようとしています。問題をオブジェクト内の整数に分離しました。ここに問題の小さな再現があります。
64 ビット マシンの場合:
32 ビット マシンの場合:
エラーを与える
これで、これらのシリアル化方法をクロス システム データ送信に使用すべきではないことがわかりました。ただし、データを別のシステムに移行しようとしているだけで、転送に積極的に使用することはありません。これは 1 回限りのことです。
これは整数オーバーフローが原因である可能性があると思いますが、32ビットサーバーでも次のようなことができます
そして、それはうまくいきます。PHP の整数型は double 型などにスケーリングされると思います。しかし、シリアル化を解除するときにそれを行わないのはなぜですか?
これらのオブジェクトのシリアル化を解除するにはどうすればよいですか? できない場合、それらを別のものに変換する方法はありますか? 最後に、PHP 自体で逆シリアル化メソッドを作成した人はいますか? または、プロトコルの詳細はありますか? それを使用して、それらの整数のカスタムケースを作成できます。
ありがとう。
注:元のデータにはアクセスできず、シリアル化された結果のみにアクセスできます。
c - argc=0 でプロセスを実行する
argc=0 のプロセスを実行することはできますか? プログラムを実行する必要がありますが、argc が 0 であることが非常に重要です。それを行う方法はありますか? argc = 0 のように見えるように、コマンド ラインに 2^32 個の引数を入れようとしましたが、引数の数には上限があります。
c - uint64_t整数の乗算を検出するとCがオーバーフローします
int64_tまたはuint64_tオペランドを使用した乗算演算がCでオーバーフローした場合に、効率的で移植性のあるチェック方法はありますか?
たとえば、uint64_tを追加するには、次のようにします。
しかし、私は乗算のための同様の単純な式に到達することはできません。
私に起こるのは、オペランドを高いuint32_t部分と低いuint32_t部分に分割し、オーバーフローをチェックしながらそれらの部分の乗算を実行することだけです。これは本当に醜く、おそらく非効率的です。
アップデート1:いくつかのアプローチを実装するいくつかのベンチマークコードが追加されました
アップデート2:JensGustedtメソッドが追加されました
ベンチマークプログラム:
これまでのところ、浮動小数点を使用してほとんどのケースをフィルタリングするケース4は、オーバーフローが非常に異常であると想定される場合に最速です。少なくとも、何もしない場合よりも2倍遅いだけの私のコンピューターではそうです。
ケース5は4よりも30%遅いですが、常に同じように実行されます。4の場合のように、処理を遅くする必要のある特別なケース番号はありません。