天天看點

C/C++學習日記:C語言,一些不安全的庫函數那些不安全的庫函數有關字元串拷貝的API

那些不安全的庫函數

C 和 C++ 不能夠自動地做邊界檢查,邊界檢查的代價是效率。一般來講,C 在大多數情況下注重效率。然而,獲得效率的代價是,C 程式員必須十分警覺以避免緩沖區溢出問題。

C/C++學習日記:C語言,一些不安全的庫函數那些不安全的庫函數有關字元串拷貝的API

C語言标準庫中的許多字元串處理和IO流讀取函數是導緻緩沖區溢出的罪魁禍首。我們有必要了解這些函數,在程式設計中多加小心。

一、字元串處理函數

strcpy() 

strcpy() 函數将源字元串複制到緩沖區。沒有指定要複制字元的具體數目!如果源字元串碰巧來自使用者輸入,且沒有專門限制其大小,則有可能會造成緩沖區溢出!

我們也可以使用strncpy來完成同樣的目的:

strncpy (dst, src, dst_size-1);

如果 src 比 dst 大,則該函數不會抛出一個錯誤;當達到最大尺寸時,它隻是停止複制字元。注意上面調用 strncpy() 中的 -1。如果 src 比 dst 長,則那給我們留有空間,将一個空字元放在 dst 數組的末尾。

但是! strncpy()也不完全安全,也有可能把事情搞糟。即使“安全”的調用有時會留下未終止的字元串,或者會發生微妙的相差一位錯誤。

確定 strcpy() 不會溢出的另一種方式是,在需要它時就配置設定空間,確定通過在源字元串上調用 strlen() 來配置設定足夠的空間。

dst = (char*)malloc(strlen(src));strcpy(dst, src);

strcat()

strcat() 函數非常類似于 strcpy(),除了它可以将一個字元串合并到緩沖區末尾。它也有一個類似的、更安全的替代方法 strncat()。如果可能,使用 strncat() 而不要使用 strcat()。

sprintf()、vsprintf

C/C++學習日記:C語言,一些不安全的庫函數那些不安全的庫函數有關字元串拷貝的API

函數 sprintf() 和 vsprintf() 是用來格式化文本和将其存入緩沖區的通用函數。它們可以用直接的方式模仿 strcpy()

行為。換句話說,使用 sprintf() 和 vsprintf() 與使用 strcpy() 一樣,都很容易對程式造成緩沖區溢出。 

sprintf() 的許多版本帶有使用這種函數的更安全的方法。可以指定格式字元串本身每個自變量的精度。sprintf 采用” * ”來占用一個本來需要一個指定寬度或精度的常數數字的位置,而實際的寬度或精度就可以和其它被列印的變量一樣被提供出來。

例如:sprintf(usage,"USAGE: %*s\n", BUF_SIZE, argv[0]);

二、字元讀取函數

gets()

永遠不要使用 gets()。

該函數從标準輸入讀入使用者輸入的一行文本,它在遇到 EOF 字元或換行字元之前,不會停止讀入文本。也就是:gets() 根本不執行邊界檢查。是以,使用 gets() 總是有可能使任何緩沖區溢出。

作為一個替代方法,可以使用方法 fgets()。它可以做與 gets() 所做的同樣的事情,但它接受用來限制讀入字元數目的大小參數,是以,提供了一種防止緩沖區溢出的方法。

getchar()、fgetc()、getc()、read()

C/C++學習日記:C語言,一些不安全的庫函數那些不安全的庫函數有關字元串拷貝的API

如果在循環中使用這些函數,確定檢查緩沖區邊界

scanf()系列 : sscanf()、fscanf()、vfscanf()、vscanf()、vsscanf()

scanf系列的函數也設計得很差。目的地緩沖區也可能會發生溢出。

同樣地,我們用設定寬度也可以解決這個問題。

getenv()

使用系統調用 getenv() 的最大問題是您從來不能假定特殊環境變量是任何特定長度的。

三、使用安全版本的代碼庫

微軟對于有緩沖溢出危險的API使用其開發的安全版本的庫來替代。

SafeCRT自Visual Studio 2005起開始支援。當代碼中使用了禁用的危險的CRT函數,Visual Studio 2005編譯時會報告相應警告資訊,以提醒開發人員考慮将其替代為Safe CRT中更為安全。

有關字元串拷貝的API

例如:strcpy, wcscpy等

替代的Safe CRT函數:strcpy_s

有關字元串合并的API

C/C++學習日記:C語言,一些不安全的庫函數那些不安全的庫函數有關字元串拷貝的API

例如:strcat, wcscat等

替代的Safe CRT函數:strcat_s

有關sprintf的API

例如:sprintf, swprintf等

替代的Safe CRT函數:

_snprintf_s 

_snwprintf_s

其它被禁用的API還有scanf, strtok, gets, itoa等等。 ”n”系列的字元串處理函數,例如strncpy等,也在被禁用之列。