メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

CERT C++: EXP39-C

Do not access a variable through a pointer of an incompatible type

説明

ルール定義

互換性のない型のポインターを通じて変数にアクセスしないようにします。1

Polyspace 実装

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

  • 関連のないポインター型へのポインターの変換

  • 最初に再初期化せずに、再割り当てされたメモリを別の型のオブジェクトから読み取る

.

すべて展開する

問題

この問題は、ポインターを関連しない型のポインターに変換すると発生します。チェッカーは、struct 型のオブジェクトを指すポインターと、同じ struct 型の最初のメンバーを指すポインターとの間を含む、すべてのポインター変換にフラグを設定します。ポインターから非ポインター型への間接的な変換は検出されません。

リスク

関連しない型のポインター間のキャストの結果は、C 標準では未指定です。このような変換は予期しない動作の原因になる可能性があります。

修正方法

関連しない型へのポインターの変換を回避します。コードとロジックをリファクタリングして、ポインター変換の必要性を小さくします。

問題

この問題は、以下の操作を順に実行すると発生します。

  1. 元の割り当てとは異なる型のオブジェクトにメモリを再割り当てする。

    たとえばこのコードの抜粋では、本来 struct A* 型のポインターに割り当てられていたメモリが、struct B* 型のポインターに再割り当てされます。

    struct A;
    struct B;
    
    struct A *Aptr = (struct A*) malloc(sizeof(struct A));
    struct B *Bptr = (struct B*) realloc(Aptr, sizeof(struct B));

  2. 再割り当てされたメモリを最初に再初期化せずに、このメモリから読み取る。

    再割り当てされたメモリを指すポインターでの読み取りアクセスは、ポインター デリファレンスまたは配列のインデックス付けにおいて発生する可能性があります。const 修飾子付きオブジェクトへのポインターを受け取る関数に、対応するパラメーターとしてこのポインターを渡す操作も、読み取りアクセスとしてカウントされます。

リスク

再初期化されていない再割り当てメモリからの読み取りは、未定義の動作です。

修正方法

再割り当ての後、最初の読み取りアクセスの前にメモリを再初期化します。

チェッカーでは、再割り当てされたメモリを指すポインターでの書き込みアクセスすべてが (オブジェクトの再初期化が部分的である場合でも)、再初期化の要件を満たしているものと解釈されます。再割り当てされたメモリを指すポインターでの書き込みアクセスは、ポインター デリファレンスと配列のインデックス付けにおいて発生する可能性があります。const 修飾子付きでないオブジェクトへのポインターを受け取る関数に、対応するパラメーターとしてこのポインターを渡す操作も、書き込みアクセスとしてカウントされます。

例 - 非準拠:最初に再初期化を行わずに、再割り当てされたメモリから読み取る
#include<cstdlib>

struct group {
    char *groupFirst;
    int groupSize;
};

struct groupWithID {
    int groupID;
    char *groupFirst;
    int groupSize;
};

char* readName();
int readSize();

void createGroup(int nextAvailableID) {
    struct group *aGroup;
    struct groupWithID *aGroupWithID;
    
    aGroup = (struct group*) malloc(sizeof(struct group));
    aGroup->groupFirst = readName();
    aGroup->groupSize  = readSize();
    
    if(!aGroup) {
        /*Handle error*/
    }
    
    /* Reassign to group with ID */
    aGroupWithID = (struct groupWithID*) realloc(aGroup, sizeof(struct groupWithID));
    if(!aGroupWithID) {
        free(aGroup);
        /*Handle error*/
    }
    
    if(aGroupWithID -> groupSize > 0) { /* Noncompliant */
        /* ... */
    }
    
    /* ...*/
    free(aGroupWithID);
}

この例では、関数 malloc を使用して group* ポインターに割り当てられたメモリを、関数 realloc を使用して、groupWithID* ポインターに再割り当てします。再割り当てされたメモリを再初期化する前に、このメモリへの読み取りアクセスが行われます。

修正 – 再初期化の後、最初の読み取りの前にメモリを再割り当てする

最初の読み取りアクセスの前に、groupWithID* ポインターに割り当てられているメモリを再初期化します。メモリのすべてのビットは、関数 memset を使用して再初期化できます。

#include<cstdlib>
#include<cstring>

struct group {
    char *groupFirst;
    int groupSize;
};

struct groupWithID {
    int groupID;
    char *groupFirst;
    int groupSize;
};

char* readName();
int readSize();

void createGroup(int nextAvailableID) {
    struct group *aGroup;
    struct groupWithID *aGroupWithID;
    
    aGroup = (struct group*) malloc(sizeof(struct group));
    aGroup->groupFirst = readName();
    aGroup->groupSize  = readSize();
    
    if(!aGroup) {
        /*Handle error*/
    }
    
    /* Reassign to group with ID */
    aGroupWithID = (struct groupWithID*) realloc(aGroup, sizeof(struct groupWithID));
    if(!aGroupWithID) {
        free(aGroup);
        /*Handle error*/
    }
    
    memset(aGroupWithID, 0 , sizeof(struct groupWithID));
    /* Reinitialize group */
    if(aGroupWithID -> groupSize > 0) { 
        /* ... */
    }
    
    /* ...*/
    free(aGroupWithID);
}

チェック情報

グループ: 02.式 (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.