一.splint介绍

splint是一个动态检查C语言程序安全弱点和编写错误的程序.splint会进行
多种常规检查,包括未使用的变量,类型不一致,使用未定义变量,无法执行的
代码,忽略返回值,执行路径未返回,无限循环等错误.

二.splint的安装

 

1.rpm安装

GTES 10.5和11版本已经整合有splint软件包,直接可以使用.

2.源代码安装

下载地址: http://www.splint.org/downloads/splint-3.1.2.src.tgz 源码包安装: # tar zxvf splint-3.1.2.src.tgz # cd splint-3.1.2 # ./configure # make install

三.splint的使用

 

1.空引用错误

在引用没有指向任何内存地址的指针时,会导致这种错误.也就是使用了一个没有赋值的指针.
splint支持一种特别的注释.这种注释写在C程序代码中,用于对程序进行特殊说明.
如下面这段程序.使用了进行了说明,表示说明*s的值可能会是NULL.

//null.c char firstChar1 ( char *s) { return *s; } char firstChar2 ( char *s) { if (s ==NULL) return '\0'; return *s; } //END

使用splint扫描这个程序时,会输出:

# splint null.c Splint 3.1.1 --- 28 Apr 2005 null.c: (in function firstChar1) null.c:3:11: Dereference of possibly null pointer s: *s null.c:1:35: Storage s may become null Finished checking --- 1 code warning found 由于firstChar1和firstChar2都使用了null说明,表示指针s可能是个NULL值. 所以,splint会对s值的使用情况进行检查.因为firstChar2函数中,对s的值进行 了NULL的判断.所以,没有对firstChar2函数的指针s输出警告信息.

2.未定义的变量错误

C语言中,要求先定义变量,而后才可使用.所以,当使用一个没有定义的变量时,编译就会出错.
如下例,使用说明的变量,表示必须进行定义.使用说明的变量,表示在 执行过此函数后,这个变量就进行了定义.

// usedef.c extern void setVal ( int *x); extern int getVal ( int *x); extern int mysteryVal (int *x); int dumbfunc ( int *x, int i) { if (i > 3) return *x; else if (i > 1) return getVal (x); else if (i == 0) return mysteryVal (x); else { setVal (x); return *x; } } // END

使用splint检查usedef.c

$ splint usedef.c Splint 3.1.1 --- 28 Apr 2005 usedef.c: (in function dumbfunc) usedef.c:7:19: Value *x used before definition An rvalue is used that may not be initialized to a value on some execution path. (Use -usedef to inhibit warning) usedef.c:9:18: Passed storage x not completely defined (*x is undefined): getVal (x) Storage derivable from a parameter, return value or global is not defined. Use to denote passed or returned storage which need not be defined. (Use -compdef to inhibit warning) usedef.c:11:22: Passed storage x not completely defined (*x is undefined): mysteryVal (x) Finished checking --- 3 code warnings //错误原因: 由于程序中没有对x进行定义,所以报未定义错误.但setVal()使用了说明,所以 在setVal(x);和return x;中,没有报未定义错误.

3.类型错误

C语言中的数据类型较多,各个之间有些细微差别.splint也可以对变量类型进行检查.

示例1:

//bool.c int f (int i, char *s,bool b1, bool b2) { if (i = 3) return b1; if (!i || s) return i; if (s) return 7; if (b1 == b2) return 3; return 2; } //END

使用splint进行检查:

$ splint bool.c Splint 3.1.1 --- 28 Apr 2005 bool.c: (in function f) bool.c:4:5: Test expression for if is assignment expression: i = 3 The condition test is an assignment expression. Probably, you mean to use == instead of =. If an assignment is intended, add an extra parentheses nesting (e.g., if ((a = b)) ...) to suppress this message. (Use -predassign to inhibit warning) // 错误原因: if语句中的条件表达式是一个赋值语句. bool.c:4:5: Test expression for if not boolean, type int: i = 3 Test expression type is not boolean or int. (Use -predboolint to inhibit warning) // 错误原因: if语句中的条件表达式的返回值,不是布尔型,而是整型. bool.c:4:8: Return value type bool does not match declared type int: b1 Types are incompatible. (Use -type to inhibit warning) // 错误原因: 返回值是布尔型,而不是整型. bool.c:5:6: Operand of ! is non-boolean (int): !i The operand of a boolean operator is not a boolean. Use +ptrnegate to allow ! to be used on pointers. (Use -boolops to inhibit warning) // 错误原因: "!"操作符的操作数不是布尔型,而是整型i. bool.c:5:11: Right operand of || is non-boolean (char *): !i || s // 错误原因: "||"操作符的右操作数不是布尔型,而是字符指针. bool.c:7:5: Use of == with boolean variables (risks inconsistency because of multiple true values): b1 == b2 Two bool values are compared directly using a C primitive. This may produce unexpected results since all non-zero values are considered true, so different true values may not be equal. The file bool.h (included in splint/lib) provides bool_equal for safe bool comparisons. (Use -boolcompare to inhibit warning) // 错误原因: 使用"=="对两个布尔型进行比较.应该使用"&&". Finished checking --- 6 code warnings

示例2:

//malloc1.c #include <stdlib.h> #include <stdio.h> int main(void) { char *some_mem; int size1=1048576; some_mem=(char *)malloc(size1); printf("Malloed 1M Memory!\n"); free(some_mem); exit(EXIT_SUCCESS); } //END

使用splint检查malloc1.c

$ splint malloc1.c Splint 3.1.1 --- 28 Apr 2005 malloc1.c: (in function main) malloc1.c:9:25: Function malloc expects arg 1 to be size_t gets int: size1 To allow arbitrary integral types to match any integral type, use +matchanyintegral. Finished checking --- 1 code warning

修改变量size1的定义为:

size_t size1=1048576;

再使用splint进行检查.

$ splint malloc1.c Splint 3.1.1 --- 28 Apr 2005 Finished checking --- no warnings

没有检查到错误.

4.内存检查

缓冲区溢出错误是一种非常危险的C语言错误,大部分安全漏洞都与它有关.splint可以
对缓冲区的使用进行检查.报告溢出或越界错误.
示例1:

//over.c int main() { int buf[10]; buf[10] = 3; retrun 0; } //END

使用splint进行检查

$ splint over.c +bounds +showconstraintlocation Splint 3.1.1 --- 21 Apr 2006 Command Line: Setting +showconstraintlocation redundant with current value over.c: (in function main) over.c:6:3: Likely out-of-bounds store: buf[10] Unable to resolve constraint: requires 9 >= 10 needed to satisfy precondition: requires maxSet(buf @ over.c:6:3) >= 10 A memory write may write to an address beyond the allocated buffer. (Use -likely-boundswrite to inhibit warning) Finished checking --- 1 code warning

数组buf的大小是10字节.最大可使用的元素位置为buf[9],但程序中使用了buf[10].
所以报错.

示例2:

// bound.c void updateEnv(char *str) { char *tmp; tmp = getenv("MYENV"); if(tmp != NULL) strcpy(str,tmp); } void updateEnvSafe(char *str, size_t strSize) { char *tmp; tmp = getenv("MYENV"); if(tmp != NULL) { strncpy(str, tmp, strSize -1); str[strSize - 1] = '/0'; } } //END
$ splint bound.c +bounds +showconstraintlocation Splint 3.1.1 --- 21 Apr 2006 Command Line: Setting +showconstraintlocation redundant with current value bound.c: (in function updateEnv) bound.c:6:19: Possible out-of-bounds store: strcpy(str, tmp) Unable to resolve constraint: requires maxSet(str @ bound.c:6:26) >= maxRead(getenv("MYENV") @ bound.c:5:9) needed to satisfy precondition: requires maxSet(str @ bound.c:6:26) >= maxRead(tmp @ bound.c:6:30) derived from strcpy precondition: requires maxSet(<parameter 1>) >= maxRead(<parameter 2>) A memory write may write to an address beyond the allocated buffer. (Use -boundswrite to inhibit warning) 错误原因: 由于使用strcpy函数时,没有指定复制字符串的长度,所以可能导致缓冲区 溢出.后面的updateEnvSafe函数,使用了strncpy进行字符串复制,避免了这种情况.

cppcheck使用的更多相关文章

  1. sublime上安装c/c++代码分析工具 sublime Linter - cppcheck

    项目官方说明 sublime Linter - cppcheck 理解下sublime Linter - cppcheck, 它是插件的插件,sublime的插件sublimeLinter的插件.网络 ...

  2. C++静态代码分析工具对比cppCheck与PreFast

    具体内容参看文件<CppCheck和PreFast对Cplusplus代码静态分析测试.zip> C++测试源代码main.cpp #define NULL 0 #include < ...

  3. cppcheck 下载与安装(Liunx)

    下载网址:https://sourceforge.net/projects/cppcheck/files/cppcheck/ 选择安装包:cppcheck-1.75.tar.gz 解压安装包:tar ...

  4. cppcheck

    http://sourceforge.net/projects/cppcheck/files/?source=navbar https://github.com/danmar/cppcheck htt ...

  5. CodeBlocks集成cppcheck

    From:http://www.cnblogs.com/killerlegend/p/3624117.html Writer:KillerLegend CodeBlocks本身配置了cppcheck的 ...

  6. Cppcheck代码分析(1)

    一.检查点 1.自动变量检查: 返回自动变量(局部变量)指针 2.越界检查: 数组越界返回自动变量(局部变量)指针 3.类检查: 构造函数初始化 4.内存泄露检查: 5.空指针检查: 6.废弃函数检查 ...

  7. 静态代码检查工具 cppcheck 的使用

      CppCheck是一个C/C++代码缺陷静态检查工具.不同于C/C++编译器及其它分析工具,CppCheck只检查编译器检查不出来的bug,不检查语法错误.所谓静态代码检查就是使用一个工具检查我们 ...

  8. C/C++代码静态检查工具Cppcheck在VS2008开发环境中的安装配置和使用

    Cppcheck is an analysis tool for C/C++code. Unlike C/C++ compilers and many other analysis tools, it ...

  9. Cppcheck软件使用

    一款开源源码检测工具.简单易用. 官网网址:http://cppcheck.sourceforge.net/ 软件可直接官网下载. [plain] view plaincopy Features Ou ...

  10. Cppcheck 1.54 C/C++静态代码分析工具

    Cppcheck是一个C/C++代码分析工具,只检测那些编译器通常无法检测到的bug类型.   官方上建议让编译器提供尽量多的警告提示:1.使用Visual C++的话,应使用警告等级4 2.使用GC ...

随机推荐

  1. Linux常用命令之awk

    标题:awk命令的使用 作用:awk是非常好用的数据处理工具,主要处理每一行的字段内的数据,默认的字段的分割符为空格键或[tab]键 一.awk脚本的基本结构: awk 'BEGIN{print &q ...

  2. 第03篇. 标准Web项目Jetty9内嵌API简单启动

    一直以来,想改变一些自己早已经习惯的事情. 到了一定年龄,便要学会寡言,每一句话都要有用,有重量. 喜怒不形于色,大事淡然,有自己的底线. --胖先生 昨天,简单的说了一下关于Jetty9的配置,大家 ...

  3. revel + swagger 文档也能互动啦

    beego 从 1.3 后开始支持自动化API文档,不过,目测比较复杂,一直期望 revel 能有官方支持. revel 确实已经有了官方支持的计划,有可能将在 0.14 版本支持,现在才 0.11. ...

  4. 百度地图LBS开放平台AK一直没有用

    http://api.map.baidu.com/geoconv/v1/?coords=114.21892734521,29.575429778924;114.21892734521,29.57542 ...

  5. 用Chrome在电脑上模拟微信浏览器

    1.先了解安卓微信和Ios微信的UA(User agent:用户代理) 安卓微信UA: mozilla/5.0 (linux; u; android 4.1.2; zh-cn; mi-one plus ...

  6. 【JS Note】字符串截取

    Js中字符截取常用的三个函数:slice().substring().substr(). slice(): slice(start,[end]) 第一个参数代表开始位置,第二个参数代表结束位置的下一个 ...

  7. 宽度的100%和auto的区别

    前段时间做项目,发现分不清width设为100%和auto的区别,实在是太水了,就查了点资料,做个总结,有不对的地方欢迎大家指出. width:auto 块级元素默认的宽度值.看一下MDN上的解释:T ...

  8. Abp Zero——前端如何新增功能模块

    为适应不同开发人员,abp rezo的UI实现了spa和mpa两套: spa--Single-page Application(单页面应用),默认"http://localhost/Acco ...

  9. Quartz.net官方开发指南系列篇

    Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中.它提供了巨大的灵活性而不牺牲 ...

  10. iOS 触摸的位置放一个大头针

    iOS 触摸的位置放一个大头针 UITapGestureRecognizer *mTap = [[UITapGestureRecognizer alloc] initWithTarget:self a ...