メインコンテンツ

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

CERT C++: OOP57-CPP

Prefer special member functions and overloaded operators to C Standard Library functions

説明

ルール定義

Prefer special member functions and overloaded operators to C Standard Library functions.1

Polyspace 実装

ルール チェッカーは、"非トリビアルなクラス オブジェクトのバイト演算" をチェックします。

すべて展開する

問題

非トリビアルなクラス オブジェクトのバイト演算は、C 標準ライブラリ関数を使用して、非トリビアルまたは非標準のレイアウト クラス型オブジェクトに対してバイト演算を実行した場合に発生します。トリビアルおよび標準のレイアウト クラスに関する定義については、C++ Standard、[class]、段落 6 および 7 をそれぞれ参照してください。

チェッカーは、次の関数を使用して非トリビアルなクラス型オブジェクトを初期化またはコピーした場合に欠陥を報告します。

  • std::memset

  • std::memcpy

  • std::strcpy

  • std::memmove

次の関数を使用して非標準のレイアウト クラス型オブジェクトを比較した場合にも欠陥が報告されます。

  • std::memcmp

  • std::strcmp

非トリビアルなクラス オブジェクトのバイト演算は、バイト演算がエイリアスで実行された場合には欠陥を報告しません。たとえば、このコードによるバイト比較演算およびバイト コピー演算では欠陥が報告されません。このバイト演算では、dptr および sptr を使用しています。これらは非トリビアルまた非標準のレイアウト クラス オブジェクト d および s のエイリアスです。

void func(NonTrivialNonStdLayout *d, const NonTrivialNonStdLayout *s)
{
   void* dptr = (void*)d; 
   const void* sptr = (void*)s;
   // ...
   // ...
   // ...
   if (!std::memcmp(dptr, sptr, sizeof(NonTrivialNonStdLayout))) {  
     (void)std::memcpy(dptr, sptr, sizeof(NonTrivialNonStdLayout)); 
      // ...
   }
}

リスク

非トリビアルまたは非標準のレイアウト クラス型オブジェクトに対して、C 標準ライブラリ関数を使用してバイト比較演算を実行すると、実装の詳細による予期しない値につながる可能性があります。オブジェクト表現は、実装の詳細 (プライベートおよびパブリック メンバーの順序など)、またはそのオブジェクトを表すバーチャル関数ポインター テーブルの使用に依存します。

非トリビアルまたは非標準のレイアウト クラス型オブジェクトに対して、C 標準ライブラリ関数を使用してバイト設定演算を実行すると、実装の詳細が変更される可能性があります。この演算により、プログラムの異常動作やコード実行の脆弱性につながる可能性があります。たとえば、メンバー関数のアドレスが上書きされた場合、その関数を呼び出すと予期しない関数が呼び出されます。

修正方法

非トリビアルまたは非標準のレイアウト クラス型オブジェクトにバイト演算を実行するには、C 標準ライブラリ関数ではなく、次の特殊な C++ メンバー関数を使用します。

C 標準ライブラリ関数C++ メンバー関数

std::memset

クラスのコンストラクター

std::memcpy

std::strcpy

std::memmove

クラスのコピー コンストラクター

クラスの移動コンストラクター

コピー代入演算子

移動代入演算子

std::memcmp

std::strcmp

operator<()

operator>()

operator==()

operator!=()

例 - 非トリビアルなクラス オブジェクトで memset を使用
#include <cstring>
#include <iostream>
#include <utility>

class nonTrivialClass
{
    int scalingFactor;
    int otherData;
public:
    nonTrivialClass() : scalingFactor(1) {}
    void set_other_data(int i);
    int f(int i)
    {
        return i / scalingFactor;
    }
    // ...
};

void func()
{
    nonTrivialClass c;
    // ... Code that mutates c ...
    std::memset(&c, 0, sizeof(nonTrivialClass)); //Noncompliant
    std::cout << c.f(100) << std::endl;
}

この例では、func()std::memset を使用して、既定のコンストラクターで初期化された非トリビアルなクラス オブジェクト c を再初期化しています。このバイト演算は、値 c の表現を適切に初期化しない可能性があります。

修正 — std::swap を使用する関数テンプレートを定義

1 つの修正方法として、std::swap を使用して交換演算を実行する関数テンプレート clear() を定義します。clear() を呼び出すと、オブジェクト c の内容と既定の初期化が施されたオブジェクト empty の内容が交換され、c は適切に再初期化されます。

 #include <cstring>
#include <iostream>
#include <utility>

class nonTrivialClass
{
    int scalingFactor;
    int otherData;
public:
    nonTrivialClass() : scalingFactor(1) {}
    void set_other_data(int i);
    int f(int i)
    {
        return i / scalingFactor;
    }
    // ...
};

template <typename T>
T& clear(T& o)
{
    using std::swap;
    T empty;
    swap(o, empty);
    return o;
}

void func()
{
    nonTrivialClass c;
    // ... Code that mutates c ...

    clear(c);
    std::cout << c.f(100) << std::endl;
}

チェック情報

グループ: Rule 09.オブジェクト指向プログラミング (OOP)

バージョン履歴

R2019b で導入


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.