[英]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.