首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C 堆疊緩衝區溢出未崩潰分析:未定義行為、編譯器優化與記憶體佈局

     編輯:程式設計疑難解答

代碼

void hello(void) { fprintf(stderr, "hello!\n"); }
void fun(void) {
    void *buf[10];
    static int i;
    for (i = 0; i < 100; i++) buf[i] = hello;
}
int main(void) {
    int buf[1000];
    fun();
    return 0;
}

為何未崩潰?

  • 未定義行為 (UB):C 標準不保證越界會崩潰,僅說行為不可預測。
  • 棧佈局:main 的 buf[1000] 在棧上分配,fun 的 buf[10] 在更高位址。寫入 buf[10]~buf[99] 覆蓋了 main 的局部變數區域,但未觸碰返回地址或關鍵控制數據。
  • 編譯器優化:static int i 放在數據段,非棧上。hello 函數指針寫入未使用的棧空間,恰好未破壞關鍵幀。

危險性

  • 看似正常實則已破壞棧完整性,稍微改動(加變數、開啟優化、換編譯器)即崩潰。
  • 惡意利用:覆蓋返回地址實現代碼注入(緩衝區溢出攻擊)。

防護手段

  1. 編譯開啟 -fstack-protector-strong -D_FORTIFY_SOURCE=2 (GCC/Clang) 或 /GS (MSVC)。
  2. 使用安全函數:strcpy_s, memcpy_s, scanf_s。
  3. 靜態分析工具:cppcheck, Clang Static Analyzer, Coverity。
  4. 運行時檢測:AddressSanitizer (-fsanitize=address) 精準捕獲越界。

結論

**不崩潰 ≠ 正確**。越界寫入屬嚴重 Bug,必須修復。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved