程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C安全編碼--數組

C安全編碼--數組

編輯:C++入門知識

建議和規則

建議:

  • 理解數組的工作方式

  • 獲取數組的長度時不要對指針應用sizeof操作符

  • 顯示地指定數組的邊界,即使它已經由初始化值列表隱式地指定

規則:

  • 保證數組索引位於合法的范圍內

  • 在所有源文件中使用一致的數組記法

  • 保證變長數組的長度參數位於合法范圍之內

  • 保證復制的目標具有足夠的存儲空間

  • 保證表達式中的數組類型是兼容的

  • 不允許循環迭代到數組尾部之後

  • 不要對兩個並不指向同一個數組的指針進行相減或比較

  • 不要把一個指向非數組對象的指針加上或減去一個整數

  • 如果結果值並不引用合法的數組元素,不要把指針加上或減去一個整數

本文地址: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.c
char a[];
void insert_a(void) {
    a[0] = 'a';
}

解決方案:

//insert_a.h
enum {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安全編碼標准》

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved