首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言 gets 函數漏洞分析與安全替代方案:自定義 Gets 函數實現緩衝區溢出防護

     編輯:關於C語言

gets 函數為何危險

char *gets(char *buf);

致命缺陷:不檢查緩衝區邊界。用戶輸入超過 buf 大小會導致緩衝區溢出,覆蓋相鄰內存,造成程序崩潰或安全漏洞。C11 標準已移除 gets。

漏洞演示

char str[30];
gets(str);  // 輸入 50 個 '1' → 緩衝區溢出 → 未定義行為

安全替代方案設計

提供兩個重載版本的 Gets(大寫區分):

版本一:動態分配,指定最大長度

char *Gets(int maxlen) {
    char *str = (char*)malloc(sizeof(char) * maxlen);
    if (!str) {
        perror("memory allocation error!");
        return NULL;
    }
    
    int i = 0;
    int c;
    while (i < maxlen - 1 && (c = getchar()) != '\n' && c != EOF) {
        str[i++] = c;
    }
    str[i] = '\0';
    return str;  // 調用者負責 free
}

版本二:針對固定大小數組,防野指針

// const 修飾指針本身不可修改,但可修改指向內容
// 類比:char str[30] 中 str 不可改,str[0] 可改
char *Gets(char *const array, int maxlen) {
    int i = 0;
    int c;
    while (i < maxlen - 1 && (c = getchar()) != '\n' && c != EOF) {
        array[i++] = c;
    }
    array[i] = '\0';
    return array;
}

設計細節解析

設計點說明
參數 maxlen限制最大讀取字符數,預留 1 位給 \0
返回 char*鏈式調用便利,兼容原 gets 接口習慣
char *const防止傳入野指針導致崩潰;數組名退化為常量指針完美匹配
循環條件i < maxlen-1 確保不越界;檢查 EOF 處理文件結束
手動添加 \0保證字符串正確終止

使用示例

int main() {
    // 固定數組版
    char s[8];
    Gets(s, 8);
    puts(s);
    
    fflush(stdin);  // 清空輸入緩衝區,關鍵!
    
    // 動態分配版
    char *p = Gets(8);
    puts(p);
    free(p);  // 必須釋放
    
    return 0;
}

標準庫安全替代品

現代 C 開發應優先使用:

  • fgets(buf, size, stdin):標準、安全、保留換行符
  • gets_s(buf, size):C11 Annex K,可選實現
  • getline():POSIX,自動分配內存

核心教訓

  1. 永不使用 gets:任何場景、任何教程都不應出現
  2. 邊界檢查是底線:所有輸入函數必須有長度限制
  3. const 正確性:char *const 防指針篡改,const char* 防內容篡改
  4. 動態內存必配對 free
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved