C中的字符串意外截断

ybzsozfc  于 2023-04-19  发布在  其他
关注(0)|答案(2)|浏览(139)

我正在读这本书,Hands-On Network Programming with C,在当前的章节中,我阅读我们正在构建一个Web客户端。这个Web客户端的功能之一是解析传递给它的URL,以确定协议,主机名,文档路径等。解析函数的一部分如下:

void parse_url(char *url, char **hostname, char **port, char **path){
    printf("URL: %s\n", url);

    char *p;
    p = strstr(url, "://");

    char *protocol = 0;
    if (p){
        protocol = url;
        printf("Protocol: %s\n", protocol);
        *p = 0;
        p += 3;
    } else {
        p = url;
    }

    printf("Protocol: %s\n", protocol);
    if (protocol){
        printf("Protocol: %s\n", protocol);
        if (strcmp(protocol, "http")){
            fprintf(stderr, "Unknown protocol, '%s'. Only 'http' is supported.\n",
                protocol);
            exit(1);
        }
    }

每当我传入一个没有使用HTTP的URL时,比如https://example.com(他们在书中使用的URL),我都会得到以下输出(我在那里放置了额外的print语句用于调试目的):
网址:https://example.com
协议:https://example.com
协议:https
协议:https
未知协议“https”。仅支持“http”。
我的问题是,指向URL的协议是如何被截断为协议而不是像以前那样被截断为整个URL的?

4dc9hkyq

4dc9hkyq1#

语句p = strstr(url, "://");将在url中找到第一个出现的"://",并将"://"的第一个字节的地址存储在p中。因此,*p将计算为':'。如果没有找到"://",则p将等于NULL
如果找到"://"protocol将被设置为指向url的开头,那么'\0'将被放置在p所指向的地址处。因此,如果url之前包含"https://www.example.com\0",那么现在url包含"https\0//www.example.com\0"(包括末尾的'\0')。
C中的字符串以'\0'结束。因此,任何处理字符串"https\0//www.example.com\0"的函数都会在第一次出现'\0'时停止处理字符串。因此,printf("%s", protocol)将打印"https"strlen(p)将返回5,依此类推。

bvuwiixz

bvuwiixz2#

作为将URL中的':'替换为'\0'的 * 替代方案 *。您可以获取相同的信息并使用指针数学来计算URL的协议部分中有多少个字符,然后使用它将strncpy中的字符数strncpy到另一个缓冲区中。我们将该缓冲区初始化为零,以便在调用strncpy后字符串以null结尾。
这种方法不会破坏原始URL字符串。

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

char *get_protocol(char *url);

int main() {
    char url[] = "https://www.example.com";
    char *protocol = get_protocol(url);

    printf("%s\n", protocol);

    free(protocol);

    return 0;
}

char *get_protocol(char *url) {
    char *p = strstr(url, "://");
    
    if (!p) return NULL;

    size_t len = p - url;
    char *result = calloc(len + 1, 1);

    if (!result) return NULL;

    strncpy(result, url, len);
    
    return result;
}

结果:https

相关问题