0

I'm currently on pset6 and having trouble in part 2. I think there's a memory leak somewhere but i'm not sure.

Here's lookup():

const char* lookup(const char* path){
    char* ret = strchr(path, '/');
    ret = strchr(ret, '.');
    char* ext5 = malloc(sizeof(char)* 6);
    ext5 = strncpy(ext5, ret, 5);
    ext5[5] = '\0';
    char* ext4 = malloc(sizeof(char)*5);
    ext4 = strncpy(ext4, ret, 4);
    ext4[4] = '\0';
    char* ext3 = malloc(sizeof(char)*4);
    ext3 = strncpy(ext3, ret, 3);
    ext3[3] = '\0';
    const char* filetype = NULL;
    if(ret != NULL){
        if(strcasecmp(ext5, ".html") == 0){
            filetype = "text/html";
        }
        else if(strcasecmp(ext4, ".css") == 0){
            filetype = "text/css";
        }
        else if(strcasecmp(ext4, ".gif") == 0){
            filetype = "image/gif";
        }
        else if(strcasecmp(ext4, ".ico") == 0){
            filetype = "image/x-icon";
        }
        else if(strcasecmp(ext4, ".jpg") == 0){
            filetype = "image/jpeg";
        }
        else if(strcasecmp(ext4, ".php") == 0){
            filetype = "text/x-php";
        }
        else if(strcasecmp(ext4, ".png") == 0){
            filetype = "image/png";
        }
        else if(strcasecmp(ext3, ".js") == 0){
            filetype = "text/javascript";
        }
    }
    free(ext5);
    free(ext4);
    free(ext3);
    return filetype;
}

parse()

bool parse(const char* line, char* abs_path, char* query)
{
    char* get = "GET ";
    // check GET and space
    if(strncmp(get, line, 4) != 0){
        error(405);
        return false;
    }
    // check if request-target begins with '/'
    if(line[4] != '/'){
        error(501);
        return false;
    }
    char* buffer = strchr(line, '/');
    int q = 0;
    int i;
    // get abs_path and query delimiters and check if request-target contains '"'
    for(i = 0; i < strlen(buffer) && buffer[i] != ' '; i++){
        if(buffer[i] == '"'){
            error(400);
            return false;
        }
        else if(q >= 1 || buffer[i] == '?'){
            q++;
        }
    }
    if(q < 0){
        q = 0;
    }
    abs_path = strncpy(abs_path, buffer, i - q);
    abs_path[i - q] = '\0';
    if(q > 1){
        char* temp = malloc(sizeof(char) * (q + 1));
        int k = 0;
        for(int j = i - q + 1; j < i ; j++, k++){
            temp[k] = buffer[j];
        }
        temp[k] = '\0';
        query = strcpy(query, (const char*)temp);
        free(temp);
    }
    else{
        query = strcpy(query, "");
    }
    // check for space
    if((buffer = strchr(buffer, ' ')) == NULL ){
        error(400);
        return false;
    }
    //check if there's anything before http version
    if(buffer[1] != 'H'){
        error(400);
        return false;
    }
    buffer = strchr(buffer, 'H');
    // check http version
    if(strncmp(buffer, "HTTP/1.1", 8) != 0)
    {
        error(505);
        return false;
    }
    // check CRLF
    if(strlen(buffer) < 9 && (buffer[8] != '\r' || buffer[9] != '\n')){
        error(400);
        return false;
    }
    return true;
}

load()

bool load(FILE* file, BYTE** content, size_t* length)
{
    length = malloc(sizeof(size_t));   
    *length = 0;
    *content = malloc(BYTES * sizeof(BYTE));
    int size = BYTES * sizeof(BYTE);
    char * buffer = malloc(size);
    int read;
    int i = 1;
    while((read = fread(buffer + size * (i - 1), BYTES, BYTES, file)>=1)){
        buffer = realloc(buffer, size * i);
        i++;
        length += read;
    }
    *content = &buffer[0];
    return true;
}

indexes()

char* indexes(const char* path)
{
    char* p = malloc(sizeof(char)*strlen(path)+sizeof(char)*11);
    p = strcpy(p, path);
    p = strcat(p, "index.php");
    if(access(p , F_OK ) != -1){
        return p;
    }
    else{
        p = strcpy(p, path);
        p = strcat(p, "index.html");
        if(access(p , F_OK ) != -1){
            char* pathToIndex = NULL;
            pathToIndex = strcpy(pathToIndex, p);
            free(p);
            return pathToIndex;
        }
    }
    free(p);
    return NULL;
}

This is the output for check50:

:) server.c exists
:) server compiles
:( Requesting cat.jpg returns 200, image/jpeg, and correct image
   \ expected an exit code of 0, not standard error of "======= Backtrace: =========\n======= M..."
:( Requesting cat.html returns 200, text/html, and correct file
:( Requesting cat2.HTML returns 200, text/html, and correct file
:( Requesting cat3.HtMl returns 200, text/html, and correct file
:( Requesting cat.gif returns 200, image/gif, and correct file
:( Requesting favicon.ico returns 200, image/x-icon, and correct file
:( Requesting test.css returns 200, text/css, and correct file
:( Requesting test.js returns 200, text/javascript, and correct file
:) Requesting hello.php returns 200, text/html, and correct output
:) Requesting hello.php? returns 200, text/html, and correct output
:) Requesting hello.php?name=Alice returns 200, text/html, and correct output
:) Requesting /test redirects to /test/
:( Requesting /test/ outputs /test/index.html
:) Requesting directory containing index.php outputs index.php
:( Requesting two files in a row (cat.html then cat.jpg) succeeds
   \ expected an exit code of 0, not standard error of "======= Backtrace: =========\n======= M..."

I'm about to give up because I can't find what's wrong, help please :)

1
  • Please don't post the output of check50 but rather the output of the run on your local machine, so that we can see the whole backtrace. – ChrisG Aug 12 '16 at 12:58
1

This feedback \ expected an exit code of 0, not standard error of "======= Backtrace: =========\n==== indicates a seg fault. Try requesting cat.jpg in your browser and see if server bails with a seg fault. This line while((read = fread(buffer + size * (i - 1), BYTES, BYTES, file)>=1)){ is troubling (at least to me). You're asking it to read 512 blocks of 512 bytes each into poor little old buffer which is allocated for 512 bytes on the first read. Notice you only get the backtrace when cat.jpg is involved. It's the biggest file that's being requested (at 26860 bytes), so it's really going to "test the limits" of buffer. Not sayin' that's the only problem, but it is a problem.

Since you "think there's a memory leak somewhere" and valigrind's main purpose in life is to detect memory leaks, you need to use the tools. The main thing to remember is valgrind will only report on your functions if your functions are invoked, so you must send a request (browser? curl?) to your server to get info from valgrind. Generally:

  1. call valgrind: valgrind -v --leak-check=full --show-leak-kinds=all --track-origins=yes ./server ./public
  2. Start small. In another terminal, issue a curl request, like curl -i http://localhost:8080/hello.html
  3. ^C valgrind. It will give report for your viewing pleasure.

Ultimately, you will want to send a browser request for cat.jpg "through valgrind" at step 2.

You must log in to answer this question.

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