我需要编写一个函数,该函数将从HTTP 1.0中的Authorization Header中获取base64字符串。因此,我写了这个函数:

char* getAuthenticate(char* buffer) {
    const char* AuthorizationLine = calloc(1, sizeof(char));
    char* BasePtr;
    char* CodePtr = calloc(1, sizeof(char));

    //Get Authoriztaion Header
    if(strstr(buffer, "Authorization: ") != NULL) {
        AuthorizationLine = strstr(buffer, "Authorization: ");
        char Copy[strlen(AuthorizationLine)];
        strcpy(Copy, AuthorizationLine);
        AuthorizationLine = strtok(Copy, "\r\n");
    }
    else {
        printf("Error - no valid Authorization Header");
        return NULL;
    }
    //Set CodePtr to the base64 String
    CodePtr = strrchr(AuthorizationLine, " ");
    CodePtr = CodePtr +1;
    return CodePtr;
}


通过在调试器中运行此功能,我发现一切正常,直到进入CodePtr部分。一旦执行CodePtr = strstr(AuthorizationLine, " "),我的授权行将被废话填充,例如“ \020Õÿÿÿ\ 177”。而且CodePtr甚至没有受到影响:直到我执行0x0之前,它的地址一直保持+1,但是只有0x1,并且Eclipse无法访问该地址的内存。

那我做错了什么?我也尝试了strstr(),但是也没有用。

最佳答案

您的函数会泄漏内存。它为一个char分配空间,并为变量AuthorizationLine分配一个指向该空间的指针,但随后在不释放分配的内存的情况下为AuthorizationLine分配了一个新值。您似乎不需要在这里分配任何内存。

您没有声明数组Copy足够大。您还需要空间来容纳字符串终止符。因此,当您复制到该数组时,您将获得不确定的行为。

您将AuthorizationLine设置为指向数组Copy的一部分的指针,但是Copy之后会立即超出范围,而使AuthorizationLine无效的指针。

strrchr()(或strstr())很有可能随后用其局部变量的值覆盖AuthorizationLine指向的任何内存(在堆栈中的某个位置)。 strrchr()返回NULL指针,因为这是在找不到指定字符时执行的操作。

此外,您将指针(输入)返回到局部变量。当Copy超出范围时,这会出现相同的问题。

更新:

这个版本可以解决问题。请注意,它返回指向已分配内存的指针,当不再需要调用者时,调用者必须将其释放。

char* getAuthenticate(char* buffer) {
    /* Get Authoriztaion Header */
    const char* AuthorizationLine = strstr(buffer, "Authorization: ");

    if (AuthorizationLine) {
        /* extract the authorization token */
        char* EndPtr = strstr(AuthorizationLine, "\r\n");
        char* CodePtr;

        if (!EndPtr) {
            /* the header is the last thing in the buffer */
            EndPtr = AuthorizationLine + strlen(AuthorizationLine) - 1;
        }

        /* ignore trailing whitespace */
        while (isspace(*EndPtr)) {
            EndPtr -= 1;
        }
        /* find the start of the authorization token */
        for (CodePtr = EndPtr; !isspace(*CodePtr); CodePtr -= 1 ) {
             if (CodePtr == AuthorizationLine) {
                 printf("Error - invalid authorization header\n");
                 return NULL;
             }
        }

        /* allocate space and copy the token into it */
        ptrdiff_t value_length = ++EndPtr - CodePtr++;
        char *Copy = malloc(value_length + 1);

        if (Copy) {
            strncpy(Copy, CodePtr, value_length);
            Copy[value_length] = '\0';
        } else {
            printf("Error - memory allocation failure\n");
        }
        return Copy;
    } else {
        printf("Error - no Authorization Header\n");
        return NULL;
    }
}

09-17 04:34