0

I am getting a segmentation fault when I try to run access a page using the server, as well as 404 and 403 errors. I used Valgrind, and it states "Conditional jump or move depends on uninitialised value(s)" for needle1, needle2, among many others.

Could someone please give me a clue how to address this?

while (true) { // reset server's state reset();

    // wait until client is connected
    if (connected())
    {
        // parse client's HTTP request
        ssize_t octets = parse();
        if (octets == -1)
        {
            continue;
        }

        // extract request's request-line
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
        const char* haystack = request;
        char* needle = strstr(haystack, "\r\n");
        if (needle == NULL)
        {
            error(400);
            continue;
        }
        else if (needle - haystack + 2 > LimitRequestLine)
        {
            error(414);
            continue;
        }   
        char line[needle - haystack + 2 + 1];
        strncpy(line, haystack, needle - haystack + 2);
        line[needle - haystack + 2] = '\0';

        // log request-line
        printf("%s", line);
        char* needle1 = strchr(line,32);
        if (needle1 == NULL)
        {
            error(400);
            continue;
        }
        char method[needle1-line+2+1];
        strncpy(method,line,needle1-line);
        method[needle1-line+2]='\0';
        printf("The method is %s.  The length is %lu.\n", method,strlen(method));//test line
        char* needle2 = strrchr(line,32);
        if (needle2 == NULL)
        {
            error(400);
            continue;
        }
        char requesttarget[needle2-needle1+2];
        strncpy(requesttarget,needle1+1,needle2-needle1-1);
        requesttarget[needle2-needle1+1]='\0';
        printf("The request-target is %s; it is %lu in length.\n", requesttarget,strlen(requesttarget));//test line

        char* needle3 = strstr(line,"\r\n");
        if (needle3 == NULL)
        {
            error(400);
            continue;
        }
        char HTTPver[needle3-needle2];
        strncpy(HTTPver,needle2+1,needle3-needle2-1);
        HTTPver[needle3-needle2-1]='\0';
        printf("The version is %s! The length is %lu.\n", HTTPver, strlen(HTTPver));//test line


        // Complete?: validate request-line NO


        // if method not GET, error 405
        if (strcasecmp(method,"GET")!=0)
        {
            error(405);
            printf("length method %lu; the method is %s.\n",strlen(method),method);
            printf("length GET %lu\n",strlen("GET"));
        }
        // if request-target does not begin with /, error 501
        if(strncmp(requesttarget,"/",1))
        {
            printf("Request-target does not being with backslash.\n");//my test comment
            error(501);
        }

        // if request-target contains ", error 400
        if(strchr(requesttarget,34)!=NULL)
        {
            error(400);
        }

        // if HTTP-version is not HTTP/1.1, error 505
        if(strcasecmp(HTTPver,"HTTP/1.1")!=0)
        {
            printf("The HTTP version is %s-length is %lu. The first character is %c.  The last character is %c.\n",HTTPver,strlen(HTTPver),HTTPver[0],HTTPver[strlen(HTTPver)-1]);
            printf("The HTTP version is %s-length is %lu\n","HTTP/1.1",strlen("HTTP/1.1"));
            error(505);
        }

        //if absolute-path does not contain ., error 501
        char* absolutepath=requesttarget;
        if(strchr(requesttarget,63)!=NULL)
        {
            int abspathlength=(requesttarget-strchr(requesttarget,63)-sizeof(char))/sizeof(char);
            strncat(absolutepath,requesttarget,abspathlength);
        }
        /*if(strchr(requesttarget,46)==NULL)
        {
            printf("abs-path doesn't contain a period.\n");//my test comment
            error(501);
        }*/

        // Complete?: extract query from request-target
        char* s= strchr(requesttarget,63); //check here for an error in server.c
        char* query="";
        //char query[strchr(requesttarget,0)-s+1];//need to change here, makes no sense if null, can't move to if statement
        if((s==NULL)||((s-requesttarget)==strlen(requesttarget)))
        {
            query= "";
        }
        else
        {
            strncpy(query,s+1,strchr(requesttarget,0)-s-1);
            query[strchr(requesttarget,0)-s]='\0';
        }


        // Complete?: concatenate root and absolute-path
        char* path = "";
        strcat(root,absolutepath);

        // Complete?: ensure path exists
        if(access(path,F_OK)!=0)
        {
            error(404);
        }

        // Complete?: ensure path is readable
        if(access(path,R_OK)!=0)
        {
            error(403);
        }

        // TODO: extract path's extension
        char* ext= strchr(absolutepath,46);
        char* extension = ext+sizeof(char);



        // dynamic content
        if (strcasecmp("php", extension) == 0)
        {
            // open pipe to PHP interpreter
            char* format = "QUERY_STRING=\"%s\" REDIRECT_STATUS=200 SCRIPT_FILENAME=\"%s\" php-cgi";
            char command[strlen(format) + (strlen(path) - 2) + (strlen(query) - 2) + 1];
            sprintf(command, format, query, path);
            file = popen(command, "r");
            if (file == NULL)
            {
                error(500);
                continue;
            }

            // load file
            ssize_t size = load();
            if (size == -1)
            {
                error(500);
                continue;
            }

            // subtract php-cgi's headers from body's size to get content's length
            haystack = body;
            needle = memmem(haystack, size, "\r\n\r\n", 4);
            if (needle == NULL)
            {
                error(500);
                continue;
            }
            size_t length = size - (needle - haystack + 4);

            // respond to client
            if (dprintf(cfd, "HTTP/1.1 200 OK\r\n") < 0)
            {
                continue;
            }
            if (dprintf(cfd, "Connection: close\r\n") < 0)
            {
                continue;
            }
            if (dprintf(cfd, "Content-Length: %i\r\n", (int)length) < 0)
            {
                continue;
            }
            if (write(cfd, body, size) == -1)
            {
                continue;
            }
        }

        // static content
        else
        {
            // look up file's MIME type
            const char* type = lookup(extension);
            if (type == NULL)
            {
                printf("Mime type is null.");//my test comment
                error(501);
                continue;
            }

            // open file
            file = fopen(path, "r");
            if (file == NULL)
            {
                error(500);
                continue;
            }

            // load file
            ssize_t length = load();
            if (length == -1)
            {
                error(500);
                continue;
            }

            // TODO: respond to client
            if (dprintf(cfd, "HTTP/1.1 200 OK\r\n") < 0)
            {
                continue;
            }
            if (dprintf(cfd, "Connection: close\r\n") < 0)
            {
                continue;
            }
            if (dprintf(cfd, "Content-Length: %i\r\n", (int)length) < 0)
            {
                continue;
            }
            if (dprintf(cfd, "Content-Type: %s\r\n", type) < 0)
            {
                continue;
            }
            if (write(cfd, body, length) == -1) //size undeclared
            {
                continue;
            }
        }

        // announce OK
        printf("\033[32m");
        printf("HTTP/1.1 200 OK");
        printf("\033[39m\n");
    }
}
3
  • i saw this line char line[needle - haystack + 2 + 1]; and i'm wondering if you meant char line[needle - (haystack + 2) + 1]; which are different. Perhaps you should check in this and in other parts of your code if you're not trying to write at an forbidden address, so getting back this segfault. I think gdb is better then valgrind to debug this kind of error, run gdb with the name of the executable followed by space and the name of the core file, it'll give you a glimpse of where the segfault occurs.
    – user10187
    Commented Dec 10, 2015 at 14:36
  • Why are those different things? Could you please explain? I can't seem to debug in gdb. What do you mean by "the core file"? Commented Dec 10, 2015 at 18:14
  • I do understand what you mean regarding the line[needle-haystack+2+1]; one adds 2, the other subtracts 2. However, that isn't the problem because that bit of code was given to me as source code, and I know it is correct. (I do not get any valgrind errors on that bit of code.) The code I wrote begins after the comment //Log the request-line. I don't know how to debug this in gdb. Basically, I launch this program as a server and then try to visit the index of my site. Can anyone else comment on how I would need to initialize the variables like needle1 and method? Commented Dec 11, 2015 at 1:28

1 Answer 1

0

There is a problem with this line:

int abspathlength=(requesttarget-strchr(requesttarget,63)-sizeof(char))/sizeof(char);

[EDIT]: requesttarget - strchr(requesttarget,63) will return a negative number because the address of requesttarget "is less than" the address of '?' in requesttarget. Swap the order.

To run server in gdb (or any program that requires command line arguments).

$ gdb server
(gdb) set your break point(s)
(gdb) run -p {port} {path-to-root}

In other words, the arguments you would use to call server from the command line. Type help run in gdb for more info.

You must log in to answer this question.

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