Immo
Immo

Reputation: 29

C. Using more memory than allocated in malloc - can I return sth, end program instead of letting it crash?

My program crashes when malloc(x*sizeof(char)), x < limit of fgets, despite buffer == NULL check.

In my example, when x is 1, and limit of what fgets can take is 100, and user types eg. 5 characters from keyboard (fgets() call), program crashes, returning some random like: 19284791298 value.

My problem: instead of crashing, I would prefer if it returned NULL.

Reason: I upload my code to my univ's linux platform that tests program's reaction to heap limit change to 0 and to 130, when my program is written to return NULL if user's input exceeds 100 characters. I don't quite understand how the environment changes memory limit to 0 and 130 and what exactly is changed, but even though, I noticed my program in CodeBlocks, windows 10, crashes in this situation described here (x < stdin input) despite checking buffer == NULL.

I wish buffer == NULL check could somehow work and prevent the crash.

If x was 100, and size was 1 (instead of 1 and 100), my program would return NULL and set err_code to 1.

I'm thinking: I can't do with x the same "if" statement I did for strlen(buffer), because... to check how long input written to buffer is, firstly I'd need to check length of what was written to this buffer?!.

printf("Insert data: ");
char *buffer = (char* )malloc(1*sizeof(char));
if (buffer == NULL) 
    return NULL;

int size=100;
if (fgets(buffer, size, stdin)!=NULL) {
    if (strlen(buffer)>(unsigned)(size-2)) { //'\0' and enter are 2 chars
        free(buffer);
        *err_code=1;
        return NULL;
    }
//... here goes some sscanf to fill struct fields, etc.
}

In other words. A bit condensed what I think may lead to understanding of my problem:

  1. Is there a way to end program returning something, instead of letting it crash in such situation? A way to make if(buffer == NULL) work? Why doesn't this check work?

  2. I'm unfamiliar with linux. When I see a comment in report I get, that linux sets (heap?) limit to 0 or 130 (when testing my program), does it mean I can replicate the problems it encounters by setting my x to 0, 130? (in the part malloc(x*sizeof(char)).

Upvotes: 0

Views: 167

Answers (2)

Steve Summit
Steve Summit

Reputation: 47915

When you call fgets, you must tell it how big the destination buffer is. You are not just telling it the maximum number of characters you want it to read, so that it can automatically allocate that much space, or anything like that. You are telling it what the size of the buffer already is, and you are telling fgets that it absolutely must not read any more characters than that, otherwise the buffer will overflow. (fgets never does any allocating of its own.)

So when you say

char *buffer = (char* )malloc(1*sizeof(char));

followed by

int size=100;
fgets(buffer, size, stdin)

you have lied. You have allocated a buffer of size 1, and you have told fgets that the buffer is of size 100. So fgets will read up to 99 characters, and store them into buf, and in most cases this will badly overflow the buffer.

What you want to do is something more like this:

int size = 100;
char *buffer = (char* )malloc(size*sizeof(char));
if (buffer == NULL) 
    return NULL;

if (fgets(buffer, size, stdin)!=NULL) {
    ...

Also, although it doesn't have anything to do with your problem, there is no need to multiply by sizeof(char) when calling malloc (because sizeof(char) is 1 by definition), and in C, there is no need to cast the return from malloc into the destination pointer type, either. I would just call

char *buffer = malloc(size);

Upvotes: 4

Ravi S
Ravi S

Reputation: 139

In your code, you have allocated buffer as a single byte array

char *buffer = (char* )malloc(1*sizeof(char));


int size=100;
if (fgets(buffer, size, stdin)!=NULL) {

In the fgets, you would want to read into buffer an input of 100 bytes. When the input is read into the buffer it goes beyond the allocated area and overwrites other data. Because of this, your program crashes,

Upvotes: 1

Related Questions