1

I'm new to C. Sorry if this has already been answered, I could'n find a straight answer, so here we go..

I'm trying to understand how malloc() works in C. I have this code:

#define MAXLINE 100

void readInput(char **s)
{
    char temp[MAXLINE];

    printf("Please enter a string: ");
    scanf("%s", temp);

    *s = (char *)malloc((strlen(temp)+1)*sizeof(char)); // works as expected
    //*s = (char *)malloc(2*sizeof(char)); // also works even when entering 10 chars, why?

    strcpy ((char *)*s, temp);
}

int main()
{
    char *str;

    readInput(&str);
    printf("Your string is %s\n", str);
    free(str);

    return 0;
}

The question is why doesn't the program crash (or at least strip the remaining characters) when I call malloc() like this:

*s = (char *)malloc(2*sizeof(char)); // also works even when entering 10 chars, why?

Won't this cause a buffer overflow if I enter a string with more than two characters? As I understood malloc(), it allocates a fixed space for data, so surely allocating the space for only two chars would allow the string to be maximum of one usable character ('0\' being the second), but it still is printing out all the 10 chars entered.

P.S. I'm using Xcode if that makes any difference.

Thanks, Simon

simon
  • 550
  • 1
  • 5
  • 14
  • 1
    Bacause you reached the "undefined behaviour" land. Anything might happen.... – Till Nov 11 '13 at 20:24
  • 1
    Also, don't cast the return of malloc: http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc, and `sizeof(char)` is superfluous, `malloc` accounts the size of the allocated array in terms of `char`, so by definition `sizeof(char)` is one. – Jens Gustedt Nov 11 '13 at 20:28
  • Thanks Jens Gustedt! I was wondering about the typecast as well. – simon Nov 11 '13 at 21:03

7 Answers7

2

It works out fine because you're lucky! Usually, a block a little larger than just 2 bytes is given to your program by your operating system.

If the OS actually gave you 16 bytes when you asked for 2 bytes, you could write 16 bytes without the OS taking notice of it. However if you had another malloc() in your program which used the other 14 bytes, you would write over that variables content.

The OS doesn't care about you messing about inside your own program. Your program will only crash if you write outside what the OS has given you.

Try to write 200 bytes and see if it crashes.

Edit:

malloc() and free() uses some of the heap space to maintain information about allocated memory. This information is usually stored in between the memory blocks. If you overflow a buffer, this information may get overwritten.

Atle
  • 1,867
  • 12
  • 10
  • Right...I guess that answers my question, thanks! So the line `*s = (char *)malloc((strlen(temp)+1)*sizeof(char));` is allocating the correct amount of space for the data? (every time when program is working, even though it shouldn't, there's a hidden mistake somewhere deep inside =) ) – simon Nov 11 '13 at 21:06
  • Yes, and after that you can safely copy the content temp to s. You don't check the length of the users input howeve, so if more than MAXLEN chars are given, temp will overflow. – Atle Nov 11 '13 at 21:09
  • Cool, thanks! C sure is an...interesting language =) – simon Nov 11 '13 at 21:15
2

Yes writing more data into an allocated buffer is a buffer overflow. However there is no buffer overflow check in C and if there happens to be valid memory after your buffer than your code will appear to work correctly.

However what you have done is write into memory that you don't own and likely have corrupted the heap. Your next call to free or malloc will likely crash, or if not the next call, some later call could crash, or you could get lucky and malloc handed you a larger buffer than you requested, in which case you'll never see an issue.

shf301
  • 31,086
  • 2
  • 52
  • 86
2

Won't this cause a buffer overflow if I enter a string with more than two characters?

Absolutely. However, C does no bounds checking at runtime; it assumes you knew what you were doing when you allocated the memory, and that you know how much is available. If you go over the end of the buffer, you will clobber whatever was there before.

Whether that causes your code to crash or not depends on what was there before and what you clobbered it with. Not all overflows will kill your program, and overflow in the heap may not cause any (obvious) problems at all.

John Bode
  • 119,563
  • 19
  • 122
  • 198
1

This is because even if you did not allocate the memory, the memory exists. You are accessing data that is not yours, and probably that with a good debugger, or static analyzer you would have seen the error.

Also if you have a variable that is just behind the block you allocated it will probably be overriden by what you enter.

dzada
  • 5,344
  • 5
  • 29
  • 37
1

Simply this is one of the case of undefined behavior. You are unlucky that you are getting the expected result.

haccks
  • 104,019
  • 25
  • 176
  • 264
1

It does cause a buffer overflow. But C doesn’t do anything to prevent a buffer overflow. Neither do most implementations of malloc.

In general, a crash from a buffer overflow only occurs when...

  • It overflows a page—the unit of memory that malloc actually gets from the operating system. Malloc will fulfill many individual allocation requests from the same page of memory.
  • The overflow corrupts the memory that follows the buffer. This doesn’t cause an immediate crash. It causes a crash later when other code runs that depends upon the contents of that memory.

(...but these things depend upon the specifics of the system involved.)

It is entirely possible, if you are lucky, that a buffer overflow will never cause a crash. Although it may create other, less noticeable problems.

Robert Fisher
  • 578
  • 4
  • 20
1

malloc() is the function call which is specified in Stdlib.h header file. If you are using arrays, you have to fix your memory length before utilize it. But in malloc() function, you can allocate the memory when you need and in required size. When you allocate the memory through malloc() it will search the memory modules and find the free block. even the memory blocks are in different places, it will assign a address and connect all the blocks. when your process finish, you can free it. Free means, assigning a memory is in RAM only. once you process the function and make some data, you will shift the data to hard disk or any other permenant storage. afterwards, you can free the block so you can use for another data. If you are going through pointer function, with out malloc() you can not make data blocks. New() is the keyword for c++.

When you don't know when you are programming how big is the space of memory you will need, you can use the function malloc

void *malloc(size_t size); The malloc() function shall allocate unused space for an object whose size in bytes is specified by size and whose value is unspecified.

how does it work is the question...

so your system have the free chain list, that lists all the memory spaces available, the malloc search this list until it finds a space big enough as you required. Then it breaks this space in 2, sends you the space you required and put the other one back in the list. It breaks in pieces of size 2^n that way you wont have weird space sizes in your list, what makes it easy just like Lego.

when you call 'free' your block goes back to the free chain list.

Kunwar Siddharth Singh
  • 1,676
  • 6
  • 33
  • 66