User Tools

Site Tools


ja:rule:num:任意精度型が必要な場合はgmp整数を利用する

任意精度型が必要な場合はGMP整数を利用する

PHPの整数型は32ビットOSでは符号付き32bit整数、64ビットOSでは符号付き64bit整数となる。この範囲を超える整数を取り扱う場合で演算が必要な場合はGMP整数を利用する。1)これはデータベースなど、任意精度型のデータ型をサポートしている外部システムを利用する場合に特に重要である。

PHPには任意精度型整数(無限精度整数)を取り扱えるBCMathとGMPモジュールがある。BCMathはデフォルトでコンパイルされ常に利用可能であるが、GMPモールはデフォルトで+-/*%などの演算オペレータが利用できる。GMPモジュールを利用した演算は将来的にデフォルトで利用できるようになる可能性が高い。このため可能な場合はGMPモジュールの利用が好ましい。

現在のPHPは任意精度の浮動小数点型をサポートする機能は持っていない。

ここではRDBMSのPostgreSQLを例として利用する。しかし、任意精度型を持つシステム(PHPを含む)の場合は出力先のデータ型と整合性が保てることに注意しなければならない。非適合コード、適合コードは以下のテーブル定義を持つデータベースとする。

CREATE TABLE sample (
  id SERIAL NOT NULL, -- SERIAL is signed 32 bit integer
  int8 INT8, -- INT8 is signed 64 bit integer
  num NUMERIC(100, 0) -- 整数100桁
);

非適合コード例

非適合コードを実行してもエラーにはならない。これは符号付き64ビット整数がオーバーフローした場合に自動的に浮動小数点型に変換されるからである。実際には浮動小数点型で表現可能な範囲まで丸められて不正確な値が保存される。

<?php
// This code is for 64 bit OS
$db = pg_connect('host=localhost');
if (!$db) {
  throw new Exception('Cannot connect to database');
}
 
$myint = 1234567890*1234567890000000; // Exceeds signed 64 bit integer range.
 
$sql = 'INSERT INTO sample (num) VALUES ($1)';
$ret = pg_query_params($sql, [$myint]);
if ($ret === FALSE) {
  throw new Exception('Query failed');
}
?>
  • 保存される$myint - 1524157875019100000000000
  • 正確な値の場合 - 1524157875019052100000000

適合コード例(GMP)

<?php
// This code is for 64 bit OS
$db = pg_connect('host=localhost');
if (!$db) {
  throw new Exception('Cannot connect to database');
}
 
// GMP整数に変換して精度を保つ
$x = gmp_init(1234567890);
$y = gmp_init(1234567890000000);
$myint = $x*$y; // Exceeds signed 64 bit integer range.
 
$sql = 'INSERT INTO sample (num) VALUES ($1)';
$ret = pg_query_params($sql, [$myint]);
if ($ret === FALSE) {
  throw new Exception('Query failed');
}
?>
  • 保存される$myintは正確な値 - 1524157875019052100000000

例外

浮動小数点型で表現可能な値に丸められても問題にならない場合は適用しなくてよい。

リスク評価

保存されるデータが不完全となる。

Rule Severity Likelihood Remediation Cost Priority Level
IDS05-J medium likely medium P4 L3

関連ガイドライン

参考文献

1)
演算が必要ない場合は無用なキャストを行ってはならない
ja/rule/num/任意精度型が必要な場合はgmp整数を利用する.txt · Last modified: 2016/03/19 01:11 by yohgaki

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki