メインコンテンツ

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

CERT C: Rule MEM33-C

フレキシブル配列メンバーを含む構造体を動的に割り当ておよびコピーする

説明

ルール定義

フレキシブル配列メンバーを含む構造体を動的に割り当ておよびコピーします。1

Polyspace 実装

ルール チェッカーは、"フレキシブル配列メンバーをもつ構造体の不適切な使用" をチェックします。

すべて展開する

問題

フレキシブル配列メンバーをもつ構造体の不適切な使用は以下の場合に発生します。

  • コンパイル時に、サイズ不明のフレキシブル配列メンバーをもつオブジェクトを定義する。

  • フレキシブル配列メンバーをもつ構造体の間で、memcpy() または類似の関数を使用せずに代入を行う。

  • フレキシブル配列メンバーをもつ構造体を関数の引数として使用し、引数を値渡しする。

  • 関数がフレキシブル配列メンバーをもつ構造体を返す。

フレキシブル配列メンバーは配列サイズが指定されていない、少なくとも 2 つの名前付きメンバーをもつ構造体の最後の要素です。

リスク

フレキシブル配列メンバーのサイズが定義されていない場合、そのフレキシブル配列メンバーを含む構造体のメモリ割り当て時にフレキシブル配列メンバーは無視されます。そのような構造体へのアクセスには、未定義の動作があります。

修正方法
  • malloc() または類似の関数を使用して、フレキシブル配列メンバーをもつ構造体のメモリを割り当てます。

  • memcpy() または類似の関数を使用して、フレキシブル配列メンバーをもつ構造体をコピーします。

  • フレキシブル配列メンバーをもつ構造体を関数の引数としてポインターで渡します。

例 - 関数に値渡しされる構造体
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>


struct example_struct
{
    size_t num;
    int data[];
};

extern void arg_by_value(struct example_struct s);

void func(void)
{
    struct example_struct *flex_struct;
    size_t i;
    size_t array_size = 4;
    /* Dynamically allocate memory for the struct */
    flex_struct = (struct example_struct *)
        malloc(sizeof(struct example_struct) + sizeof(int) * array_size);
    if (flex_struct == NULL)
    {
        /* Handle error */    
    }
    /* Initialize structure */
    flex_struct->num = array_size;
    for (i = 0; i < array_size; ++i)
    {
        flex_struct->data[i] = 0;
    }
    /* Handle structure */
	
	/* Argument passed by value. 'data' not 
	copied to passed value. */
    arg_by_value(*flex_struct);  //Noncompliant
	
    /* Free dynamically allocated memory */
    free(flex_struct);
}
        
      

この例では、flex_structarg_by_value に引数として値渡しされています。その結果、渡す引数にフレキシブル配列メンバー データがコピーされていません。

修正 — 関数に構造体をポインターで渡す

渡す引数に構造体のすべてのメンバーをコピーするには、flex_structarg_by_pointer にポインターで渡します。

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>


struct example_struct
{
    size_t num;
    int data[];
};

extern void arg_by_pointer(struct example_struct *s);

void func(void)
{
    struct example_struct *flex_struct;
    size_t i;
    size_t array_size = 4;
    /* Dynamically allocate memory for the struct */
    flex_struct = (struct example_struct *)
        malloc(sizeof(struct example_struct) + sizeof(int) * array_size);
    if (flex_struct == NULL)
    {
        /* Handler error */       
    }
    /* Initialize structure */
    flex_struct->num = array_size;
    for (i = 0; i < array_size; ++i)
    {
        flex_struct->data[i] = 0;
    }
    /* Handle structure */
	
	/* Structure passed by pointer */
    arg_by_pointer(flex_struct); 
	
    /* Free dynamically allocated memory */
    free(flex_struct);
} 

チェック情報

グループ: Rule 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.