数値のバリデーションは無意味なのか?

(更新日: 2018/03/05)

数値の入力にはバリデーションは要らない、と考えているケースが少なからずあるようです。本当に数値に対するバリデーションは無意味なのでしょうか?

数値にバリデーションは必要ないとする理由

数値にバリデーションが必要ない、とする理由は以下のような物だと思います。

  • どんな入力値でも数値には変換できる
  • 無効な入力なら0などにすれば良いだけ
  • 言語が任意精度整数型(Ruby, Python3など)をサポートしている

どんな入力値でも数値には変換できる

C/C++でプログラミングをしている方でも、アプリケーションのコードばかりを書いていると1バイト、2バイト整数、もしかすると4バイト(32ビット)整数でさえ意識していないかも知れません。整数と言えば8バイト(64ビット)整数であることが前提の方も少なくないと思います。

しかし、今でも低いレベルのコードでは普通に1,2,4バイトの整数が使われています。PHPのようにCPUのワードサイズに整数値の範囲が影響される言語も少なからずあります。

固定精度の整数値の場合、オーバーフロー/アンダーフローのリスクを無視できません。

無効な入力なら0などにすれば良いだけ

無効な入力を0などに変換して取り敢えず動作するプログラムにすることは可能です。しかし、無効な入力を0などの数値に変換するのは正しい動作ではありません。

「出力対策だけのセキュリティ設計」が誤りである理由

例えば、割り算を行う際の分母側の引数が0である場合、プログラマーなら誰でも知っているゼロ除算エラーが発生します。このような場合、0にはできません。

言語が任意精度整数型をサポートしている

Python3やRubyのように整数型が任意精度整数である言語もあります。四則演算も問題なく行えます。

しかし、プログラムの大部分はCやC++などの固定精度整数を利用しています。浮動小数点型にも精度があり、単純に丸め誤差を無視することもできません。CやC++で書かれたライブラリやAPI(Webサービス含む)を利用する場合には、パラメータの値が仕様の範囲内に収まっているか保障する必要があります。

言語が任意精度整数型をサポートしていても、整数値が正しく動作可能な範囲に収まるようアプリケーションプログラムが責任を持っています。ライブラリには”出鱈目な数値が渡された場合でも正しく動作させる”責任はありません。責任がないというより、原理的/論理的に出鱈目な入力で正しく動作できません。

例えば、ゼロ除算が行われるとどうしようもありません。固定精度整数を持つ整数型の場合はオーバーフロー/アンダーフローするしかありません。ライブラリの仕様としてオーバーフロー/アンダーフローの場合に例外としてエラーを返すことは可能です。しかし、オーバーフロー/アンダーフローすは正しくない動作であることに変わりはありません。

まとめ

テキストインターフェースが中心のWebアプリケーションでは”文字列型の入力”バリデーションが最も重要なデータバリデーションです。しかし、数値の入力を必ず整数型/浮動小数点型に変換1しているとしても、数値型データのバリデーション(範囲の検証)は欠かせません。数値型データ範囲のバリデーションはISO 27000/ISMSの要求事項でもあります。

数値のオーバーフロー/アンダーフロー、精度問題は見過ごされがちなので注意が必要です。2

結局のところ、プログラムは正しい入力(=妥当な入力 – これには入力ミスなども含む)でしか正しく動作することは出来ません。データ型を問わず、正しい入力であることを保障するのはアプリケーションプログラマの責任です。

入力値の種類は3種類しかない

 

 

 


  1. 本来は”文字列型”から”数値型”の変換前に、文字列として妥当であるか検証すべきです。 
  2. 固定精度整数のC/C++プログラマが大量の整数オーバー/アンダーフロー脆弱性を作ってきたことからも、注意が必要であることは明らかです。 

Comments

comments