4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHP7調査(5)整数型の引数のオーバーフローがエラーになった

Last updated at Posted at 2015-04-10

PHP7では、組み込み関数の整数型引数に整数で表現できない値を渡した場合にエラーになります。

float1.php
<?php
var_dump(array_fill(10000000000000000000, 3, "foo"));
string1.php
<?php
var_dump(array_fill("10000000000000000000", 3, "foo"));

これらを実行すると次のようなエラーが帰ってきます。

PHP Warning:  array_fill() expects parameter 1 to be integer, string given in /tmp/string1.php on line 2
NULL
PHP Warning:  array_fill() expects parameter 1 to be integer, float given in /tmp/float1.php on line 2
NULL

array_fillの第一引数はint型ですが(PHPマニュアルの「array_fill」参照)、これに整数以外の値を渡してエラーになっているのがわかります。

これはint型のタイプヒントの場合も同様です。

float2.php
<?php
function foo(int $i) {}
foo(10000000000000000000);
PHP Fatal error:  Uncaught TypeException: Argument 1 passed to foo() must be of the type integer, float given, called in /tmp/float2.php on line 3 and defined in /tmp/float2.php:2
Stack trace:
#0 /tmp/float2.php(3): foo(1E+19)
#1 {main}
  thrown in /tmp/float2.php on line 2

こうしたエラーメッセージを見ると浮動小数点数や文字列を渡したせいで怒られているように見えますが、実際には整数にキャストできない値を渡したせいで怒られています。具体的には、[PHP_INT_MIN, PHP_INT_MAX]の範囲外だと怒られます。

下記のように、整数の範囲内であれば浮動小数点数や文字列を渡しても期待通りに動きます。

float3.php
<?php
var_dump(array_fill(1.9, 3, "foo"));
/*
array(3) {
  [1]=>
  string(3) "foo"
  [2]=>
  string(3) "foo"
  [3]=>
  string(3) "foo"
}
*/
string3.php
<?php
var_dump(array_fill("1e10", 3, "foo"));
/*
array(3) {
  [10000000000]=>
  string(3) "foo"
  [10000000001]=>
  string(3) "foo"
  [10000000002]=>
  string(3) "foo"
}
*/

ちなみにPHP5までは、整数の範囲外の値を持つ浮動小数点数を整数にキャストした場合の挙動は未定義でした。実際に手元で試してみると非常に小さな整数にキャストされます。

$ php56 -r 'var_dump(array_fill(NAN, 3, "foo"));'
array(3) {
  [-9223372036854775808]=>
  string(3) "foo"
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "foo"
}

これに対応するPHP5のCソースコードを見ると、単にdoubleからlongにキャストするような処理になっています。このようなキャストでdoubleがlongの範囲外の場合の挙動はC言語として未定義で、結果は処理系依存・環境依存ということになります。Cレベルで未定義の挙動をPHPプログラマに提供してきたこと自体が残念仕様だったと思いますので、今回の修正は当然とも言えるでしょう。

# 参考

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?