integer overflow at int_of_string

OCaml をインストールして数日でバグを見つけた方を発見!!

新米CShaperの他言語日記(http://d.hatena.ne.jp/green_csharper/20090529/1243709860)

# 1073741824;;
- : int = -1073741824 <= コレは何??
# 1073741825;;
Characters 0-10:
  1073741825;;
  ^^^^^^^^^^
Error: Integer literal exceeds the range of representable integers of type int

すごい、これは気づかんかった。

1073741824 を16進で書くと 0x4000_0000。これは 31bit符号付整数では負の -1073741824 になります。32bit符号付整数で 0x8000_0000 が最早正ではなくて負数なのと同じ理由ですね。でも 1073741825 は符号付整数の範囲を超えるからエラーと言われるのに、1073741824 はエラーじゃなくってオーバーフローを許しているのはどうして?

で、Caml mantis を見たら、既に Xavier Leroy が二年前に答えています: http://caml.inria.fr/mantis/view.php?id=4210 (適当に和訳):

正しい 31bit符号付整数の文字列 "-1073741824" は、1073741824 という正に見える数に unary operator の - が付いている、という形でパースします。だから、1073741824 を範囲を超えているからエラー、とすると -1073741824 がパースできなくなるんよ。 だから 1073741824 は有り得ない数だけど、パースエラーにはしないようになってます。
これをちゃんとエラーとして弾くのはちょっと面倒だよね(but that's more work...)

という訳で華麗にスルーされちゃってますが、、、

私達にとってはこれは大いに困る。だって、データファイルに正数だと思って書きこんだこの大っきな数が実は負数で、その数を元に株取引したら、、、いやー恐ろしいですよね!! よりによっちゃあ、これ一つで会社つぶすことも可能じゃないですかね。

ちなみに 64bit 環境の 63bit整数でも同じことが起こりますよ: 4611686018427387904