2012-04-11 30 views
5

Một cách rõ ràng để gây ra tràn ngăn xếp và nhận được Segmentation fault sẽ là đệ quy đẩy khung chồng lên nhau cho đến khi nó bùng nổ. Tôi tự hỏi nếu chồng tràn có thể xảy ra mà không cần đẩy khung stack mới.Làm thế nào để tràn ngăn xếp mà không cần đẩy khung ngăn xếp mới?

Tạo một mảng đủ lớn có thể làm điều đó quá từ kinh nghiệm, nhưng bất kỳ tình huống nào khác có thể xảy ra?

+0

Điều này sẽ ở trong môi trường Linux/UNIX. –

+1

'alloca' và VLAs. – Mat

Trả lời

3

C99 sử dụng một mảng có thể thay đổi kích cỡ mà bạn có thể sử dụng và tiếp tục đổi kích thước thành hình lớn hơn. Tuy nhiên mảng có thể thay đổi kích thước này được triển khai bằng cách sử dụng alloca. Dưới đây là một mẫu mã trong UNIX env:

#include <stdio.h> 
#include <alloca.h> 
#include <stdlib.h> 
#include <stdbool.h> 

int 
main() 
{ 
    while (true) 
    { 
     void *p = alloca(32UL); 
     printf("new memory allocated at %p \n", p); 
    } 
    exit(EXIT_SUCCESS); 
} 

Và đầu ra của bạn sẽ trông như thế này

new memory allocated at 0xbf800a60 
new memory allocated at 0xbf800a30 
new memory allocated at 0xbf800a00 
new memory allocated at 0xbf8009d0 
new memory allocated at 0xbf8009a0 
[1] 3977 segmentation fault ./a.out 

alloca là trong gia đình malloc chức năng, ngoại trừ việc nó được phân bổ bộ nhớ trên stack bằng cách điều chỉnh con trỏ ngăn xếp.

1

Lạm dụng alloca() hoặc _alloca() nếu bạn đang phát triển trên Windows SDK/VS:

Các alloca() chức năng phân bổ byte kích thước của không gian trong stack frame của gọi.

Lưu ý _alloca() hiện không được dùng để ủng hộ _malloca().

1

Về cơ bản, việc nói "ngăn xếp" chỉ là một số bộ nhớ và tràn ngăn xếp là khi ESP/EBP thoát khỏi giới hạn của bộ nhớ này.

Bạn có thể thực hiện điều này trong một số cách sau:

  1. Tạo một mảng đống phân bổ rất lớn đó là lớn hơn kích thước của ngăn xếp không gian còn lại: int x[10000000];
  2. Đặt ESP trực tiếp: __asm mov esp, 0x0
  3. Tham nhũng ngăn xếp sao cho khi chức năng hiện tại được giải phóng, ESP/EBP sẽ được đặt thành rác: int x; memset(&x, 0, 10000000);

Và danh từ tless cách khác ...

1

Bằng cách khai báo và sử dụng một mảng lớn hơn kích thước ngăn xếp của bạn:

$ ulimit -s 
8192 
$ 

sau đó

int main(void) 
{ 
    volatile char bla[8192 * 1024 + 16] = {0}; 
} 

có khả năng segfault khi thực thi.

+0

lý do loại dễ bay hơi? –

+0

trong ví dụ của tôi để tránh trình biên dịch tối ưu hóa nó ra vì nó không được sử dụng ở nơi khác trong chương trình. Nếu bạn tạo một vòng lặp 'for' để in tất cả các phần tử bằng cách sử dụng' printf', bạn sẽ không cần hàm lượng 'volatile' khi trình biên dịch không thể tối ưu hóa nó. – ouah

Các vấn đề liên quan