cppcheck,代码简单分析,以及实现一个简单的模块

摘要:
经过半天的分析和了解,我已经大致了解了这个工具的使用方法和原理。该工具将解析一个源文件、每个有效的符号或元素,然后将其存储在一个大列表中,以便稍后进行模块检测。然而,一些特殊元素不会在列表中列出,例如调用约定,其他元素应该仍然存在,但尚未使用。正如我们所看到的,整个文件的所有内容都放在一个列表中,这非常痛苦。

经过半天的分析和了解,大致明白了这个工具的使用方法和原理。

这个工具,会将一个源文件(目前我是用单一源文件测试的,没有使用目录测试),

每一个有效符号或者元素都解析出来,之后储存在一个大list里面,供后续模块检测时使用,

但是一些特殊的元素,不会被列入list,如调用约定(__stdcall 此类等等),其他应该还有,但是还没使用到,

目前看到的情况是,整个文件所有内容全部都被放到了一个list 里面,挺痛苦的。

内置模块部分,其实它内置了很多功能

cppcheck,代码简单分析,以及实现一个简单的模块第1张

一堆check,很方便我来学习,据此我也写出了一个简单的check模块,代码如下

 1 #pragma once
 2 
 3 #include "check.h"
 4 #include "ctu.h"
 5 
 6 #include <cstddef>
 7 #include <list>
 8 #include <map>
 9 #include <string>
10 #include <vector>
11 
12 class CPPCHECKLIB CheckZooFrame : public Check {
13 public:
14 
15     /** This constructor is used when registering the CheckClass */
16     CheckZooFrame() : Check(myName()) {
17     }
18 
19     /** This constructor is used when running checks. */
20     CheckZooFrame(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger)
21         : Check(myName(), tokenizer, settings, errorLogger) {
22     }
23 
24     void runChecks(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) OVERRIDE;
25 
26     void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const OVERRIDE;
27 
28     /** @brief Parse current TU and extract file info */
29     Check::FileInfo* getFileInfo(const Tokenizer* tokenizer, const Settings* settings) const OVERRIDE;
30 
31     /** @brief Analyse all file infos for all TU */
32     bool analyseWholeProgram(const CTU::FileInfo* ctu, const std::list<Check::FileInfo*>& fileInfo, const Settings& settings, ErrorLogger& errorLogger) OVERRIDE;
33 
34 private:
35 
36     /** data for multifile checking */
37     class MyFileInfo : public Check::FileInfo {
38     public:
39         /** unsafe array index usage */
40         std::list<CTU::FileInfo::UnsafeUsage> unsafeArrayIndex;
41 
42         /** unsafe pointer arithmetics */
43         std::list<CTU::FileInfo::UnsafeUsage> unsafePointerArith;
44 
45         /** Convert MyFileInfo data into xml string */
46         std::string toString() const OVERRIDE {
47             return "Zoos";
48         }
49     };
50 
51     Check::FileInfo* loadFileInfoFromXml(const tinyxml2::XMLElement* xmlElement) const OVERRIDE;
52 
53 
54     static std::string myName() {
55         return "Zoo checking";
56     }
57 
58     std::string classInfo() const OVERRIDE {
59         return "Zoo Check Frame
";
60     }
61 };
 1 #include "check_zoo.h"
 2 #include "check.h"
 3 
 4 namespace {
 5     CheckZooFrame instance;
 6 }
 7 
 8 
 9 
10 static const CWE CWE_POINTER_ARITHMETIC_OVERFLOW(758U);
11 
12 
13 void CheckZooFrame::runChecks(const Tokenizer* tokenizer, const Settings* settings, ErrorLogger* errorLogger) {
14     printf("FILE [%s] LINE [%d] Function [%s] 
", __FILE__, __LINE__, tokenizer->tokens()->next()->str().c_str());
15     CheckZooFrame c(tokenizer, settings, errorLogger);
16     c.reportError(tokenizer->tokens(), Severity::portability, "Zoo检测点", "Zoo框架", CWE_POINTER_ARITHMETIC_OVERFLOW, false);
17 
18     for (const Token* tok = tokenizer->tokens(); tok; tok = tok->next())
19     {
20         printf("%s ", tok->str().c_str());
21         if (tok->str() == "{" || tok->str() == "}" || tok->str() == ";")
22         {
23             printf("
");
24         }
25     }
26 }
27 
28 void CheckZooFrame::getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const {
29     printf("FILE [%s] LINE [%d] 
", __FILE__, __LINE__);
30 }
31 
32 /** @brief Parse current TU and extract file info */
33 Check::FileInfo* CheckZooFrame::getFileInfo(const Tokenizer* tokenizer, const Settings* settings) const {
34     printf("FILE [%s] LINE [%d] 
", __FILE__, __LINE__);
35     return NULL;
36 }
37 
38 /** @brief Analyse all file infos for all TU */
39 bool CheckZooFrame::analyseWholeProgram(const CTU::FileInfo* ctu, const std::list<Check::FileInfo*>& fileInfo, const Settings& settings, ErrorLogger& errorLogger) {
40     printf("FILE [%s] LINE [%d] 
", __FILE__, __LINE__);
41     return true;
42 }
43 
44 
45 Check::FileInfo* CheckZooFrame::loadFileInfoFromXml(const tinyxml2::XMLElement* xmlElement) const {
46     printf("FILE [%s] LINE [%d] 
", __FILE__, __LINE__);
47     return NULL;
48 }

扩展性还是非常强的,我的代码,几乎全部都是对照其他模块来写的,

而且接口也非常简单,很友好。

这里简单地解释一下吧。

cppcheck的模块系统属于构造时直接靠全局变量串起来的这种模式(相似的可以看llvm,clang的命令行系统,也是这么串起来的),

优点是简单方便,只要继承了父类,然后实例化一个自己,就解决了问题,

缺点是,很多关键信息无法在初次构造时就获取到,所以使用时有点麻烦。

本人在编写这个简单模块的时候,就遇到了这个小麻烦,不过还是解决了。

主要体现在,错误上报的部分。

整个cppcheck框架,其实比较强大,它实际上真的仅仅是作为一个普通框架来执行的,

内部功能通过一个个模块,一次次传递参数,一个个reportError来列出。

以 CheckZooFrame 为例,

首先需要实现若干虚函数,继承于 check 父类,

然后定义一个全局变量,供初始化的时候,挂接自己,

但是这时候,由于自己无法获取到任何关键信息,所以内部变量初始化全部都是空,

即CPP代码中第五行。

挂接了自己之后,最重要的函数,其实只有一个,是runcheck,

这个函数会被外面check管理器直接调用,会传入一系列的参数,

让当前模块来检测是否有需要检测的异常,

如果有的话,则通过reportError上报。

这时候就有问题了,reportError上报需要知道当前的代码list,但是初始化的时候已经全都是空了,没有list,

怎么办,那就只能在自己内部重新创建个局部变量,构造时让它有list,

即CPP代码中15行的作用。

然后就可以尽情地玩耍了。

还有个问题,就是CWE是什么,其实CWE是一个索引ID,这个ID遵守一套XXXX的规则,

这个规则里面定义了若干种代码可能出现的问题,通过这个ID,大家就可以统一使用并查询出代码出现了什么问题。

具体这个ID去哪查,就去下面的网站。

https://cwe.mitre.org/data/downloads.html

例子中的CWE是我随便写的,并不影响。

其实挺容易的,没有那么难,只不过,任重而道远啊。比如

下图,指定位置有一个非常明显的内存越界写操作,可能会导致出现 0xC0000005,但是呢,cppcheck内置的模块没有发现这个问题,

这说明了一个事情,就是它内置模块的检测范围可能还是以函数为单位的,只能检测到当前函数内的事情,无法朔源检测前面或者后面函数内的事情。

cppcheck,代码简单分析,以及实现一个简单的模块第2张

这只是一个点吧,我希望基于对它的学习,能多少再了解一些代码审计相关的知识。

就到这吧

其实,由于它的模块化是如此地出色,甚至可以插入一个python或者lua脚本解释器之类的,让它支持通过脚本来加模块,那么应该会更完美。

免责声明:文章转载自《cppcheck,代码简单分析,以及实现一个简单的模块》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇docker固定IP重启不变的方法Docker开发环境预览下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

duilib之源码分析

《duilib之源码分析》1 stdAfx.h [cpp]view plaincopy *lengthof(x)计算数组长度宏 *MAX两值最大 *MIN两值最小 *CLAMP(x,a,b)x在a,b之间则取x否则取最小 2 UIBase [cpp]view plaincopy *UI_WNDSTYLE_窗口风格属性 *UI_CLASS...

互动直播中的前端技术——即时通讯

前言 在疫情期间,上班族开启了远程办公,体验了各种远程办公软件。老师做起了主播,学生们感受到了被钉钉支配的恐惧,歌手们开启了在线演唱会,许多综艺节目也变成了在线直播。在这全民互动直播的时期,我们来聊聊互动直播中的即时通讯技术在前端中的使用。 即时通讯技术 即时通讯(Instant Messaging,简称IM)是一个实时通信系统,允许两人或多人使用网络实时...

snmp学习笔记

snmp5.5 client 包含头文件 #include <net-snmp/net-snmp-config.h> #include <net-snmp/net-snmp-includes.h> 用到的函数有:初始化snmp库:void init_snmp(const char *); 用于初始化snmp库 netsnmp_ses...

OpenCV 图像采样 插值 几何变换

InitLineIterator 初始化线段迭代器 int cvInitLineIterator( const CvArr* image, CvPoint pt1, CvPoint pt2, CvLineIterator* line_iterator, int connectivity=8 ); image 带采线段的输入图像. pt1 线段起始点 pt...

Vue(一)

一、es6语法:let和const es6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。 上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效 for循环...

Qt之log数据展示模块简要实现

Log模块主要用于实时测井数据的显示和测后曲线数据的预览和打印,为更好的展示对Qt中相关知识点的应用,特以Log模块为例对其进行简要实现。 内容导图: 一、功能需求 1、界面效果图 Log模块实现曲线数据的显示及相关属性(曲线颜色、画笔类型、画笔宽度等)的设置 将上图划分为三个区域:右边为轨道信息显示和管理区,可以参看和设置相关轨道信息 左上为轨道的L...