Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C: Valgrind: Use of uninitialized value of size 4 AND Use of uninitialised value of size 4

Tags:

c

valgrind

These 2 errors are coming up with a linked list/low level file read/strtok program.

==10982== Use of uninitialised value of size 4
==10982==    at 0x40C3899: strtok (strtok.S:197)
==10982==    by 0x8048719: main (main.c:9)
==10982==  Uninitialised value was created by a stack allocation
==10982==    at 0x80487D2: buildList (functions.c:13)
==10982== 
==10982== Use of uninitialised value of size 4
==10982==    at 0x40C38C1: strtok (strtok.S:223)
==10982==    by 0x8048719: main (main.c:9)
==10982==  Uninitialised value was created by a stack allocation
==10982==    at 0x80487D2: buildList (functions.c:13)
==10982== 
==10982== Conditional jump or move depends on uninitialised value(s)
==10982==    at 0x40C38C4: strtok (strtok.S:224)
==10982==    by 0x8048719: main (main.c:9)
==10982==  Uninitialised value was created by a stack allocation
==10982==    at 0x80487D2: buildList (functions.c:13)

Here is the function buildList

void buildList(int fdin, int lines)
{
    char ara[4096];
    int num;
    double p;
    read(fdin, ara, 4096);
    char *nl = "\n";
    char *ws = " ";
    char *temp =  strtok(ara, " ");
    while(temp != NULL)
    {
        Stock *s = (Stock*)calloc(1, sizeof(Stock));
        s->c.symbol = (char*)calloc(strlen(temp)+1, sizeof(char));
        strcpy(s->c.symbol, temp);
        temp = strtok(NULL, "\n");
        s->c.name = (char*)calloc(strlen(temp)+1, sizeof(char));
        strcpy(s->c.name, temp);
        temp = strtok(NULL, "\n");
        sscanf(temp, "%lf", &p);
        temp = strtok(NULL, "\n");
        s->price = p;
        sscanf(temp, "%d", &num);
        s->shares = num;
        Node *n = (Node*)calloc(1, sizeof(Node));
        n->data = s;
        addOrdered(n);
        temp = strtok(NULL, " ");
    }
    close(fdin);
}

I cannot figure out why this error occurs. From what I've read it is because I am assigning things to a char* from strtok without assigning any memory to them. However this is how I have done it in the past and I think it has been fine.

like image 928
Austin Johnston Avatar asked May 24 '13 23:05

Austin Johnston


1 Answers

As others have surmised, valgrind is complaining that strtok is making use of uninitialized memory. The question then turns to why, since it seems like it is being initialized by:

read(fdin, ara, 4096);

However, read() does not \0 terminate the data, while strtok expects a \0 terminated string. Make sure the input is terminated properly:

ssize_t result = read(fdin, ara, sizeof(ara)-1); /* leave room for '\0' */
ara[result > 0 ? result : 0] = '\0';

The memset(ara, 0, sizeof(ara)); suggestion by Lee Daniel Crocker amounts to the same kind of fix, but it only works if the file contains less than sizeof(ara) bytes of input. You are still exposed to a similar problem if the file you read from has 4096 bytes of data or more. Then, strtok will be forced to scan past the end of the buffer to look for the \0, leading to undefined behavior.

like image 134
jxh Avatar answered Sep 22 '22 12:09

jxh