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

C 語言 vfprintf 段錯誤排查:%20 格式字串陷阱

     編輯:關於C語言

錯誤現象

Program received signal SIGSEGV, Segmentation fault.
0x0098735e in vfprintf () from /lib/libc.so.6
#1  0x0098e3cf in fprintf () from /lib/libc.so.6

將 fprintf 改為 printf 即正常,初步懷疑緩衝區或檔案指標問題,實際為格式字串漏洞。

根本原因

格式字串中包含 %20(URL 編碼空格),被 vfprintf 解析為:

  • %:格式指示符開頭
  • 20:最小寬度 20
  • 後續字元若為 s、d 等 → 期望對應引數

實際呼叫未提供足夠引數,導致 va_arg 讀取亂碼指標,觸發段錯誤。

重現範例

char *url = "path%20to%20file";
fprintf(fp, "URL: %s\n", url);  // 正常

// 危險:格式字串來自外部輸入
char *fmt = get_user_format();  // 可能包含 "%20s"
fprintf(fp, fmt, arg1);         // 崩潰或資訊洩漏

安全修正

  1. 永遠使用字面常數格式字串:
// 錯誤
fprintf(fp, user_string);

// 正確
fprintf(fp, "%s", user_string);
  1. 若需動態格式,嚴格驗證或使用 snprintf 組合:
char safe_fmt[64];
snprintf(safe_fmt, sizeof(safe_fmt), "%%%ds", width);  // 產生 "%20s"
fprintf(fp, safe_fmt, str);

同類風險函數

  • printf、sprintf、snprintf、vprintf、vsprintf、vsnprintf
  • syslog、err、warn 等系統日誌函數

編譯器防護

gcc -Wformat -Wformat-security -Werror=format-security
  • -Wformat:檢查格式字串與引數匹配
  • -Wformat-security:警告非字面常數格式字串
  • -D_FORTIFY_SOURCE=2:執行期緩衝區檢查

最佳實務

  1. 格式字串永遠為字面常數
  2. 使用者輸入永遠作為引數傳入,而非格式字串
  3. 啟用編譯器警告並視為錯誤
  4. 程式碼審查時檢查所有 printf 族函數呼叫點
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved