外部数据作为数组索引时必须确保在数组大小范围内

【描述】 外部数据作为数组索引对内存进行访问时,必须对数据的大小进行严格的校验,确保数组索引在有效范围内,否则会导致严重的错误。 当一个指针指向数组元素时,可以指向数组最后一个元素的下一个元素的位置,但是不能读写该位置的内存。

【错误代码示例】 如下代码示例中, set_dev_id()函数存在差一错误,当 index 等于 DEV_NUM 时,恰好越界写一个元素; 同样get_dev()函数也存在差一错误,虽然函数执行过程中没有问题,但是当解引用这个函数返回的指针时,行为是未定义的。

#define DEV_NUM 10
#define MAX_NAME_LEN 128
typedef struct {
	int id;
	char name[MAX_NAME_LEN];
} Dev;

static Dev devs[DEV_NUM];
int set_dev_id(size_t index, int id)
{
	if (index > DEV_NUM) { // 错误:差一错误。
 		... // 错误处理
	}

	devs[index].id = id;
	return 0;
}

static Dev *get_dev(size_t index)
{
	if (index > DEV_NUM) { // 错误:差一错误。
 		... // 错误处理
	}

	return devs + index;
}

【正确代码示例】 如下代码示例中,修改校验索引的条件,避免差一错误。

#define DEV_NUM 10
#define MAX_NAME_LEN 128
typedef struct {
	int id;
	char name[MAX_NAME_LEN];
} Dev;

static Dev devs[DEV_NUM];

int set_dev_Id (size_t index, int id)
{
	if (index >= DEV_NUM) {
		... // 错误处理
	}

	devs[index].id = id;
	return 0;
}

static Dev *get_dev(size_t index)
{
	if (index >= DEV_NUM) {
 		... // 错误处理
	}

	return devs + index;
}

【相关软件CWE编号】 CWE-119,CWE-123,CWE-125

禁止通过对指针变量进行sizeof操作来获取数组大小

【描述】 将指针当做数组进行sizeof操作时,会导致实际的执行结果与预期不符。例如:变量定义 char *p = array,其中array的定义为char array[LEN],表达式sizeof(p) 得到的结果与 sizeof(char *)相同,并非array的长度。

【错误代码示例】 如下代码示例中,buffer和path分别是指针和数组,程序员想对这2个内存进行清0操作,但由于程序员的疏忽,将内存大小误写成了sizeof(buffer),与预期不符。

char path[MAX_PATH];
char *buffer = (char *)malloc(SIZE);
...
(void)memset(path, 0, sizeof(path));
// sizeof与预期不符,其结果为指针本身的大小而不是缓冲区大小
(void)memset(buffer, 0, sizeof(buffer));

【正确代码示例】 如下代码示例中,将sizeof(buffer)修改为申请的缓冲区大小:

char path[MAX_PATH];
char *buffer = (char *)malloc(SIZE);
...
(void)memset(path, 0, sizeof(path));
(void)memset(buffer, 0, SIZE); // 使用申请的缓冲区大小