0

I have been stumbling over load for a couple of days now. Here's my code:

bool load(FILE* file, BYTE** content, size_t* length)
{
    printf("load started \n");
     // initialize content and its length
    *content = NULL;
    *length = 0;
    BYTE* buffer = malloc(512 * sizeof(BYTE));

    size_t temp = fread(buffer, sizeof(BYTE), 512, file);

    while (temp > 0)
    {
        *content = realloc(*content, (*length + temp + 1) * sizeof(BYTE));
        if (*content == NULL)
        {
            *length = 0;
            break;
        }
        *length += temp;
        memcpy(*content + *length, buffer, temp); //valgrind reports an error here
        *(*content+*length) = '\0';
        temp = fread(buffer, sizeof(BYTE), 512, file);
    }

    free(buffer);

    if (*content == NULL)
    {
        *length = 0;
        return false;
    }

    return true;
}

Using valgrind, I was able to narrow down the error to memcpy. However I am unable to find the error in my usage of memcpy. Below is the error given by valgrind.

==7692== Invalid write of size 8
==7692==    at 0x4C2F793: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7692==    by 0x403F69: load (server.c:651)
==7692==    by 0x40362E: transfer (server.c:1122)
==7692==    by 0x401C29: main (server.c:261)
==7692==  Address 0x5506c50 is 512 bytes inside a block of size 513 alloc'd
==7692==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7692==    by 0x4C2CF1F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7692==    by 0x403EF1: load (server.c:644)
==7692==    by 0x40362E: transfer (server.c:1122)
==7692==    by 0x401C29: main (server.c:261)
==7692== 
--7692-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--7692-- si_code=80;  Faulting address: 0x0;  sp: 0x802b99de0

valgrind: the 'impossible' happened:
   Killed by fatal signal
==7692==    at 0x3805CF06: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==7692==    by 0x38021B95: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==7692==    by 0x3809D99A: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==7692==    by 0x380AC87C: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)

sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable
==7692==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7692==    by 0x403EF1: load (server.c:644)
==7692==    by 0x40362E: transfer (server.c:1122)
==7692==    by 0x401C29: main (server.c:261)
1

Your use of memcpy is fine. The problem is the order of these statements:

 *length += temp;
    memcpy(*content + *length, buffer, temp); `

You are trying to copy buffer after the end of the memory allocated for *content. For example, after the first fread, you allocate 512 to *content, then try to memcpy to *content + 512.

Also, get rid of the + 1 in the realloc and delete this line *(*content+*length) = '\0';. This is not string data. You do not want to change any of the bytes in content.

2
  • Hi there, your advice worked for me! However regarding the *(*content+*length) = '\0';, without the null terminator, how does the computer know that the file has ended?
    – Wet Feet
    Mar 8 '16 at 1:06
  • 1
    Great! The computer knows the file has ended because it knows how long it is (length). Mar 8 '16 at 1:40

You must log in to answer this question.

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