修改CppCheck,做自己的扫描器 - 01

栏目: C++ · 发布时间: 7年前

内容简介:CppCheck是一个静态语法扫描器,官方介绍:Static analysis of C/C++ code. Checks for: memory leaks, mismatching allocation-deallocation, buffer overrun, and many more. The goal is 0% false positives. SeeCppCheck是一个开源工程,要对其进行修改,最好还是理清楚它的工作流程。首先,让我们对一个常见的问题进行检查,代码如下:

CppCheck是一个静态语法扫描器,官方介绍:

Static analysis of C/C++ code. Checks for: memory leaks, mismatching allocation-deallocation, buffer overrun, and many more. The goal is 0% false positives. See http://cppcheck.sourceforge.net for more information.

CppCheck是一个开源工程,要对其进行修改,最好还是理清楚它的工作流程。首先,让我们对一个常见的问题进行检查,代码如下:

int a[10];

a[10] = 0;

对这个越界代码进行扫描,可以发现如下调用栈处报警:

>   cppcheck-core.dll!CheckBufferOverrun::arrayIndexOutOfBoundsError(const Token * tok, const CheckBufferOverrun::ArrayInfo & arrayInfo, const std::vector<ValueFlow::Value,std::allocator<ValueFlow::Value> > & index) 行 142   C++
    cppcheck-core.dll!CheckBufferOverrun::valueFlowCheckArrayIndex(const Token * const tok, const CheckBufferOverrun::ArrayInfo & arrayInfo) 行 878  C++
    cppcheck-core.dll!CheckBufferOverrun::bufferOverrun() 行 1593    C++
    cppcheck-core.dll!CheckBufferOverrun::runChecks(const Tokenizer * tokenizer, const Settings * settings, ErrorLogger * errorLogger) 行 91 C++
    cppcheck-core.dll!CppCheck::checkNormalTokens(const Tokenizer & tokenizer) 行 563    C++
    cppcheck-core.dll!CppCheck::checkFile(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & filename, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & cfgname, std::basic_istream<char,std::char_traits<char> > & fileStream) 行 416 C++
    cppcheck-core.dll!CppCheck::check(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & path) 行 83   C++
    cppcheck.exe!CppCheckExecutor::check_internal(CppCheck & cppcheck, int __formal, const char * const * argv) 行 871   C++
    cppcheck.exe!CppCheckExecutor::check(int argc, const char * const * argv) 行 198 C++
    cppcheck.exe!main(int argc, char * * argv) 行 95 C++

简单分析一下,基本是这几行起了作用:

cppcheck-core.dll!CheckBufferOverrun::runChecks(const Tokenizer * tokenizer, const Settings * settings, ErrorLogger * errorLogger) 行 91 C++
    cppcheck-core.dll!CppCheck::checkNormalTokens(const Tokenizer & tokenizer) 行 563    C++
>   cppcheck-core.dll!CppCheck::checkFile(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & filename, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & cfgname, std::basic_istream<char,std::char_traits<char> > & fileStream) 行 416 C++

注意第一行:

void CppCheck::checkNormalTokens(const Tokenizer &tokenizer)
{
    // call all "runChecks" in all registered Check classes
    for (std::list<Check *>::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) {
        if (mSettings.terminated())
            return;

        if (tokenizer.isMaxTime())
            return;

        Timer timerRunChecks((*it)->name() + "::runChecks", mSettings.showtime, &S_timerResults);
        (*it)->runChecks(&tokenizer, &mSettings, this);
    }

也就是说,it从Check::instances()中遍历所有项目。

Check::instances中有:

名称  值   类型
▶   [0] 0x01557438 {cppcheck-core.dll!Check64BitPortability instance} {...} Check * {Check64BitPortability}
▶   [1] 0x01557494 {cppcheck-core.dll!CheckAssert instance} {...}   Check * {CheckAssert}
▶   [2] 0x015574ec {cppcheck-core.dll!CheckAutoVariables instance} {...}    Check * {CheckAutoVariables}
▶   [3] 0x01557550 {cppcheck-core.dll!CheckBool instance} {...} Check * {CheckBool}
▶   [4] 0x015575b8 {cppcheck-core.dll!CheckBoost instance} {...}    Check * {CheckBoost}
▶   [5] 0x01557614 {cppcheck-core.dll!CheckBufferOverrun instance} {...}    Check * {CheckBufferOverrun}
▶   [6] 0x01557774 {cppcheck-core.dll!CheckFunctions instance} {...}    Check * {CheckFunctions}
▶   [7] 0x0155768c {cppcheck-core.dll!CheckClass instance} {mSymbolDatabase=0x00000000 <NULL> } Check * {CheckClass}
▶   [8] 0x0155771c {cppcheck-core.dll!CheckCondition instance} {...}    Check * {CheckCondition}
▶   [9] 0x01557864 {cppcheck-core.dll!CheckExceptionSafety instance} {...}  Check * {CheckExceptionSafety}
▶   [10]    0x015578bc {cppcheck-core.dll!CheckIO instance} {...}   Check * {CheckIO}
▶   [11]    0x01557974 {cppcheck-core.dll!CheckLeakAutoVar instance} {...}  Check * {CheckLeakAutoVar}
▶   [12]    0x01557a7c {cppcheck-core.dll!CheckMemoryLeakNoVar instance4} {...} Check * {CheckMemoryLeakNoVar}
▶   [13]    0x01557a0c {cppcheck-core.dll!CheckMemoryLeakInClass instance2} {...}   Check * {CheckMemoryLeakInClass}
▶   [14]    0x015579d4 {cppcheck-core.dll!CheckMemoryLeakInFunction instance1} {...}    Check * {CheckMemoryLeakInFunction}
▶   [15]    0x01557a44 {cppcheck-core.dll!CheckMemoryLeakStructMember instance3} {...}  Check * {CheckMemoryLeakStructMember}
▶   [16]    0x01557b34 {cppcheck-core.dll!CheckNullPointer instance} {...}  Check * {CheckNullPointer}
▶   [17]    0x01557bb0 {cppcheck-core.dll!CheckOther instance} {...}    Check * {CheckOther}
▶   [18]    0x01557d20 {cppcheck-core.dll!CheckStl instance} {...}  Check * {CheckStl}
▶   [19]    0x01557cbc {cppcheck-core.dll!CheckSizeof instance} {...}   Check * {CheckSizeof}
▶   [20]    0x015577ec {cppcheck-core.dll!CheckString instance} {...}   Check * {CheckString}
▶   [21]    0x01557e98 {cppcheck-core.dll!CheckType instance} {...} Check * {CheckType}
▶   [22]    0x01557f00 {cppcheck-core.dll!CheckUninitVar instance} {...}    Check * {CheckUninitVar}
▶   [23]    0x01557f70 {cppcheck-core.dll!CheckUnusedFunctions CheckUnusedFunctions::instance} {mFunctions={ size=0 } ...}  Check * {CheckUnusedFunctions}
▶   [24]    0x01557ff8 {cppcheck-core.dll!CheckUnusedVar instance} {mIsRecordTypeWithoutSideEffectsMap={ size=0 } ...}  Check * {CheckUnusedVar}
▶   [25]    0x01557c64 {cppcheck-core.dll!CheckPostfixOperator instance} {...}  Check * {CheckPostfixOperator}
▶   [26]    0x01558070 {cppcheck-core.dll!CheckVaarg instance} {...}    Check * {CheckVaarg}

鉴于代码表明_instalces这是一个static变量,所以必然有代码调用了Check::instances().XXXX向它推送代码。

std::list<Check *> &Check::instances()
{
#ifdef __SVR4
    // Under Solaris, destructors are called in wrong order which causes a segmentation fault.
    // This fix ensures pointer remains valid and reachable until program terminates.
    static std::list<Check *> *_instances= new std::list<Check *>;
    return *_instances;
#else
    static std::list<Check *> _instances;
    return _instances;
#endif
}

查找所有的代码以后,只有构造函数有相关代码:

Check::Check(const std::string &aname)
    : mTokenizer(nullptr), mSettings(nullptr), mErrorLogger(nullptr), mName(aname)
{
    for (std::list<Check*>::iterator i = instances().begin(); i != instances().end(); ++i) {
        if ((*i)->name() > aname) {
            instances().insert(i, this);
            return;
        }
    }
    instances().push_back(this);
}

下断点,重新执行。

cppcheck-core.dll!Check::Check(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & aname) 行 30 C++
    cppcheck-core.dll!Check64BitPortability::Check64BitPortability() 行 46   C++
>   cppcheck-core.dll!`anonymous namespace'::`dynamic initializer for 'instance''() 行 41    C++

可以看到这样的调用栈,再往下就是程序的初始化代码了,一层层看。

1:最上层可以看到一个类似全局变量的代码

// Register this check class (by creating a static instance of it)
namespace {
    Check64BitPortability instance;
}

2:可以看到检测的类都是公开继承Check的

class CPPCHECKLIB Check64BitPortability : public Check {
public:
    /** This constructor is used when registering the Check64BitPortability */
    Check64BitPortability() : Check(myName()) {
    }

3:随后代码走到Check中,该类被加入。

再保留断点继续执行,可以发现所有的Check都是这样加入的,因为这些Check类都是全局变量,所以程序一启动就会自动添加进去。等他们执行完了才会进入main。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Developing Large Web Applications

Developing Large Web Applications

Kyle Loudon / Yahoo Press / 2010-3-15 / USD 34.99

As web applications grow, so do the challenges. These applications need to live up to demanding performance requirements, and be reliable around the clock every day of the year. And they need to withs......一起来看看 《Developing Large Web Applications》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具