1. 程式人生 > >C/C++ 程式碼安全(一)

C/C++ 程式碼安全(一)

規則1:

不通過連結建立通用字串。

C11標準:如果匹配通用字元名稱的字元序列由符號連結生成,將產生未定義行為。
#define assign(uc1,uc2,val) uc1##uc2 = val 

void func(){

    int u0401;

    assign(u04,01,4);

    printf("u0401 = %d\n",u0401);
}

int main(){

    func();

}
此結果是未定義的,不要使用連結誒字串來賦值。 規則2: 避免使用不安全的巨集引數
#define ABS(x)  (((x) < 0) ? -(x) : (x))

void fun(int n){
    /*
     *   n++;
     *   ABS(n);  right
     */
    ABS(n++);/*erro*/

}
注意n的加減。 解決方案一: 我們可以寫一個行內函數或者寫一個靜態函式來代替此巨集。 解決方案二: 使用範型程式設計_Generic 引數,範型選擇不求值,所以我們的值只會求一次。
#include<stdio.h>
#include<complex.h>
#include<math.h>

static inline long labs(long v){
    return v < 0 ?  -v : v;
}

static inline int ilabs(int v){
    return v < 0 ? -v : v;
}

static inline short slabs(int v){
    return v < 0 ? -v : v;
}


#define ABS(v) _Generic(v,long : labs ,\
                          int  : ilabs ,\
                          short: slabs)(v)

void fun(int n){
    int m = ABS(++n);
}

int main(){

    fun(10);
}
解決方案三: 使用GCC 擴充套件,但是會帶來平臺問題。
#define ABS(x) __extension__ ({__typeof(x) tmp = x ;\
                               tmp < 0 ? -tmp : tmp;})
規則: 不要在類函式的巨集呼叫中使用前處理器指令
void func(const char * src){

    char *dest;
    memcpy(dest,src,
        #ifdef A
          12
        #else 
          13
        #endif);

}
其實能寫出這種程式碼的人腦洞也是大的沒誰了,我感覺這都不關乎安全問題了。 解決方法很簡單,寫完整就好了。

檢視原文:http://zmrlinux.com/2016/08/27/cc-%e4%bb%a3%e7%a0%81%e5%ae%89%e5%85%a8%ef%bc%88%e4%b8%80%ef%bc%89/