Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C buffer memory allocation

Tags:

c

malloc

I'm quite new to C so please bear with my incompetence. I want to read an whole EXEcutable file into a buffer:

#include <stdlib.h>
FILE *file = fopen(argv[1], "rb");
long lSize;

fseek(file, 0, SEEK_END);
lSize = ftell(file);
fseek(file, 0, SEEK_SET);

char *buffer = (char*) malloc(sizeof(char)*lSize);
fread(buffer, 1, lSize, file);

The file has 6144 bytes (stored correctly in lSize) but the size of my buffer is only 4 bytes, therefore only the MZ signature is stored in the buffer.

Why does malloc only allocate 4 bytes in this case?

Edit: Probably the char buffer is terminated by the first 0 in the MZ header of the PE file. If I set the buffer to a certain value however, the whole file will be stored. If I set the buffer to int (= 4 bytes), the buffer won't be terminated but will be of course larger (vs. char = 1 byte). I just want to copy the file byte for byte with the null bytes as well.

Edit 2: The buffer of course contains everything it should but if I try to write it to a new file with fwrite, it only wrote up to the first \0 (which is 4 bytes). I just got fwrite wrong. Fixed this. Sorry, the problem wasn't well defined enough.

like image 528
Laughingman Avatar asked Dec 17 '22 08:12

Laughingman


2 Answers

If lSize really does equal 6144 then your code will indeed allocate 6144 bytes and then read the entire contents of the file. If you believe that only 4 bytes are being read it is probably because the 5th byte is a zero. Thus when buffer is interpreted as a zero terminated string, it terminates at that point.

You can inspect the rest of your buffer by looking at buffer[4], buffer[5], etc.

As an aside, you don't need to cast the return from malloc, and sizeof(char) == 1 by definition. Best practice is to write the malloc like this:

char *buffer = malloc(lSize);

But that will not change your results.

like image 194
David Heffernan Avatar answered Dec 23 '22 16:12

David Heffernan


Why does malloc only allocate 4 bytes in this case?

Because you failed to #include <stdlib.h> (and cast the return value of malloc()).


Do not forget to #include <stdlib.h> so that the compiler knows malloc returns a value of type void* (rather than assuming it returns an int) and takes an argument of size_t type (rather than asuuming it is an int)

Also do not cast the return value of malloc. A value of type void* can be assigned to an object of pointer (to any type) type. Casting the return value makes the compiler silently convert int (assumed when <stdlib.h> was not included) to the type in the cast. Note the compiler would complain without the cast letting you know you had forgotten the include.


The real error is not malloc allocating the wrong amount (I believe it will allocate the correct amount anyway). The real error is assuming malloc returns an int when it returns a void*. int and void* can be passed differently (one in a register, the other on the stack for instance) or they have different representations (two's complement for int and segmented address for void*) or any other thing (most probably sizeof (int) != sizeof (void*)).

like image 36
pmg Avatar answered Dec 23 '22 17:12

pmg