在软件测试团队建立软件测试体系或软件测试实验室申请CNAS/CMA认定时,都需要依据相关技术标准,确认权威的测试方法,指导日常的软件测试工作。GJB-8114《C/C++语言编程安全子集》是一部嵌入式软件安全测试相关的国家标准,本系列文章我们针对GJB-8114标准的具体内容进行解读和介绍,前面已经为大家介绍了声明定义类、版面书写类、指针使用类、分支控制类四大部分,本文我们继续为大家介绍运算处理类。
在介绍运算处理类之前,还有一个跳转控制类。跳转控制类我们现在真正能用到的不是太多,它的标志性符号就是goto 语句,现在的要求是除了汇编语言以外,所有的高级语言都不允许用goto语句,所以这一类我们就不详细展开讲了。
运算处理类
第六类是运算处理类,一共是19条,比较繁杂,把所有的跟运算有关的东西都放到了一起。
R-1-6-1
禁止将浮点常数赋给整型变量

第一个是禁止将浮点常数赋给整型变量,这个是说在我们实际应用中,经常会把一些浮点数赋值给整型变量,它会丢失精度,同时因为浮点数数的范围比较大,整型数数的范围比较小,所以在丢失精度的基础上,有可能还会产生上下溢出的情况。
R-1-6-2
禁止将越界整数赋给整型变量

程序中任何一个变量,它都有一个数据的范围,超出范围以外的数,把它赋给这个变量,是不允许的。这里说整型,实际上也不完全是整型,包括所有的字符、浮点数、长整型数等等都是这样。
R-1-6-3
禁止在逻辑表达式中使用赋值语句

禁止在逻辑表达式中使用赋值语句,这个是说如果你想使用赋值语句,一定要用括号括起来。
R-1-6-4
禁止对逻辑表达式进行位运算

位运算很显然是一个算数运算,在逻辑运算中它就是一个真和假的意义,没有其他的位的概念,所以它不允许你做这种的位运算。
R-1-6-5
禁止在运算表达式中或函数调用参数中使用++或--操作符

这个就是一个强制性的规定,在一个表达式中,除了对一个变量本身进行操作,在表达式中用++或--的话是不允许的。
R-1-6-6
对变量进行移位运算禁止超出变量长度

对变量进行移位运算禁止超出变量长度,一个变量到底有多长?通常串是八位的,整型是十六位的,长整型是三十二位,但是并不绝对。要看我们用的cpu它对应的数集是什么样的,比如说有些cpu它的串就是十六位的,咱们现在的pc机的整型就是三十二位的。
R-1-6-7
禁止移位操作中的移位数为负数

这个也就是说我们往左或者往右移负多少位,这个严格来说在我们的C语言中犯这种错误的人比较少。但是在汇编中通常是支持往左移负的多少位等等,这个是支持的,只不过在C语言中不允许这样做。
R-1-6-8
数组禁止越界使用

通常是我们按照使用的长度定义了一个数组的长度,在后来修改的过程中,数域增加了,但是这个数组的定义没有改变,就会造成这个数组有可能会超长了。
这个还有一个地方需要注意,array[100]这里,在有些语言中,array下标为100的意思是指0-100,有的是0-99。我们现在为了统一,通常是定义的最长的下标减1是我们能用到的最大的数。
这里有些人可能也会比较困惑,我在写程序的时候并没有越界,为什么在这里不允许呢?这里是为了统一,大家都遵循这样一个规则。
R-1-6-9
数组下标必须是大于等于零的整型数

这个没什么好说的,不能用小数和负数。
R-1-6-10
禁止对常数值做逻辑非运算

这个是说我们对常数值进行逻辑运算也没什么问题,主要是不能做逻辑非的运算,逻辑非只对逻辑值的真假做非运算。
R-1-6-11
禁止非枚举类型变量使用枚举类型的值

这个是大家常犯的一个错误,我们在声明一个枚举的时候,把枚举中各个变量的值赋给了一个变量。
像违背示例中举的例子,把枚举中的第二个变量的值赋给了一个正整型的变量,这个就违反了规则。
往往枚举是自动初始化的,你可以不把第一个数初始化,它也会正常运行,这个时候它里面的枚举值到底是多少,有可能我们是不知道,所以这个赋值就存在不确定性。
在遵循示例中表示的是,我们定义了一个枚举变量,这个变量就取枚举中的第二个值。
R-1-6-12
除法运算中禁止被零除

说是被零除,实际上并不是指真真正正地被零除,比如说浮点数,有一些浮点数就接近于0,但是又不等于0,在这种情况下,你用一个大数去除以这个接近于0的数,它会溢出。实际上就是为了防止溢出,这里才规定了禁止被零除。
这里大家要明白一个“大数”和“小数”的概念,大数和小数进行加减操作通常是没有意义的,因为这个小数不可能影响到大数。它俩要是做乘除操作呢,比如说小数又是二阶的,一相乘就基本上等于0了,它要是一阶的,跟大数相乘有可能就很接近于一个正常的常数,这个就根据具体的实际情况去判断。
这里要求不能够被零除,咱们在运用当中,通常把这个取成十的负五次方,也就是说小于十的负五次方的数就可以理解为接近于0的数。
但是对于有些运算,这个数还是不够小,那可能需要取到十的负十次方。
R-1-6-13
禁止在sizeof中使用赋值

sizeof只是指向一种某种类型的名字、结构的名字等等,不能像违背示例中,进行赋值或者混合的运算。
R-1-6-14
缓存区读取操作禁止越界

像违背示例中展示的,我们把一个长为4的数组赋给了一个长为2的区间,当然就会超出两个,超出两个的结果就是有可能把其他的变量给改写了。
R-1-6-15
缓存区写入操作禁止越界

这个是说,针对缓存区的读写操作,读不允许越界读,写也不允许越界写,写会冲掉一些别的变量,读通常会读了一些没有章法的乱数,对你是没有意义的数。
R-1-6-16
禁止使用已被释放了的内存空间

对于一个申请内存的指针,这个指针一旦把它释放了之后,它的空间实际上就没了,这时候你再用它的时候,它原来指向的空间有可能正在被别的程序占用,这个时候,也会影响到你的程序,所以是不允许的。
像违背示例中,每次判断它是不是空这是正确的,但是先把它释放就错了。
R-1-6-17
被释放的指针必须指向最初malloc、calloc分配的地址

也就是说最初我为一个指针分配了一个地址,一旦我对这个指针进行了增减操作,比如说增加操作指向不是原来的那个初始地址,这个时候我们释放的时候会出问题的。我们要想释放它,必须得把它恢复到原来给它赋值的那个指针的位置。
R-1-6-18
禁止使用gets函数,应使用fgets函数替代

咱们在C语言当中的两个函数,一个是gets,一个是fgets。因为gets函数在使用过程中被发现了一些问题,所以现在为了跳过这个bug,要求不使用gets函数。
现在我们所用到的一些编译器中,gets函数是不是还有bug?这个不好说,有的里有,有的里没有。所以统一规定了不要用gets函数。
R-1-6-19
使用字符串赋值、拷贝、追加等函数时,禁止目标字符串存储空间越界

这个就是说,我先给一个字符串赋值,然后再在它的后面追加,这样的情况下占用的空间就越来越大,有时候我们分配的初始空间有可能会不够这个长度,像违背示例中展示的,我们一共给str2分配了10个空间,但是它却占用了11个空间,这样就不行。
以上就是针对GJB-8114《C/C++语言编程安全子集》标准中,运算处理类的相关要求,后面会继续为大家介绍后面的七大类规则,欢迎大家继续关注。
本系列内容整理自优品软件培育计划百场前沿技术系列讲座直播第16期,中国航天科技集团公司软件评测中心研究员李国良为大家带来的《白盒测试——C/C++编程规范》专题讲座,他曾参与过多个大型航空、航天、军工、电子型号项目的测试任务,如需直播回放视频也可私信我获取。
(谢绝转载,更多内容可查看我的专栏)

607

被折叠的 条评论
为什么被折叠?



