4

我正在编写一个代理服务器,我遇到了一个奇怪的错误,我希望有人能够解释。

我收到来自客户端的 GET 请求的第一行。例如,客户端将发送请求:

GET http://en.wikipedia.org/wiki/Special:Random HTTP/1.0
Host: en.wikipedia.org
...

我会将此请求转发给服务器。

但是,对于某些网址,我会遇到一个问题:

GET http://map.media6degrees.com/orbserv/curl=http%3A%2F%2Fwww.masteringemacs.org%2Farticles[trunc] HTTP/1.0

我将这一行读入char buffer[MAXLINE_LENGTH],它的长度足以容纳字符串。

当我打印收到的获取请求时

printf(buffer);

打印出来的字符串是:

GET http://map.media6degrees.com/orbserv/hbpix?pixId=2869&curl=http0X0.0000000000015P-10220.0000000.000000www.masteringemacs.org0.000000articles0.00000020100.000000110.000000010.000000running-shells-in-emacs-overview204741995430849962482228271154502456423284733956118041206315879167624419264810411254941012469231829496710329852458403099883653794777355548418601638730167027236864.000000 HTTP/1.0

似乎 %3A、%2F 等已被格式化。

当我运行时printf("%s", buffer);,我得到正确和预期的输出

编辑:我明白为什么会这样;我对为什么会这样发生很感兴趣。printf 是“字符串格式”的值是否来自堆栈上的某个任意区域?%3A et al 是有效的格式字符串吗?

4

4 回答 4

7

1) 如果您查看函数原型,您会看到 printf() 需要一个格式字符串和零个或多个参数。所以,严格来说,“printf(string)”是正确的:

SYNOPSIS
       #include <stdio.h>

       int printf(const char *format, ...);
       int fprintf(FILE *stream, const char *format, ...);
       int sprintf(char *str, const char *format, ...);
       int snprintf(char *str, size_t size, const  char  *format,
       ...);

2) 第一个参数被解释为格式字符串,它找到的任何“%XXX”条目都将被解释为占位符。这听起来正是正在发生的事情:)

3)当然,解决方案是printf ("%s", string)

4)或使用puts(string)代替:)

于 2012-12-03T21:33:36.827 回答
5

切勿将输入字符串用作 printf 的格式参数。

要正常工作,它必须没有“%...”项。这些是 printf() 函数用于访问参数列表的特殊命令。

于 2012-12-03T21:32:10.597 回答
1

在and函数族的format参数中被视为转义字符。你的原始输入有一些,并试图解释它们。printfscanf%printf

于 2012-12-03T21:33:06.357 回答
0

如果使用 printf(string),则打印的字符串可能为 NULL。
这是我看到的唯一问题。 printf 函数根据提供的格式读取所有 va_list 参数,因此如果传递 NULL 指针,它可能会崩溃。使用 LLVM 4.1,我收到以下警告:

Format string is not a literal string (potentially insecure)

这是我个人的意见:如果您确定字符串不为 NULL(可能通过断言验证它,然后在版本中删除该断言),那么您可以使用 printf(string)。如果您不完全确保字符串可能为 NULL 或无效,然后使用文字字符串。

于 2012-12-03T22:15:05.773 回答