##C++のsize_tは範囲を超えるとどうなるか
C++のsize_tは範囲を超えるとどうなるか、実験して見ました。size_tはCとC++で使われるもので、どちらも脆弱性を作り込みやすい言語です。
メモリサイズを指定しているので、最大値の次が0とかになったら、バッファオーバーフローとかそういった脆弱性が出るのかなーと勝手に思っていて、それあんまり良くないなーと思いつつ、ちょっと実験してみます。
環境はClionを使ってみました。
#include <iostream>
int main() {
using namespace std;
size_t value = -1000;
cout << "valueの値は" << value << endl;
return 0;
}
これを走らせてみると、結果は以下のように
```
valueの値は18446744073709550616
つまり、0以下の数字を入れるとビットが反転して、すごい大きな数になるわけですね。
では、これは
#include
int main() {
using namespace std;
size_t value = 0;
value --;
cout << "valueの値は" << value << endl;
return 0;
}
結果は以下のように
valueの値は18446744073709551615
18446744073709551615が最大値なのかなーと思いつつ、以下のコードを実行してみました。
#include
int main() {
using namespace std;
size_t value = 18446744073709551615;
value ++;
cout << "valueの値は" << value << endl;
return 0;
}
結果は以下の通り
valueの値は0
つまるところ、size_tという型は、0に−1すると、18446744073709551615になり、18446744073709551615に+1すると0になる。
そこらへんにバッファオーバーフローとかを起こさせる要因が発生するのかなーと思ったりします。
18446744073709551615を超えることってあんまりないと思いますが、計算違いして、0以下の値になることはあると思います。
そういう時にエラーを投げてくれないって、結構危険な言語だと思いました。
ちなみに、こういう、範囲を超えたら値が反転するのは、C#とかではエラーとか返してくれるのかなと思って実験してみました。
using System;
namespace IntegerOverflow
{
class MainClass
{
public static void Main (string[] args)
{
uint i = 0;
i--;
Console.Write (i);
}
}
}
結果は以下の通り
4294967295
実験にはMacとMonoDevelopを使いました。完全に範囲を超えて、値が反転してますね。
エラーを投げてくれませんでした。
以下を実験してみると
using System;
namespace IntegerOverflow
{
class MainClass
{
public static void Main (string[] args)
{
uint i = 4294967295;
i++;
Console.Write (i);
}
}
}
以下の通り
0
なんで、値を超えた時に、値が反転するのか、考察してみます。言い換えれば、「なぜエラーを投げないか」を考察してみます。4294967295ってそんなにでかい値ではないと思うのですが、場合によってはこういうのってバグの元になると思います。
恐らく、パフォーマンスの理由によると思います。つまり、値が反転する場合にエラーを投げるには、加減乗除した時に、常に範囲が超えてないかチェックする機構を走らせる必要があるんだと思います。
それがかなりコストがかかる、そして場合によっては不可能なんじゃないかと思いますね。
だから、逆に言えば、バグハンティングはこういう、値が反転しそうなところを狙っていけば脆弱性とか発見できて、バグバウンティプログラムで稼げるのかなと思いますね。
突っ込みどころ満載だと思うので、コメント歓迎です。でも、いじめないでください。