我可以配置 clang-tidy 来接受除 NULL 之外的某些死存储值吗?

问题描述 投票:0回答:1

例如,以下函数使用 Windows API 将文件加载到内存中,并使用在其他地方定义为

POLYNOMIAL
的多项式计算其 CRC32 校验和:

#include <Windows.h>


UINT32 WINAPI GetFileCRC32(WCHAR *wszFileName, LPDWORD lpdwError)
{
    HANDLE hHeap = GetProcessHeap();
    HANDLE hFile = INVALID_HANDLE_VALUE;
    LARGE_INTEGER liSize;
    DWORD dwError, dwRead;
    SIZE_T cbAlloc, i, i2;
    BYTE *bBuffer = NULL;
    UINT32 uCRC = 0xFFFFFFFFU;

    hFile = CreateFileW(wszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == hFile)
    {
        dwError = GetLastError();
        goto cleanup;
    }
    GetFileSizeEx(hFile, &liSize);
    do
    {
        cbAlloc = min(liSize.QuadPart, ALLOC_MAX);
        bBuffer = (BYTE *) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbAlloc);
        if (NULL == bBuffer)
        {
            dwError = ERROR_OUTOFMEMORY;
            goto cleanup;
        }

        if (!ReadFile(hFile, bBuffer, cbAlloc, &dwRead, NULL))
        {
            dwError = GetLastError();
            goto cleanup;
        }

        for(i = 0; i < cbAlloc; i++)
        {
            uCRC ^= bBuffer[i];
            for (i2 = 0; i2 < 8; i2++)
            {
                uCRC = (uCRC >> 1) ^ ((uCRC & 1) ? POLYNOMIAL : 0);
            }
        }

        HeapFree(hHeap, 0, bBuffer);
        bBuffer = NULL;

        liSize.QuadPart -= cbAlloc;
    }
    while(liSize.QuadPart);
    dwError = ERROR_SUCCESS;
cleanup:
    if (hFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hFile);
        hFile = INVALID_HANDLE_VALUE;
    }
    if (bBuffer != NULL)
    {
        HeapFree(hHeap, 0, bBuffer);
        bBuffer = NULL;
    }
    *lpdwError = dwError;
    return uCRC;
}
默认情况下,

Clang-Tidy 不会将

bBuffer = NULL
行检测为死存储,我认为是因为它认识到将指针设置为
NULL
的做法是一种防御性编程做法,以防止双重释放错误。不过,我还在关闭后将
hFile
的值设置回
INVALID_HANDLE_VALUE
,作为同一模式的一部分。

但是,clang-tidy 确实抱怨函数末尾的

INVALID_HANDLE_VALUE
分配(这是强制转换为
-1
的数值
HANDLE
)作为“死存储”。

如何配置 clang-tidy 分析以接受

NULL
以外的值作为免于死存储分析的值?

c winapi static-analysis clang-tidy resource-disposal
1个回答
0
投票

不,无法配置

clang-tidy
deadcode.DeadStores
检查器忽略
nullptr
以外的值分配。

忽略

nullptr
赋值的代码位于
DeadStoresChecker.cpp:340

      if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(B->getLHS()))
        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
          // Special case: check for assigning null to a pointer.
          //  This is a common form of defensive programming.
          const Expr *RHS =
              LookThroughTransitiveAssignmentsAndCommaOperators(B->getRHS());

          QualType T = VD->getType();
          if (T.isVolatileQualified())
            return;
          if (T->isPointerType() || T->isObjCObjectPointerType()) {
===>        if (RHS->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNull))
              return;
          }

          // Special case: self-assignments.  These are often used to shut up
          //  "unused variable" compiler warnings.
          if (const DeclRefExpr *RhsDR = dyn_cast<DeclRefExpr>(RHS))
            if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
              return;

          // Otherwise, issue a warning.
          DeadStoreKind dsk = Parents.isConsumedExpr(B)
                              ? Enclosing
                              : (isIncrement(VD,B) ? DeadIncrement : Standard);

          CheckVarDecl(VD, DR, B->getRHS(), dsk, Live);
        }

指定线路呼叫

Expr::isNullPointerConstant
检查
nullptr
,但这里没有任何灵活性允许 其他值。

在引用片段的末尾有一个对

CheckVarDecl
的调用, 它根据变量的类型进行更多的过滤 (例如,忽略引用)在发布报告之前。它 接受 RHS 表达式,但仅使用它来获取源位置 范围;没有根据分配的值进行过滤。

我看到的唯一半可行的解决方法是将作业包装在 调用恒等宏 (

#define ID(x) x
),因为检查器拒绝 报告宏扩展内的代码。

© www.soinside.com 2019 - 2024. All rights reserved.