メインコンテンツ

CERT C: Rec.INT00-C

Understand the data model used by your implementation(s)

説明

ルール定義

実装に使用されているデータ モデルを理解します。1

Polyspace 実装

ルール チェッカーは以下の問題をチェックします。

  • 基本型の宣言および変数や関数の定義の使用

  • 整数のオーバーフロー

  • 整数定数のオーバーフロー

  • 書式文字列指定子と引数の不一致

チェッカーの拡張

入力値が不明であり、入力のサブセットのみがエラーの原因として考えられる場合、既定の Bug Finder 解析では "整数定数のオーバーフロー" および "整数定数のオーバーフロー" が検出されない場合があります。特定のシステム入力値を原因とする違反の有無をチェックするには、より厳密な Bug Finder 解析を実行してください。特定のシステム入力値から欠陥を見つけるための Bug Finder チェッカーの拡張を参照してください。

すべて展開する

問題

この問題は、基本的な数値型としてのデータ型に、ビット単位の有効なサイズが含まれていない場合、または一般的に使用されるサイズ関連の単語が含まれていない場合に発生します。Polyspace® は、整数型、浮動小数点型、複素数型を基本的な数値型とみなします。ビット単位の有効なサイズは、8 の倍数です。サポートされているサイズ関連の単語は、bit、byte、word、およびその他の一般的なキーワードです。

リスク

割り当てられるメモリ量が重要な場合、特定長の型を使うことで各オブジェクトに予約されたストレージの量が明確になります。

例 - 定義での基本型の直接使用

この例は、基本的な数値型に対して準拠している型と非準拠の型を示しています。基本的な数値型の型でビット単位の有効なサイズを指定していない場合、Polyspace は違反を報告します。wordbyte などのキーワードを使用したサイズの指定は、このルールに準拠しています。

typedef unsigned int uint32_t;     /* Compliant */
typedef unsigned short WORD;       /* Compliant */
typedef unsigned int DWORD;        /* Compliant */
typedef unsigned long qword;       /* Compliant */


int x = 0;                         /* Non compliant */
uint32_t y = 0;
問題

整数のオーバーフローは、整数変数に対する演算が、結果のデータ型では表せない値になる可能性がある場合に発生します。変数のデータ型によって、変数ストレージに割り当てられるバイト数が決まり、許容される値の範囲が制限されます。

異なる浮動小数点型への正確なストレージ割り当てはプロセッサに依存します。ターゲット プロセッサ タイプ (-target)を参照してください。

リスク

符号付き整数のオーバーフローにより、未定義の動作が発生します。

修正方法

修正方法は欠陥の根本原因によって異なります。多くの場合、結果の詳細には欠陥につながる一連のイベントが表示されます。このイベント リストを使用して、オーバーフローの発生した計算で変数がどのように現在の値を取得したのかを確認します。そのシーケンス内のどのイベントについても修正を実装できます。結果の詳細にイベント履歴が表示されない場合は、ソース コード内で右クリック オプションを使用して逆のトレースを行い、これまでの関連するイベントを確認できます。Polyspace デスクトップ ユーザー インターフェイスでの Bug Finder の結果の解釈も参照してください。

この欠陥は次のようにして修正できます。

  • すべての値に適応できるように、演算の結果に対してより大きいデータ型を使用。

  • オーバーフローにつながる値をチェックし、適切なエラー処理を実行。

通常、オーバーフローを回避するために、次のいずれかの手法を試します。

  • 整数変数値を符号付き整数の範囲の半分の範囲内に制限。

  • オーバーフローする可能性がある演算で、オーバーフローにつながる可能性がある条件をチェックし、演算の結果を使用する方法に応じてラップ アラウンド動作または飽和動作を実装。結果が予測可能になり、以降の計算で安全に使用できます。

以下の修正例を参照してください。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

例 - 整数の最大値に加算する
#include <limits.h>
typedef int int32;
int32 plusplus(void) {

    int32 var = INT_MAX;
    var++;   //Noncompliant           //Noncompliant
    return var;
}

この関数の 3 番目のステートメントで、変数 var は 1 つ増加しています。しかし var の値は整数の最大値であるため、整数の最大値に 1 を加えると int では表現できません。

修正 — 異なるストレージ型

1 つの修正方法として、データ型を変更することができます。演算結果をより大きいデータ型に保存します (32 ビット マシンでは、intlong は同じサイズです)。この例では、32 ビット マシンで int ではなく long long を返すことでオーバーフロー エラーが修正されます。

#include <limits.h>
typedef int int32;
typedef long long llint; 
llint plusplus(void) {

    llint var = INT_MAX;
    var++;   //Compliant          
    return var;
}
問題

整数定数のオーバーフローは、コンパイル時の定数を、その値を格納できないデータ型をもつ符号付き変数に代入すると発生します。n ビット符号付き整数は、範囲 [-2n-1, 2n-1-1] 内の値を保持します。

たとえば、c は 8 ビットの符号付き char 型の変数であるため、値 255 を保持できません。

signed char c = 255;

基本型のサイズを判別するために、Bug Finder では [ターゲット プロセッサ タイプ] (-target) の指定が使用されます。

リスク

定数のオーバーフローの既定の動作は、コンパイルやプラットフォームによって異なる場合があります。定数のオーバーフローを維持するとコードの移植性が低くなる可能性があります。

コンパイラでオーバーフローした定数が警告を伴ってラップ アラウンドされる場合でも、ラップ アラウンドの動作は意図されたものではなく、予期しない結果を引き起こす可能性があります。

修正方法

定数値が意図したものかどうかをチェックします。値が正しい場合は、より大きい可能性のある別のデータ型をその変数に使用します。

例 - マクロ展開での定数のオーバーフロー
#define MAX_UNSIGNED_CHAR 255  //Noncompliant
#define MAX_SIGNED_CHAR 127 //Noncompliant

void main() {
    char c1 = MAX_UNSIGNED_CHAR;
    char c2 = MAX_SIGNED_CHAR+1;
}

この例では、1 つ以上のマクロを使用するとオーバーフローが起こるため、マクロに欠陥が表示されます。この欠陥を再現するには、[ターゲット プロセッサ タイプ] (-target) を使用します。ここで、char は、既定では符号付きになります。

修正 — 別のデータ型を使用

1 つの修正方法として、オーバーフローする変数に別のデータ型を使用します。

#define MAX_UNSIGNED_CHAR 255 
#define MAX_SIGNED_CHAR 127
typedef unsigned char uchar;
void main() {
    uchar c1 = MAX_UNSIGNED_CHAR;
    uchar c2 = MAX_SIGNED_CHAR+1;
}
問題

書式文字列指定子と引数の不一致は、printf などの書式設定付き出力関数の書式指定子が、それに対応する引数と一致しない場合に発生します。たとえば、unsigned long 型の引数の書式指定は %lu でなければなりません。

リスク

書式指定子と対応する引数の間の不一致により、未定義の動作が発生します。

修正方法

書式指定子が対応する引数と一致することを確認します。たとえば、次の例では、%d 指定子は文字列引数 message に一致せず、%s 指定子は整数引数 err_number に一致しません。

  const char *message = "License not available";
  int err_number = ;-4
  printf("Error: %d (error type %s)\n", message, err_number);
2 つの書式指定子を入れ替えると、問題が修正されます。書式指定子の詳細は、関数 printf の仕様を参照してください。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

例 - 浮動小数点の出力
#include <stdio.h>
typedef unsigned long UL;
void string_format(void) {

    UL fst = 1;

    printf("%d\n", fst); //Noncompliant //Noncompliant
}

printf ステートメントで、書式指定子 %dfst のデータ型と一致していません。

修正 — 符号なしの long 書式指定子を使用

1 つの修正方法として、%lu 書式指定子を使用することができます。この指定子は fstunsigned 整数型および long サイズに合致します。

#include <stdio.h>
typedef unsigned long UL;
typedef int int32;
void string_format(void) {

    UL fst = 1;

    printf("%lu\n", fst); //Compliant
}
修正 — 整数引数を使用

1 つの修正方法として、書式指定子と一致するように引数を変更することができます。fst を書式指定子と一致するよう整数に変換し、値 1 を出力します。

#include <stdio.h>
typedef unsigned long UL;
typedef int int32;
void string_format(void) {

    UL fst = 1;

    printf("%d\n", (int32)fst); //Compliant
}

チェック情報

グループ: Rec.04.整数 (INT)

バージョン履歴

R2019a で導入

すべて展開する


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.