2015-07-14 5 views
2

Следующая программа поражает ошибку сегментации, и я не могу понять, в чем проблема.Ошибка сегментации при использовании 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 } 

Я пытался в БГД, и он говорит мне, что проблема заключается в 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 

Можете ли вы помочь мне найти проблему?

+3

[в риторическом режиме] вы проверяли успех 'fopen()'? –

+1

Вы можете использовать 'writeformat (fp,"% s "," /modules.php?name = ..... '. – alk

ответ

7

Ваша строка формата содержит символы экранированного пробела. Побег делается с знаками процента, HTML стиль:

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

Эти знаки процента имеют значение в printf строк формата стиля. Вы должны либо вынести пространства дословно:

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

или использовать printf «s собственный побег для печати знаки процента, а именно %%:

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

или, как алк указывает на комментарий, используйте строку формат и распечатать строку в качестве аргумента:

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

, который является лучшим способом для печати строк, которые имеют или могут иметь форматирование спецификаторов дословно.

Вы получаете нарушение сегментации, потому что каждый формат, указанный в %, кроме %%, ожидает дополнительный аргумент. Например, %20A с печатью двоичного представления поплавка ширины 20. Поэтому он ожидает двойной аргумент, но вы не указали никаких аргументов, поэтому vprintf пытается освободить память за пределы списка переменных.

Многие компиляторы могут предупреждать вас о несоответствиях формата для известных функций printf. Некоторые компиляторы позволяют маркировать аргументы ваших собственных функций как printf как строки формата. Атрибуты SAL или gcc в Microsoft позволят вам это сделать.

+1

Это ... a _forward_ tick ?! –

+0

@LightnessRacesinOrbit: Я думаю, вы имеете в виду искаженная компоновка? Это был передний тик, который на моей клавиатуре находится на том же ключе, что и обратный тик, и удерживая клавишу сдвига в то же время, с другой стороны, трудно. Я исправил форматирование, спасибо. –

+0

Я не жаловался, просто интересовался :) –

1

При передаче строк до vfprintf символ % интерпретируется как введение в спецификацию преобразования. Чтобы удержать % дословно, вам придется сбежать от него. Это делается путем замены каждого % на спецификацию преобразования %%.

2

vfprintf думает, что вы передаете некоторые varargs с данными в них, потому что ваша строка формата содержит %.

Похоже, вы имели в виду для тех, кто % для печати дословно, так что вы должны избежать их как %%:

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

Кстати, что /*, вероятно, не должно быть и сам запрос кажется странным. Либо это действительно странный код, либо вы не в порядке.

0

GCC будет поймать ошибку форматной строки во время компиляции если вы отметили writeformat как принимать printf -style строку формата:

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

Попутно я допрашивать тип void возврата - вы на самом деле означает игнорировать возвращаемое значение vprintf?