
int parse_request(const char *request, char *method,
char *hostname, char *port, char *uri) {
if (!is_complete_request(request)) {
return 0;
}
char reqCpy[strlen(request)];
strcpy(reqCpy, request);
strcpy(method, strtok(reqCpy, " "));
strtok(NULL, "//");
char* url = strtok(NULL, " ");
printf("URL is %s\n", url);
if (strstr(url, ":") == NULL) {
char newCpy[strlen(request)];
strcpy(newCpy, request);
strtok(newCpy, "//");
char* name = strtok(NULL, "/");
strcpy(hostname, name);
strcpy(port, "80");
} else {
char newCpy[strlen(request)];
strcpy(newCpy, request);
strtok(newCpy, "//");
char* name = strtok(NULL, ":");
strcpy(hostname, name);
strcpy(port, strtok(NULL, "/"));
}
//printf("URI: %s", uri);
return 1;
}req1 = "GET http://www.example.com/index.html HTTP/1.0\r\n“”主机: www.example.com\r\n“用户代理: Mozilla/5.0 (X11;Linux x86_64;rv:68.0) Gecko/20100101火狐/68.0\r\n”接受-语言: en-US,en;q=0.5\r\n\r\n";
req2 = "GET http://www.example.com:8080/index.html?foo=1&bar=2 HTTP/1.0\r\n“”主机:www.example.com:8080\r\n““用户-代理: Mozilla/5.0 (X11;Linux x86_64;rv:68.0) Gecko/20100101火狐/68.0\r\n”接受-语言: en-US,en;q=0.5\r\n\r\n";
发布于 2021-03-18 15:55:49
这就是strtok的工作方式。它当然不是世界上最方便的界面,但至少它已经被合理地记录下来了。
您似乎假设strtok(…, "//");使用字符串"//"作为分隔符。但是strtok的第二个参数不是单个的,可能是多字符分隔符。它是一组可能的单个分隔符字符,其中任何或所有字符都将被视为分隔符。有关细节,请参阅strtok命令页。
你会发现很多关于strtok的警告漂浮在网络上,其中很多都是合理的。但是,您的代码中的"gotcha“并不多见,这与您使用不同的分隔符集两次调用strtok时发生的情况有关。
回顾一下,strtok首先跳过分隔符字符,然后跳过非分隔符字符,然后用0覆盖下一个分隔符字符(如果有)。它将下一个字符的地址保存在下一个调用中。
当分隔符集不改变时,它会像预期的那样工作。而且它在字符串上的工作方式与预期一样,没有重复的分隔符。但是,当字符串具有重复的分隔符,并且为第二个令牌更改分隔符集时,就会有一个奇怪的现象。意外的结果(在您的例子中,是一个神秘的/)是由于对strtok的第一次调用只删除了令牌后面的第一个分隔符字符。如果令牌后面跟着一系列分隔符字符,那么对strtok的下一次调用需要跳过这个序列的其余部分。当然,如果分隔符集没有改变,它就会这样做。但是,如果您更改了第二个调用的分隔符集,那么从第一个调用中被认为是分隔符的不再是第二个调用中的分隔符,它们不会被跳过,这可能与预期相反。
我的猜测是,对于您所要做的事情,strtok并不是最好的标准库函数。我建议综合考虑以下几点:
strstr查找多字符字符串,如//。strchr查找下一个特定字符的出现。strpbrk查找一组字符之一的下一次出现。strspn和strcspn用于查找一组字符(或一组字符的倒数)序列的长度。注意,前三个函数的返回值与后两个函数的返回值不同。前三个函数提供一个指向正在搜索的子字符串/字符的指针,如果搜索失败,则为NULL。最后两个函数计算到集合的一个成员的字符数;如果它们找不到一个,它们只返回字符串中剩下的字符数。(这种行为通常更容易使用,这就是为什么将函数添加到C标准中的原因。)
注意:您还需要修复@chux标识的缓冲区溢出。您必须始终意识到需要为字符串的终止NUL (0)分配空间。但是,如果您重写代码以避免使用strtok,您可能还会发现需要更少的字符串副本,甚至不需要任何字符串副本。
发布于 2021-03-18 03:00:01
导致未定义行为(UB)的各种问题包括
char reqCpy[strlen(request)];
strcpy(reqCpy, request);reqCpy[]太小,由1存储长度为strlen(request)的字符串。还需要一个。
char reqCpy[strlen(request) + 1];
strcpy(reqCpy, request);至少要解决这个问题,否则代码功能的其余部分是有问题的。
https://stackoverflow.com/questions/66683814
复制相似问题