2006/10/05
ADEXに整数オーバーフローのバグを発見 (ADEXの呪いパート2)
# ADEXに関しては、「ADEXの呪い」(http://dev.ariel-networks.com/Members/inoue/adex)を参照してください。
アリエルの技術の中で、"state of the art"と呼べそうな技術は、ADEXぐらいですが、高度すぎて呪いも深いものがあります。
実際のコードは違うのですが、本質は次のサンプルコードと等価なバグでした。
#include <stdio.h> #include <stdlib.h> static int cmp(const void *lhs, const void *rhs) { int64_t l = *(int64_t*)lhs; int64_t r = *(int64_t*)rhs; return l - r; /* integer overflow bug */ } int main(int argc, const char **argv) { int64_t arr[] = { 1<<10, 1, 2, (int64_t)1<<40, 1<<20, 666 }; int i; qsort(arr, sizeof arr/sizeof arr[0], sizeof(int64_t), cmp); for (i = 0; i < sizeof arr/sizeof arr[0]; i++) { printf("%lld\n", arr[i]); } return 0; }
最後のprintf(3)はソート結果を表示しているだけなので、本質はcmp()関数とqsort(3)の呼び出しの部分だけです。
int64_t値の引き算の結果(64bit)がintに対してオーバーフローします。このため、配列中の値同士の差が大きい場合、ソートが正しく機能しません。
gcc(手元はバージョン3.3.5)に-Wallをつけても、警告を出してくれません。
お客さんからのバグ報告で「再現性のポイントとして(マージ対象の文書の作成)時間を空ける」という指摘がありました。 実に鋭い指摘でした。 AirOneは時刻を64bitで管理していますが、約1時間で31bitの範囲を越えます。
手元で頑張って再現しようとしても再現しないわけです。せっせと文書を作ってマージさせても再現はしません。一時間待ってから(時計を進めてもいいですが)マージしてれば再現したのでしょう。
- Category(s)
- カテゴリなし
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/inoue/integer-overflow-bug/tbping