a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 編程 > C > 正文

淺析C語言編程中的數組越界問題

2020-01-26 14:49:27
字體:
來源:轉載
供稿:網友

因為C語言不檢查數組越界,而數組又是我們經常用的數據結構之一,所以程序中經常會遇到數組越界的情況,并且后果輕者讀寫數據不對,重者程序crash。下面我們來分析一下數組越界的情況:
1) 堆中的數組越界

因為堆是我們自己分配的,如果越界,那么會把堆中其他空間的數據給寫掉,或讀取了其他空間的數據,這樣就會導致其他變量的數據變得不對,如果是一個指針的話,那么有可能會引起crash

2) 棧中的數組越界

因為棧是向下增長的,在進入一個函數之前,會先把參數和下一步要執行的指令地址(通過call實現)壓棧,在函數的入口會把ebp壓棧,并把esp賦值給ebp,在函數返回的時候,將ebp值賦給esp,pop先前棧內的上級函數棧的基地址給ebp,恢復原棧基址,然后把調用函數之前的壓入棧的指令地址pop出來(通過ret實現)。

棧是由高往低增長的,而數組的存儲是由低位往高位存的 ,如果越界的話,會把當前函數的ebp和下一跳的指令地址覆蓋掉,如果覆蓋了當前函數的ebp,那么在恢復的時候esp就不能指向正確的地方,從而導致未可知的情況,如果下一跳的地址也被覆蓋掉,那么肯定會導致crash。

-------------------------

 壓入的參數和函數指針

-------------------------

                        aa[4]

                        aa[3]

合法的數組空間   aa[2]

                        aa[1]

                        aa[0]

-------------------------

 

###sta.c###

#include <stdio.h>void f(int ai){int aa[5]={1,2,3};int i = 1;for (i=0;i<10;i++) aa[i]=i;printf("f()/n");}void main(){f(3);printf("ok/n");}  ###sta.s###     .file  "sta.c"                 ;說明匯編的源程序    .section    .rodata           ;說明以下是只讀數據區.LC0:    .string "f()"                  ;"f()" 的類型是string,地址為LC0    .text                       ;代碼段開始.globl f                         ;f為全局可訪問    .type  f, @function            ; f是函數f:    pushl  %ebp    movl  %esp, %ebp    subl  $40, %esp    movl  $0, -24(%ebp)    movl  $0, -20(%ebp)    movl  $0, -16(%ebp)    movl  $0, -12(%ebp)    movl  $0, -8(%ebp)    movl  $1, -24(%ebp)    movl  $2, -20(%ebp)    movl  $3, -16(%ebp)    movl  $1, -4(%ebp)    movl  $0, -4(%ebp)    jmp   .L2.L3:    movl  -4(%ebp), %edx    movl  -4(%ebp), %eax    movl  %eax, -24(%ebp,%edx,4)    addl  $1, -4(%ebp).L2:    cmpl  $9, -4(%ebp)    jle   .L3    movl  $.LC0, (%esp)    call  puts    leave    ret    .size  f, .-f                     ;用以計算函數f的大小    .section    .rodata.LC1:    .string "ok"    .text.globl main    .type  main, @functionmain:    leal  4(%esp), %ecx    andl  $-16, %esp    pushl  -4(%ecx)    pushl  %ebp    movl  %esp, %ebp    pushl  %ecx    subl  $4, %esp    movl  $3, (%esp)    call  f    movl  $.LC1, (%esp)    call  puts    addl  $4, %esp    popl  %ecx    popl  %ebp    leal  -4(%ecx), %esp    ret    .size  main, .-main    .ident "GCC: (GNU) 4.1.2 20070115 (SUSE Linux)"        ;說明是用什么工具編譯的    .section    .note.GNU-stack,"",@progbits

 

從main函數開始壓入f函數的參數開始,堆棧的調用情況如下

20151117171954436.gif (341×267)

圖1  壓入參數

20151117172018789.gif (315×241)

圖二  通過call 命令壓入下一跳地址 IP

20151117172103760.gif (319×250)

圖三  函數f 通過pushl   %ebp 把 ebp保存起來

20151117172121305.gif (414×210)

圖四  函數 f 通過movl    %esp, %ebp讓ebp指向esp,這樣esp就可以進行修改,在函數返回的時候用ebp的值對esp進行恢復

20151117172136004.gif (407×540)

圖五  函數 f 通過subl    $40, %esp 給函數的局部變量預留空間

20151117172152902.gif (418×531)

圖六  int數組 aa[5]占用了20個字節的空間,然后 int i占用了4個字節的空間(緊鄰著之前壓入棧的%ebp)

故,如果aa[5]進行賦值,則會把 i 的值覆蓋掉,

如果對aa[6]進行賦值,則會把 棧中的 %ebp 覆蓋掉,那么在函數 f 返回的時候則不能對ebp進行恢復,即main函數的ebp變成了我們覆蓋掉的值,程序不知道會發生什么事情,但因為我們的程序接下來沒有調用棧中的內容,故還是可以運行的。

如果對aa[7]進行賦值,則會把棧中的 %IP 覆蓋掉,在函數 f 返回的時候就不能正確地找到下一跳的地址,會crash;

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 国产蜜臀97一区二区三区 | 涩涩av | 免费看片91| 97爱爱视频 | 日韩一区二区三区在线 | 日韩av电影网 | 欧美 日韩 在线播放 | 午夜看片在线观看 | 欧美一级黄色片 | 日韩欧美综合 | 日本不卡中文字幕 | 九九热免费精品视频 | 免费a在线看 | www.一区| 一级看片 | 亚洲人人艹 | 99国产精品99久久久久久 | 日本另类αv欧美另类aⅴ | 91视频免费版污 | 欧美激情一区二区三级高清视频 | 国产成人免费av一区二区午夜 | 欧美午夜一区二区三区免费大片 | 日韩在线免费 | 日韩亚洲一区二区 | 免费在线一区二区三区 | 日韩成人高清 | 欧美成人免费 | 日本xxxxx片免费观看19 | 精品999 | 欧美一区在线观看视频 | 日韩9999| 亚洲成av人片一区二区梦乃 | 欧洲一级免费 | 国产一区二区在线播放 | 国产精品中文字幕在线播放 | 欧美在线观看网站 | 国外成人在线视频网站 | 国产一区 | 一区二区视频网站 | 99视频精品在线 | 天天夜碰日日摸日日澡 |