簡體   English   中英

使用vfprintf()時出現分段錯誤

[英]Segmentation fault while using vfprintf()

以下程序遇到了分段錯誤,我無法弄清問題是什么。

  1 #include<stdio.h>
  2 #include<stdarg.h>
  3 void writeformat(FILE*,char*, ...);
  4 int main()
  5 {
  6   FILE *fp;
  7   fp=fopen("file1.txt","w");
  8   writeformat(fp,"/modules.php?name=Top&querylang=%20WHERE%201=2%20ALL%20SELECT%201,pwd,1,1%20FROM%20nuke_authors/*");
  9   fclose(fp);
 10   return(0);
 11 }
 12 
 13 void writeformat(FILE *stream,char *format, ...)
 14 {
 15   va_list args;
 16   va_start(args,format);
 17   vfprintf(stream,format,args);
 18   va_end(args);
 19 }

我試過gdb,它告訴我問題出在vfprintf()

(gdb) run
Starting program: /ws/anaganes-sjc/junk 
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000

Program received signal SIGSEGV, Segmentation fault.
0x0000003c44c7fb30 in wcslen () from /lib64/libc.so.6
(gdb) bt
#0  0x0000003c44c7fb30 in wcslen () from /lib64/libc.so.6
#1  0x0000003c44c80b27 in wcsrtombs () from /lib64/libc.so.6
#2  0x0000003c44c464b2 in vfprintf () from /lib64/libc.so.6
#3  0x0000000000400649 in writeformat (stream=0x601010, format=0x400758 "/modules.php?name=Top&querylang=%20WHERE%201=2%20ALL%20SELECT%201,pwd,1,1%20FROM%20nuke_authors/*") at junk.c:20
#4  0x0000000000400556 in main () at junk.c:9

能幫我找到問題嗎?

您的格式字符串包含轉義空格字符。 使用百分號,HTML樣式完成轉義:

"querylang=%20WHERE%201=2%20ALL%20SELECT%201..."

這些百分號在printf樣式格式字符串中有意義。 您必須逐字渲染空格:

"querylang= WHERE 1=2 ALL SELECT 1..."

或使用printf自己的轉義來打印百分號,即%%

"querylang=%%20WHERE%%201=2%%20ALL%%20SELECT%%201..."

或者,正如注釋中指出的那樣,使用字符串格式並將字符串作為參數打印:

writeformat(fp, "%s", "/modules.php?name=");

這是打印字符串的最佳方式,這些字符串具有或可能具有格式說明符。

您會收到分段違規,因為使用%%%指定的每種格式都需要一個額外的參數。 例如%20A withh打印寬度為20的浮點數的二進制表示。因此,它需要一個double參數,但是您沒有指定任何參數,因此vprintf嘗試超出變量參數列表范圍內的內存。

許多編譯器可以警告您有關眾所周知的printf函數的格式不匹配。 有些編譯器允許您將自己函數的參數標記為printf如格式字符串。 Microsoft的SAL或gcc樣式屬性將允許您這樣做。

vfprintf認為你傳遞了一些帶有數據的varargs,因為你的格式字符串包含%

看起來你的意思是那些%要逐字打印,所以你必須將它們作為%%轉義:

"/modules.php?name=Top&querylang="
"%%20WHERE%%201=2%%20ALL%%20SELECT%%201,pwd,1,1%%20FROM%%20nuke_authors/*"

順便說一下, /*可能不應該存在,查詢本身看起來很奇怪。 要么這是非常奇怪的代碼,要么就是沒有好處。

將字符串傳遞給vfprintf時%字符被解釋為轉換規范的介紹。 為了保住%逐字,你將不得不逃避它。 這是通過將每個%替換為轉換規范%%

如果您將writeformat標記為采用printf樣式的格式字符串,GCC將在編譯時捕獲格式字符串錯誤:

void writeformat(FILE *stream, char *format, ...)
     __attribute__((format (printf, 2, 3)));

順便說一句,我質疑void返回類型 - 你真的是要忽略vprintf的返回值嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM