splint使用

splint使用

一.splint介绍

splint是一个静态检查C语言程序安全弱点和编写错误的工具。splint会进行多种常规检查,包括未使用的变量,类型不一致,使用未定义变量,无法 执行的代码,忽略返回值,执行路径未返回,无限循环等错误。同时通过在源码中添加注记给出的附加信息,使其可以进行功能更加强大的检查。而注记,则是对文 件中的函数、变量、参数以及类型进行假定的一种的程式化的注释。

二.splint的安装

下载地址:
http://www.splint.org/downloads/splint-3.1.2.src.tgz
源码包安装:
# tar zxvf splint-3.1.2.src.tgz
# cd splint-3.1.2
# mkdir /usr/local/splint
# ./configure --prefix=/usr/local/splint
# make install
# vi ~/.bashrc
添加:
export LARCH_PATH=/usr/local/splint/share/splint/lib
export LCLIMPORTDIR=/usr/local/splint/share/splint/import
# source ~/.bashrc
# export PATH=/usr/local/splint/bin/splint:$PATH

三.splint的使用

1.空引用错误

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

//null.c
char firstChar1 (/*@null@*/ char *s)
{
return *s;
}

char firstChar2 (/*@null@*/ 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语言中,要求先定义变量,而后才可使用.所以,当使用一个没有定义的变量时,编译就会出错.
如下例,使用/*@in@*/说明的变量,表示必须进行定义.使用/*@out@*/说明的变量,表示在 执行过此函数后,这个变量就进行了定义.

// usedef.c
extern void setVal (/*@out@*/ int *x);
extern int getVal (/*@in@*/ int *x);
extern int mysteryVal (int *x);
int dumbfunc (/*@out@*/ 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 /*@out@*/ 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()使用了/*@out@*/说明,所以
在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进行字符串复制,避免了这种情况.

来至:http://blogold.chinaunix.net/u1/44908/showart_405418.html
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值