數組越界怎么處理 數組越界( 二 )


但是要注意,如果這個時候我們根據緩沖區溢出發生的具體情況填充緩沖區,不但可以避免程序崩潰,還會影響到程序的執行流程,甚至會讓程序去執行緩沖區里的代碼 。示例運行結果為:
1請輸入密碼:12345
2密碼錯誤!
3請輸入密碼:123456
4密碼正確!
5請輸入密碼:1234567
6密碼正確!
7請輸入密碼:aaaaaaa
8密碼正確!
9請輸入密碼:0123456
10密碼錯誤!
11請輸入密碼:
在示例代碼中,flag 變量實際上是一個標志變量,其值將決定著程序是進入密碼錯誤的流程(非 0)還是“密碼正確”的流程(0) 。當我們輸入錯誤的字符串1234567或者aaaaaaa,程序也都會輸出“密碼正確” 。但在輸入0123456的時候,程序卻輸出“密碼錯誤”,這究竟是為什么呢?
其實,原因很簡單 。當調用 Test() 函數時,系統將會給它分配一片連續的內存空間,而變量char buffer[7]與int flag將會緊挨著進行存儲,用戶輸入的字符串將會被復制進 buffer[7] 中 。如果這個時候,我們輸入的字符串數量超過 6 個(注意,有字符串截斷符也算一個),那么超出的部分將破壞掉與它緊鄰著的 flag 變量的內容 。
當輸入的密碼不是宏定義的123456時,字符串比較將返回 1 或 -1 。我們都知道,內存中的數據按照 4 字節(DWORD)逆序存儲,所以當 flag 為 1 時,在內存中存儲的是0x01000000 。如果我們輸入包含 7 個字符的錯誤密碼,如aaaaaaa,那么字符串截斷符 0x00 將寫入 flag 變量,這樣溢出數組的一個字節 0x00 將恰好把逆序存放的 flag 變量改為0x00000000 。在函數返回后,一旦 main 函數的 flag 為 0,就會輸出“密碼正確” 。這樣,我們就用錯誤的密碼得到了正確密碼的運行效果 。
而對于0123456,因為在進行字符串的大小比較時,它小于123456,flag的值是 -1,在內存中將按照補碼存放負數,所以實際存儲的不是0x01000000而是0xffffffff 。那么字符串截斷后符 0x00 淹沒后,變成0x00ffffff,還是非 0,所以沒有進入正確分支 。
【數組越界怎么處理數組越界】其實,本示例只是用一個字節淹沒了鄰接變量,導致程序進入密碼正確的處理流程,使設計的驗證功能失效 。

數組越界怎么處理  數組越界

文章插圖

盡量顯式地指定數組的邊界在 C 語言中,為了提高運行效率,給程序員更大的空間,為指針操作帶來更多的方便,C 語言內部本身不檢查數組下標表達式的取值是否在合法范圍內,也不檢查指向數組元素的指針是不是移出了數組的合法區域 。因此,在編程中使用數組時就必須格外謹慎,在對數組進行讀寫操作時都應當進行相應的檢查,以免對數組的操作超過數組的邊界,從而發生緩沖區溢出漏洞 。
要避免程序因數組越界所發生的錯誤,首先就需要從數組的邊界定義開始 。盡量顯式地指定數組的邊界,即使它已經由初始化值列表隱式指定 。示例代碼如下所示:
int a[]={1,2,3,4,5,6,7,8,9,10};
很顯然,對于上面的數組 a[],雖然編譯器可以根據始化值列表來計算出數組的長度 。但是,如果我們顯式地指定該數組的長度,例如:
int a[10]={1,2,3,4,5,6,7,8,9,10};
它不僅使程序具有更好的可讀性,并且大多數編譯器在數組長度小于初始化值列表的長度時還會發生相應警告 。
當然,也可以使用宏的形式來顯式指定數組的邊界(實際上,這也是最常用的指定 *** ),如下面的代碼所示:
#define MAX 10

int a[MAX]={1,2,3,4,5,6,7,8,9,10};
除此之外,在 C99 標準中,還允許我們使用單個指示符為數組的兩段“分配”空間,如下面的代碼所示:
int a[MAX]={1,2,3,4,5,[MAX-5]=6,7,8,9,10};
在上面的a[MAX]數組中,如果 MAX 大于 10,數組中間將用 0 值元素進行填充(填充的個數為MAX-10,并從 a[5] 開始進行 0 值填充);如果 MAX 小于 10,[MAX-5]之前的 5 個元素(1,2,3,4,5)中將有幾個被[MAX-5]之后的 5 個元素(6,7,8,9,10)所覆蓋,示例代碼如下所示:
1#define MAX 10
2#define MAX1 15
3#define MAX2 6
4int main(void)
5{
6 int a[MAX]={1,2,3,4,5,[MAX-5]=6,7,8,9,10};
7 int b[MAX1]={1,2,3,4,5,[MAX1-5]=6,7,8,9,10};
8 int c[MAX2]={1,2,3,4,5,[MAX2-5]=6,7,8,9,10};
9 int i=0;
10 int j=0;
11 int z=0;
12 printf("a[MAX]:\n");
13 for(i=0;i<MAX;i++)
14 {
15 printf("a[%d]=%d ",i,a[i]);
16 }
17 printf("\nb[MAX1]:\n");
18 for(j=0;j<MAX1;j++)

推薦閱讀