メインコンテンツ

CERT C: Rec.EXP09-C

型または変数のサイズを判別する場合は sizeof を使用する

説明

ルール定義

型または変数のサイズを判別する場合は sizeof を使用します。1

Polyspace 実装

ルール チェッカーは、"メモリの操作に使用するオブジェクトのサイズがハードコードされています" をチェックします。

すべて展開する

問題

問題 "メモリの操作に使用するオブジェクトのサイズがハードコードされています" は、ハードコードされている定数を次のメモリ関数のメモリ サイズ引数として使用する場合に発生します。

  • malloccalloc などの動的メモリ割り当て関数。

  • memcpymemmovememcmpmemset などのメモリ操作関数。

メモリ サイズをハードコードしている場合、文字列リテラルを使用してメモリ操作を実行すると、Polyspace® はこのルールの違反を報告しません。

リスク

オブジェクトのサイズをハードコードすると、コードが、型のサイズが異なるアーキテクチャに移植できません。定数値がオブジェクトのサイズと同じでない場合、バッファーがオーバーフローしたり、しなかったりする可能性があります。

修正方法

メモリ関数のサイズ引数には、sizeof(object) を使用します。

例 - 4 バイトの整数ポインターを仮定
#include <stddef.h>
#include <stdlib.h>
enum {
    SIZE3   = 3,
    SIZE20  = 20
};
extern void fill_ints(int **matrix, size_t nb, size_t s);

void bug_hardcodedmemsize()
{
    size_t i, s;

    s = 4;
    int **matrix = (int **)calloc(SIZE20, s); //Noncompliant
    if (matrix == NULL) {
        return; /* Indicate calloc() failure */
    }
    fill_ints(matrix, SIZE20, s);
    free(matrix);
}

この例では、メモリ割り当て関数 calloc が 4 バイトのメモリ サイズで呼び出されています。このメモリは整数ポインターに対して割り当てられています。整数ポインターは、ターゲットによって 4 バイトよりも大きい場合も小さい場合もあります。整数型ポインターが 4 バイトでない場合、プログラムは失敗する可能性があります。

修正 — sizeof(int *) を使用

calloc を呼び出す際、ハード コードしているサイズを sizeof の呼び出しに置き換えます。この変更によりコードの移植性が高くなります。

#include <stddef.h>
#include <stdlib.h>
enum {
    SIZE3   = 3,
    SIZE20  = 20
};
extern void fill_ints(int **matrix, size_t nb, size_t s);

void corrected_hardcodedmemsize()
{
    size_t i, s;

    s = sizeof(int *);
    int **matrix = (int **)calloc(SIZE20, s);
    if (matrix == NULL) {
        return; /* Indicate calloc() failure */
    }
    fill_ints(matrix, SIZE20, s);
    free(matrix);
}

memset でハードコードされているサイズ

この例では、関数 clean_sensitive_memory が機密情報をメモリからクリアします。ここで、memset のメモリ サイズ引数は 64 バイトとしてハードコードされています。s->data64 バイトを格納できない場合、プログラムは失敗し、機密情報がメモリに残る可能性があります。Polyspace はメモリ操作に対してこのルールの違反を報告します。

#include<string.h>

struct sensitiveInfo
{
    unsigned char data[64];
    int length;
};

char key[64];

void clean_sensitive_memory (struct sensitiveInfo *s)
{
    memset (s->data, 0, 64);          //Defect
    memset ((void *) key, 0, 64);  //Defect
}

修正 — サイズ引数に sizeof() を使用

この違反を修正するには、ハードコードされているメモリ サイズを sizeof() の呼び出しに置き換えます。

#include<string.h>

struct sensitiveInfo
{
    unsigned char data[64];
    int length;
};

char key[64];

void clean_sensitive_memory (struct sensitiveInfo *s)
{
  memset (s->data, 0, sizeof (s->data));	//Fixed
  memset ((void *) key, 0, sizeof(key)); //Fixed
}

チェック情報

グループ: Rec.03.式 (EXP)

バージョン履歴

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.