簡體   English   中英

為什么C沒有像strcpy()這樣的函數並自動檢查緩沖區大小以防止緩沖區溢出錯誤?

[英]Why C doesn't have a function which is used like strcpy() and check buffer size automatically to prevent buffer overflow bug?

我真的很想知道為什么C中沒有像strcpy()memcpy()等函數會自動檢查緩沖區的大小。 表現如下:

#define strcpy2(X, Y) strncpy(X, Y, sizeof(X))

有人告訴我:“因為這是古老的語言。” 但是,C並非一成不變的語言。 IOS可以修復該標准,並添加了諸如strncpy類的新功能。

其他人告訴我:“這會導致性能問題。” 但是,我認為“如果存在類似的功能,那么在性能很重要的情況下,您仍然可以使用舊功能。在所有情況下,您都可以使用該功能,並且可以期望提高安全性。”

還有一些人告訴我:“所以,有一個類似strncpy()的函數,或者“ C是為考慮此問題的專業開發人員設計的”,但是strncpy()不會自動進行檢查-開發人員必須確定緩沖區的大小,以及由專業開發人員制作的大型程序(如Chrome)仍然具有緩沖區溢出漏洞。

我想知道為什么無法執行此功能的技術原因。


*英語不是我的母語。 所以我想可能有一些錯誤...對此感到抱歉。 (編輯(cmaster):現在應該修復。希望您喜歡新的措辭。)

如果X通常是一個指針,則sizeof X不會告訴您X指向的數組的大小。 大小必須作為參數傳遞。

要真正理解C函數無法執行所需功能的原因,您需要了解數組與指針之間的區別,以及數組衰減為指針的含義。 只是讓您了解我在說什么:

int array[7];    //define an array
int* pointer = array;    //define a pointer that points to the same memory, array decays into a pointer to the first int

//Now the following two expressions are precisely equivalent, since array decays to a pointer again:
pointer[3];
array[3];

//However, the sizeof of the two is not the same:
assert(sizeof(array) == 7*sizeof(int));    //this is what you used in your define
assert(*pointer == sizeof(int));    //probably not what you expected

//Now the thing gets nasty: Array declarations in function arguments truly decay into pointers!
void foo(int bar[9]) {
    assert(sizeof(bar) == sizeof(int));    //I bet, you didn't expect this!
}

//This is, because the definition of foo() is truly equivalent to this definition:
void foo(int* bar) {
    assert(sizeof(bar) == sizeof(int));
}

//Transfering this to your #define, this will definitely not do what you want:
void baz(char aBuffer[BUFFER_SIZE], const char* source) {
    strcpy2(aBuffer, source);    //This will copy only the first four or eight bytes (depending on the size of a pointer on your system), no matter how big you make BUFFER_SIZE!
}

希望我現在已經誘使您使用Google進行數組指針衰減...

事實是,C語言在很大程度上依賴於以下事實:不需要數組大小即可正確訪問數組元素,只有周圍的循環才需要知道大小。 這樣,數組在許多地方都會衰減為純指針,一旦它們衰減,就無法恢復數組的大小。 這給語言帶來了極大的靈活性和簡單性(非常容易處理子數組!),但同時也使行為像#define的函數成為不可能。

技術原因是:在C語言中,緩沖區大小無法自動檢查,因為它不受語言管理。 諸如strcpy函數對指針進行操作,盡管指針指向緩沖區,但strcpy實現無法知道緩沖區的長度。 您使用sizeof建議不起作用,因為sizeof返回對象的大小,而不是指針指向的緩沖區的大小。 (在您的示例中,它將始終返回相同的數字,最有可能是4或8)。

C語言使程序員負責管理緩沖區大小,因此可以使用諸如strncpy函數並顯式傳遞緩沖區大小。 但是永遠不可能在C中實現strcpy安全版本,因為它將要求語言處理指針的方式發生根本變化。

所有這些都同樣適用於Objective C的C ++之類的C后代。

#include <stdlib.h>

char* x;

if (!asprintf(&x, "%s", y)) {
    perror("asprintf");
    exit(1);
}

// from here, x will contain the content of y

在假設y為Null終止的情況下,這可以安全地工作。

(在平板電腦上寫了一個,所以請原諒任何愚蠢的錯誤。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM