数値型のオーバーフロー対策

数値型には固有の上限下限値があり、四則演算や数値型のダウンキャスト(範囲の大きい型から小さい型にキャストすること)数値が溢れることがあります。これをオーバーフローと言います。

オーバーフロー発生時の挙動は言語により異なりiOS/Androidとネイティブ開発言語では以下のような挙動になります。

・iOS/Swift
オーバーフロー時は例外をスローせずに処理を強制終了

・iOS/Objectve-C, Android/Java, Android/Kotlin
オーバーフロー時は値が不正確になったまま、処理が継続する。
例えばJavaのint型の最大値2147483647に1を足した場合、-2147483648となる。

Swift以外は数値が不正確なまま処理が継続するためより注意が必要です。

オーバーフローの発生時には以下のようなリスクがあります。

【リスク】
・オーバーフローが発生した場合、プログラムが予期せぬ挙動をする。
・ユーザー入力値を基に演算する場合に、オーバーフローを意図的に発生させる攻撃にさらされる。

【対策】
1.大きな数の計算が予想される場合はなるべく大きい数値型を使用する
対策としては一番単純なもので、なるべく数値範囲の大きい型を使用すれば、通常の演算の範囲ではオーバーフローが発生しにくくなります。
例えば整数型なら
Swiftであれば、Int64
Objective-C long long
Java/Kotlinなら Long
を使用すれば
-9,223,372,036,854,775,808~9,223,372,036,854,775,807
の範囲で計算できます。

それ以上の計算をしたい場合は、
JavaならBigInteger/BigDecimal
SwiftならNSDecimalNumberなどを使用します。

2.演算時にオーバーフローをチェックする
ユーザー入力値などのアプリ外部から来た数値を基に演算する部分など、特にオーバーフローの発生が見込まれる部分に関しては、その演算によりオーバーフローが発生しないか検証を行ってください。

検証方法は、各言語の組み込みAPIで用意されたオーバーフローの検知機能を有した演算関数を使用するのがベストプラクティスです。
例えばJava8以降のJavaならMath.xxExact()を使用するとオーバーフロー時は例外をスローします。

もし、言語のバージョンの都合でそれらが存在しない場合は、ライブラリを使用するか、独自実装をする必要があります。

オーバーフローはコンパイラでは検知できず、かつ実行時にも見かけ上正常に処理が継続するため、気づきにくい点です。新規実装時はもちろん、既存のアプリの演算部分やダウンキャスト時に発生する可能性がないかよく検証してみましょう。

目次に戻る