C語(yǔ)言 一些不安全的庫(kù)函數(shù)

2018-08-12 21:24 更新

那些不安全的庫(kù)函數(shù)

C 和 C++ 不能夠自動(dòng)地做邊界檢查,邊界檢查的代價(jià)是效率。一般來(lái)講,C 在大多數(shù)情況下注重效率。然而,獲得效率的代價(jià)是,C 程序員必須十分警覺(jué)以避免緩沖區(qū)溢出問(wèn)題。

C語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的許多字符串處理和IO流讀取函數(shù)是導(dǎo)致緩沖區(qū)溢出的罪魁禍?zhǔn)?。我們有必要了解這些函數(shù),在編程中多加小心。

一、字符串處理函數(shù)

strcpy()

strcpy() 函數(shù)將源字符串復(fù)制到緩沖區(qū)。沒(méi)有指定要復(fù)制字符的具體數(shù)目!如果源字符串碰巧來(lái)自用戶輸入,且沒(méi)有專門限制其大小,則有可能會(huì)造成緩沖區(qū)溢出!

我們也可以使用strncpy來(lái)完成同樣的目的:
strncpy (dst, src, dst_size-1);
如果 src 比 dst 大,則該函數(shù)不會(huì)拋出一個(gè)錯(cuò)誤;當(dāng)達(dá)到最大尺寸時(shí),它只是停止復(fù)制字符。注意上面調(diào)用 strncpy() 中的 -1。如果 src 比 dst 長(zhǎng),則那給我們留有空間,將一個(gè)空字符放在 dst 數(shù)組的末尾。
但是! strncpy()也不完全安全,也有可能把事情搞糟。即使“安全”的調(diào)用有時(shí)會(huì)留下未終止的字符串,或者會(huì)發(fā)生微妙的相差一位錯(cuò)誤。

確保 strcpy() 不會(huì)溢出的另一種方式是,在需要它時(shí)就分配空間,確保通過(guò)在源字符串上調(diào)用 strlen() 來(lái)分配足夠的空間。

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

strcat()

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

sprintf()、vsprintf

函數(shù) sprintf() 和 vsprintf() 是用來(lái)格式化文本和將其存入緩沖區(qū)的通用函數(shù)。它們可以用直接的方式模仿 strcpy() 行為。換句話說(shuō),使用 sprintf() 和 vsprintf() 與使用 strcpy() 一樣,都很容易對(duì)程序造成緩沖區(qū)溢出。

sprintf() 的許多版本帶有使用這種函數(shù)的更安全的方法??梢灾付ǜ袷阶址旧砻總€(gè)自變量的精度。sprintf 采用” * ”來(lái)占用一個(gè)本來(lái)需要一個(gè)指定寬度或精度的常數(shù)數(shù)字的位置,而實(shí)際的寬度或精度就可以和其它被打印的變量一樣被提供出來(lái)。

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

二、字符讀取函數(shù)

gets()

永遠(yuǎn)不要使用 gets()。
該函數(shù)從標(biāo)準(zhǔn)輸入讀入用戶輸入的一行文本,它在遇到 EOF 字符或換行字符之前,不會(huì)停止讀入文本。也就是:gets() 根本不執(zhí)行邊界檢查。因此,使用 gets() 總是有可能使任何緩沖區(qū)溢出。

作為一個(gè)替代方法,可以使用方法 fgets()。它可以做與 gets() 所做的同樣的事情,但它接受用來(lái)限制讀入字符數(shù)目的大小參數(shù),因此,提供了一種防止緩沖區(qū)溢出的方法。

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

如果在循環(huán)中使用這些函數(shù),確保檢查緩沖區(qū)邊界

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

scanf系列的函數(shù)也設(shè)計(jì)得很差。目的地緩沖區(qū)也可能會(huì)發(fā)生溢出。
同樣地,我們用設(shè)置寬度也可以解決這個(gè)問(wèn)題。

getenv()

使用系統(tǒng)調(diào)用 getenv() 的最大問(wèn)題是您從來(lái)不能假定特殊環(huán)境變量是任何特定長(zhǎng)度的。

三、使用安全版本的代碼庫(kù)

微軟對(duì)于有緩沖溢出危險(xiǎn)的API使用其開(kāi)發(fā)的安全版本的庫(kù)來(lái)替代。 SafeCRT自Visual Studio 2005起開(kāi)始支持。當(dāng)代碼中使用了禁用的危險(xiǎn)的CRT函數(shù),Visual Studio 2005編譯時(shí)會(huì)報(bào)告相應(yīng)警告信息,以提醒開(kāi)發(fā)人員考慮將其替代為Safe CRT中更為安全。

  1. 有關(guān)字符串拷貝的API

    例如:strcpy, wcscpy等

    替代的Safe CRT函數(shù):strcpy_s

  2. 有關(guān)字符串合并的API

    例如:strcat, wcscat等

    替代的Safe CRT函數(shù):strcat_s

  3. 有關(guān)sprintf的API

    例如:sprintf, swprintf等

    替代的Safe CRT函數(shù):

    _snprintf_s

    _snwprintf_s

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

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)