CL.SHALLOW.ASSIGN

由于在赋值运算中进行浅层复制而释放已释放的内存

这是一个类级别 (CL) 检查器,可告知由于在赋值 (=) 运算中进行浅层复制导致类析构函数双重释放堆内存的潜在情况。如果一个类析构函数释放由一个或多个数据成员所指的动态内存(仅当在赋值运算中对这些指针执行浅层复制时),Klocwork 将报告 CL.SHALLOW.ASSIGN。

漏洞与风险

在执行浅层复制后,调用赋值运算符将导致具有数据成员的两个对象指向同一动态内存。如果没有恰当的引用计数设备,第一个对象超出范围时,类析构函数将释放两个对象之间共享的内存。第二个对象的相应数据成员将指向现已删除的内存位置。第二个对象超出范围时,其析构函数将尝试再次释放此内存。这可能导致应用程序崩溃和/或堆内存损坏。

漏洞代码示例 1

复制
    struct D {
        /* omitted for brevity */
    };

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

在此示例中,在赋值 (=) 运算中对成员指针 d 执行了浅层复制。相应堆内存释放于析构函数 ~C() 中。Klocwork 将这种潜在的危险情况标记为 CL.SHALLOW.ASSIGN。

修正代码示例 1

复制
    struct D {
       /* omitted for brevity */
       D(const D&);
    };

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

在修正代码示例 1 中,在赋值 (=) 运算中执行了深层复制;因此,调用两个对象的析构函数时不会发生双重释放的情况。

安全培训

应用程序安全培训材料由 Secure Code Warrior 提供。

扩展

此检查器可通过 Klocwork 知识库进行扩展。有关详情,请参阅调整 C/C++ 分析。