0

I have a problem in my parse() function of server.c

It took me almost 2 days to get to the specifics of the problem,

the problem is in the abs_path when the request target is:

  • /hello.html, abs_path and query is empty
  • /hello.php?q=alice, abs_path is /hello.p and query is q=alice

request target and query are fine the problem is in abs_path.

Due to this I am getting two errors in check50:

:) server.c exists

:) server compiles

:) HTTP/1.0 returns error code 505

:) Method of 'abcGET' returns error code 405

:) Method of 'GETabc' returns error code 405

:) request-target without starting '/' returns error code 501

:) request-target of abc/hello.php returns error code 501

:( Requesting cat.exe returns error code 501

\ expected output, but not "HTTP/1.1 301 Moved Permanently\r\nLocat..."

:( Requesting non-existant file returns error code 404

\ expected output, but not "HTTP/1.1 301 Moved Permanently\r\nLocat..."

:) Requesting request-target with " returns error code 400

:) Two spaces after GET returns error code

:) A space within the request target returns error code

:) Two spaces before HTTP/1.1 returns error code

here's my parse function:

bool parse(const char* line, char* abs_path, char* query)
{
// copy line to new string
char* temp = malloc(strlen(line) + 1);
if(temp == NULL)
{
    free(temp);
    return false;
}
memset(temp, 0, strlen(line) + 1);
strcpy(temp, line);


// Find method in the request line
if(strncmp(temp, "GET ", 4) != 0)
{
    error(405);
    return false;
}

char* haystack = NULL;
haystack = temp;
char* needle = strstr(haystack, " ");
if(needle == NULL)
{
    return false;
}

// get request-target from the request line
haystack = needle + 1;
needle = strstr(haystack, " ");
if(needle == NULL)
    return false;

char* reqt = malloc(needle - haystack + 1);
if(reqt == NULL)
    return false;
memset(reqt, 0, needle - haystack + 1);

strncpy(reqt, haystack, needle - haystack);
*(reqt + (needle - haystack)) = '\0';

for(int i = 0; strcmp(&reqt[i], "\0") != 0; i++)
{
    if(strcmp(&reqt[i], "\"") == 0)
    {
        error(400);
        return false;
    }
}

if(reqt[0] != 47) //request target must start with a '/'
{
    error(501);
    return false;
}


// get HTTP version from the request line
haystack = needle + 1;
needle = strstr(haystack, "\r\n");
if(needle == NULL)
    return false;

if(strncmp(haystack, "HTTP/1.1", needle - haystack) != 0)
 {
     error(505);
     return false;
 }

// reading abs_path and query from request target
int i = 0;
haystack = reqt;
needle = strstr(haystack, "?");
if(needle == NULL)
{
    needle = strstr(haystack, "\0");
    i = 1;
    if(needle == NULL)
        return false;
}
memset(abs_path, 0, needle - haystack + 1);
strncpy(abs_path, haystack, needle - haystack);
if(abs_path == NULL)
{
    return false;
}
*(abs_path + (needle - haystack)) = '\0';


printf("abs=\n");
for(int i = 0; i < sizeof(abs_path); i++)
{
    printf("%c", abs_path[i]);
}
printf("\nend\n");


if(i == 1)
{
    *query = '\0';
}

else
{
    needle++;
    if(strncmp(needle, "\0", 1) == 0)
    {
        *query = '\0';
    }

    else
    {
        strcpy(query, needle);
        if(query == NULL)
            return false;
    }
}
for(int i = 0; i < sizeof(query); i++)
{
    printf("%c", query[i]);
}
printf("\n%s\n", reqt);

free(temp);
free(reqt);
return true;

}

1

Good detective work so far. The first problem /hello.html, abs_path and query is empty leads us to here

int i = 0;
haystack = reqt;
needle = strstr(haystack, "?");
if(needle == NULL)
{
    needle = strstr(haystack, "\0");
    i = 1;
    if(needle == NULL)
        return false;
}

According to man strstr:

The terminating null bytes ('\0') are not compared.

So what might happen when you search for the terminating null byte? According to this doc

If needle is an empty string, the function returns haystack.

So this line strncpy(abs_path, haystack, needle - haystack); copies how many bytes, when needle = haystack (which is does, here needle = strstr(haystack, "\0");)?

For the second problem, have you determined that abs_path is /hello.p because of this?:

printf("abs=\n");
for(int i = 0; i < sizeof(abs_path); i++)
{
    printf("%c", abs_path[i]);
}
printf("\nend\n");

You need to correct this sizeof(abs_path). abs_path is a pointer, and as such is 8 bytes so sizeof(abs_path) is [always] 8, thus /hello.p.

| improve this answer | |
  • Thank you so much, you are awesome, and also thank you for the valuable resource you provided, It's would be very useful for the future. – Vipin kumar Jul 6 '16 at 14:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .