メインコンテンツ

CERT C: Rec.MEM02-C

Immediately cast the result of a memory allocation function call into a pointer to the allocated type

説明

ルール定義

メモリ割り当て関数を呼び出した結果は、割り当てられた型へのポインターにすぐにキャストします。1

Polyspace 実装

ルール チェッカーは、"キャストに割り当てられた誤ったオブジェクト サイズ" をチェックします。

すべて展開する

問題

キャストに割り当てられた誤ったオブジェクト サイズはポインター変換時にポインターのアドレスが整列していない場合に生じます。ポインターを異なるポインター型に変換する際に、割り当てられたメモリのサイズは変換先のポインターのサイズの倍数でなければなりません。

リスク

整列していないポインターをデリファレンスすると、未定義の動作が発生し、プログラムがクラッシュする可能性があります。

修正方法

ポインター ptr1ptr2 に変換するとします。ptr1N バイトのバッファーを指し、ptr2type * ポインターで、sizeof(type)n バイトの場合、Nn の整数倍であることを確認します。

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

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

例 - ポインターの動的割り当て
#include <stdlib.h>

void dyn_non_align(void){
    void *ptr = malloc(13);
    long *dest;

    dest = (long*)ptr; //defect //Noncompliant
}

この例では、ptr から long* への変換に関する欠陥が報告されます。ptr に動的に割り当てられるメモリである 13 バイトは、dest のサイズである 4 バイトの倍数ではありません。この不整列のため、キャストに割り当てられた誤ったオブジェクト サイズの欠陥が生じます。

修正 — ポインターのサイズを変更

1 つの修正方法として、変換先のサイズの倍数となるポインター サイズを使用することができます。この例では、割り当てられるメモリを 13 ではなく 12 に変更して欠陥を解決します。

#include <stdlib.h>

void dyn_non_align(void){
    void *ptr = malloc(12);
    long *dest;

    dest = (long*)ptr;
}
例 - ポインターの静的割り当て
void static_non_align(void){
    char arr[13], *ptr;
    int *dest;

    ptr = &arr[0];
    dest = (int*)ptr; //defect //Noncompliant
}

この例では、行 6 で ptrint* に変換する際に欠陥が報告されます。配列 arr のサイズは 13 バイトであるため、ptr のメモリ サイズは 13 バイトです。dest のサイズは 4 バイトで、13 の倍数ではありません。この不整列のため、キャストに割り当てられた誤ったオブジェクト サイズの欠陥が生じます。

修正 — ポインターのサイズを変更

1 つの修正方法として、変換先のサイズの倍数となるポインター サイズを使用することができます。この例では、配列 arr のサイズを 4 の倍数に変更して欠陥を解決します。

void static_non_align(void){
    char arr[12], *ptr;
    int *dest;

    ptr = &arr[0];
    dest = (int*)ptr;
}
例 - 関数による割り当て
#include <stdlib.h>

void *my_alloc(int size) { 
    void *ptr_func = malloc(size); 
    if(ptr_func == NULL) exit(-1); 
    return ptr_func; 
}

void fun_non_align(void){
    int *dest1;
    char *dest2;

    dest1 = (int*)my_alloc(13);  //defect //Noncompliant
    dest2 = (char*)my_alloc(13); //not a defect
}

この例では、行 11 において my_alloc(13) で返されるポインターを int* に変換する際に欠陥が生じます。my_alloc(13) は動的に割り当てられた 13 バイトのサイズのポインターを返します。dest1 のサイズは 4 バイトで、13 の除数ではありません。この不整列のため、キャストに割り当てられた誤ったオブジェクト サイズの欠陥が生じます。行 12 で、同じ関数呼び出し my_alloc(13) は、dest2 の変換に対し欠陥にはなりません。char* のサイズの 1 バイトが 13 の除数であるためです。

修正 — ポインターのサイズを変更

1 つの修正方法として、変換先のサイズの倍数となるポインター サイズを使用することができます。この例では、my_alloc の引数を 4 の倍数に変更して欠陥を解決します。

#include <stdlib.h>

void *my_alloc(int size) { 
    void *ptr_func = malloc(size); 
    if(ptr_func == NULL) exit(-1); 
    return ptr_func; 
}

void fun_non_align(void){
    int *dest1;
    char *dest2;

    dest1 = (int*)my_alloc(12); 
    dest2 = (char*)my_alloc(13); 
}

チェック情報

グループ: Rec.08.メモリ管理 (MEM)

バージョン履歴

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.