CL.SHALLOW.COPY

コピー コンストラクタでの形式的なコピーによる解放されたメモリの解放

これは、コピーコンストラクタでの形式的なコピーに起因するクラスデストラクタによるヒープメモリの二重解放の可能性を通知するクラスレベル (CL) のチェッカーです。Klocwork は、クラスデストラクタが 1 つ以上のデータメンバーによってポイントされる動的メモリの解放を実行し、コピーコンストラクタでこれらのポインターの形式的なコピーのみを実行する場合に、CL.SHALLOW.COPY をレポートします。

脆弱性とリスク

形式的なコピーの場合、コピーコンストラクタの呼び出しにより、同じ動的メモリをポイントするデータメンバーを持つ 2 つのオブジェクトが作成されます。適切なリファレンスカウンターデバイスがない場合、最初のオブジェクトが範囲外になると、クラスデストラクタは 2 つのオブジェクト間で共有されるメモリを解放します。2 番目のオブジェクトの該当するデータメンバーは、この場合、削除されたメモリ場所をポイントします。2 番目のオブジェクトが範囲外になると、そのデストラクタはこのメモリを再度解放しようとします。これはアプリケーションのクラッシュやヒープメモリの破壊といった問題につながる可能性があります。

脆弱コード例 1

コピー
    struct D {
        /* omitted for brevity */
    };

    class C {
    public
        C();
        ~C() {
            delete d;
       }
       C(const C& rhs) {
           d = rhs.d;    // shallow copy
       }
   private
       C& operator=(const C&);
       D* d;
   };

この例では、メンバーポインター d の形式的なコピーがコピーコンストラクタにて実行されます。対応するヒープメモリはデストラクタ ~C() で解放されます。Klocwork はこの潜在的に危険な状況に対して CL.SHALLOW.COPY のフラグを立てます。

修正コード例 1

コピー
    struct D {
        /* omitted for brevity */
        D(const D&);
    };

    class C {
    public
        C();
        ~C() {
           delete d;
       }
       C(const C& rhs) {   
           d = new D(*rhs.d);
       }
   private
       C& operator=(const C&);
       D* d;
   }; 

修正例 1 ではコピーコンストラクタで実質的なコピーが実行されます。この結果、2 つのオブジェクトのデストラクタが呼び出される場合に二重解放は起こりません。

セキュリティトレーニング

Secure Code Warrior が提供しているアプリケーションセキュリティトレーニング教材。

拡張機能

このチェッカーは、Klocwork knowledge base (ナレッジベース) を利用して拡張できます。詳細については、C/C++ 解析のチューニングを参照してください。