標籤:des style blog http color 使用
建議和規則
建議:
規則:
本文地址:http://www.cnblogs.com/archimedes/p/c-security-array.html,轉載請註明源地址。
擷取數組的長度時不要對指標應用sizeof操作符
代碼:
void clear(int array[]) { for(size_t i = 0; i < sizeof(array) / sizeof(array[0]); i++) { array[i] = 0; }}void dowork(void) { int dis[12]; clear(dis); /*...*/}
clear()使用sizeof(array) / sizeof(array[0])這種用法確定這個數組的元素數量,但由於array是一個形參,因此它是指標類型,sizeof(array) = sizeof(int *) = 4 (32位OS)
當sizeof操作符應用於聲明為數組或函數類型的形參時,它產生經過調整的(指標)類型的長度
解決方案:
void clear(int array[], size_t len) { for(size_t i = 0; i < len; i++) { array[i] = 0; }}void dowork(void) { int dis[12]; clear(dis, sizeof(dis) / sizeof(dis[0])); /*...*/}
保證數組索引位於合法的範圍內:
代碼:
enum {TABLESIZE = 100};int *table = NULL;int insert_in_table(int pos, int value) { if(!table) { table = (int *)malloc(sizeof(int) *TABLESIZE); } if(pos >= TABLESIZE) { return -1; } table[pos] = value; return 0;}
pos為int類型,可能為負數,導致在數組所引用的記憶體邊界之外進行寫入
解決方案:
enum {TABLESIZE = 100};int *table = NULL;int insert_in_table(size_t pos, int value) { if(!table) { table = (int *)malloc(sizeof(int) *TABLESIZE); } if(pos >= TABLESIZE) { return -1; } table[pos] = value; return 0;}
在所有源檔案中使用一致的數組記法
當在同一檔案中時,void func(char *a); 和 void func(char a[]); 完全等價
但在函數原型之外,如果一個數組在一個檔案中聲明為指標,在另一個不同的檔案中聲明為數組,它們是不等價的
代碼:
//main.c#include<stdlib.h>enum {ARRAYSIZE = 100};char *a;void insert_a(void);int main(void) { a = (char*)malloc(ARRAYSIZE); if(a == NULL) { //處理分配錯誤 } insert_a(); return 0;}//insert_a.cchar a[];void insert_a(void) { a[0] = ‘a‘;}
解決方案:
//insert_a.henum {ARRAYSIZE = 100};extern char *a;void insert_a(void);//insert_a.c#include "insert_a.h"char *a;void insert_a(void) { a[0] = ‘a‘;}//main.c#include<stdlib.h>#include"insert_a.h"int main(void){ a = (char*)malloc(ARRAYSIZE); if(a == NULL) { //處理分配錯誤 } insert_a(); return 0;}
保證變長數組的長度參數位於合法範圍之內
代碼:
void func(size_t s) { int vla[s]; /*...*/}/*...*/func(size);/*...*/
解決方案:
enum {MAX_ARRAY = 1024};void func(size_t s) { if(s < MAX_ARRAY && s != 0) { int vla[s]; /*...*/ } else { //錯誤處理 }}/*...*/func(size);/*...*/
保證複製的目標具有足夠的儲存空間
代碼:
enum {WORKSPACE_SIZE = 256};void func(const int src[], size_t len) { int dest[WORKSPACE_SIZE]; if(len > WORKSPACE_SIZE) { //錯誤處理 } memcpy(dest, src, sizeof(int) * len); /*...*/}
保證運算式中的數群組類型是相容的
代碼:
enum {a = 10, b = 15, c = 20};int arr1[c][b];int (*arr2)[a];arr2 = arr1; //不匹配 a != b
解決方案:
enum {a = 10, b = 10, c = 20};int arr1[c][b];int (*arr2)[a];arr2 = arr1; //匹配 a == b
不要把一個指向非數組對象的指標加上或減去一個整數
代碼:
struct numbers { short num1; short num2; /*...*/ short num9;};int sum_numbers(const struct numbers *numb) { int total = 0; const int *numb_ptr; for(numb_ptr = &numb->num1; numb_ptr <= &numb->num9; numb_ptr++) { total += *(numb_ptr); } return total;}int main(void) { struct numbers my_numbers = {1,2,3,4,5,6,7,8,9}; sum_numbers(&my_numbers); return 0;}
上面的代碼試圖用指標運算訪問結構的元素,這是危險的,因為結構中的欄位並不保證在記憶體中是連續的
解決方案(使用數組):
struct numbers { short num1; short num2; /*...*/ short num9;};int sum_numbers(const short *numb, size_t dim) { int total = 0; const int *numb_ptr; for(numb_ptr = numb; numb_ptr < numb + dim; numb_ptr++) { total += *(numb_ptr); } return total;}int main(void) { short my_numbers[9] = {1,2,3,4,5,6,7,8,9}; sum_numbers(my_numbers, sizeof(my_numbers) / sizeof(my_numbers[0])); return 0;}
參考資料
《C安全編碼通訊協定》