JPCERT コーディネーションセンター

FLP06-C. 浮動小数点数の演算時には整数を浮動小数点数に変換する

浮動小数点型の変数へ代入する値を整数演算で求めると、情報が欠損する可能性がある。式中の整数オペランドのいずれかを浮動小数点型に変換することで、この問題を回避できる。

整数値から浮動小数点値への変換、あるいはその逆の変換を行う場合、未定義の動作の発生を避けるために適切な範囲チェックを行うことが重要である。(「FLP34-C. 浮動小数点の型変換は変換後の型の範囲に収まるようにする」を参照。)

違反コード

以下のコード例では、整数に対する除算と乗算が行われ、その結果が浮動小数点に変換されている。結果として、浮動小数点変数である de、および f は正しく初期化されない。なぜならば、値が浮動小数点に変換される前に整数演算が行われるからである。結果の値はもっとも近い整数値に切り捨てられるか、オーバーフローする恐れがある。

void func(void) {
  short a = 533;
  int b = 6789;
  long c = 466438237;

  float d = a / 7; /* d の値は 76.0 */
  double e = b / 30; /* e の値は 226.0 */
  double f = c * 789; /* f の値はオーバーフローの結果、負になりうる */
}
適合コード (浮動小数点定数)

以下の適合コードでは、初期化式の評価が浮動小数点演算で行われるようにするため、除算式中のオペランドの少なくとも1つを浮動小数点型にしている。

void func(void) {
  short a = 533;
  int b = 6789;
  long c = 466438237;

  float d = a / 7.0f; /* d の値は 76.14286 */
  double e = b / 30.; /* e の値は 226.3 */
  double f = (double)c * 789; /* f の値は 368019768993.0 */
}
適合コード (型変換)

以下の適合コードでは、計算に使う整数をまず浮動小数点型の変数に格納し、そのあとに算術演算を行っている。これにより、オペランドの少なくとも一方は浮動小数点数となり、続く算術演算が浮動小数点演算として行われることが保証される。

void func(void) {
  short a = 533;
  int b = 6789;
  long c = 466438237;

  float d = a;
  double e = b;
  double f = c;

  d /= 7; /* d の値は 76.14286 */
  e /= 30; /* e の値は 226.3 */
  f *= 789; /* f の値は 368019768993.0 */
}
例外

FLP06-EX0: 型変換が行われる前に整数演算が行われることが望ましい場合もある(たとえば trunc() 呼び出しを不要にするため)。プログラマが意図的にそうしている場合、それが意図されたものであることをコードを保守する人間が理解できるよう、明確にドキュメントしておくべきである。

リスク評価

整数と浮動小数点の間で不適切な型変換が行われると、予期せぬ結果、特に精度の欠損が引き起こされる恐れがある。また、これらの予期せぬ結果には、オーバーフロー、未定義の動作が含まれることがある。

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

FLP06-C

P6

L2

自動検出

ツール

バージョン

チェッカー

説明

Compass/ROSE

 

 

このルールの違反を検出できる。代入される値の型が float もしくは double であるが、代入の右辺値の式がすべて整数であるような代入式はこのルールの違反としてとらえられる

LDRA tool suite

8.5.4

442 S
443 S
444 S

実装済み

PRQA QA-C v8.2

4117
4118

部分的に実装済み

Splint

3.1.1

 

 

関連するガイドライン
CERT C コーディングスタンダード FLP34-C. 浮動小数点の型変換は変換後の型の範囲に収まるようにする 
CERT C++ Coding Standard FLP05-CPP. Convert integers to floating point for floating point operations
CERT Oracle Secure Coding Standard for Java NUM50-J. Convert integers to floating point for floating-point operations
MITRE CWE CWE-681, Incorrect conversion between numeric types
CWE-682, Incorrect calculation
参考資料
[Hatton 1995] Section 2.7.3, "Floating-Point Misbehavior"
翻訳元

これは以下のページを翻訳したものです。

FLP06-C. Convert integers to floating point for floating-point operations (revision 88)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter