Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to fread 0 bytes into a NULL-pointer?

In my environment, the following code runs fine, but is it guaranteed to be okay?

FILE *file = fopen("in", "r");
int *read_to = NULL;
size_t count = 0;
size_t read = fread(read_to, sizeof(*read_to), count, file);
fclose(file);

respectively

FILE *file = fopen("out", "w");
int *write = NULL;
size_t count = 0;
size_t written = fwrite(write, sizeof(*write), count, file);
fclose(file);
like image 617
urzeit Avatar asked Sep 18 '25 16:09

urzeit


1 Answers

This is not guaranteed to work, and a strict reading of the Standard leads to the conclusion that passing a null pointer as the first argument to fread() or fwrite() causes undefined behavior.

According to §7.21.8.1 ¶2 of the C11 Draft Standard:

size_t fread(void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream);

The fread function reads, into the array pointed to by ptr....

Similarly, in §7.21.8.2 ¶2:

size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream);

The fwrite function writes, from the array pointed to by ptr....

But, in the section describing the use of library functions (§7.1.4) it is stated that:

If an argument to a function has an invalid value (such as a value outside the domain of the function, or a pointer outside the address space of the program, or a null pointer, or a pointer to non-modifiable storage when the corresponding parameter is not const-qualified) or a type (after promotion) not expected by a function with variable number of arguments, the behavior is undefined. If a function argument is described as being an array, the pointer actually passed to the function shall have a value such that all address computations and accesses to objects (that would be valid if the pointer did point to the first element of such an array) are in fact valid.

Finally, in §4 ¶2:

If a ''shall'' or ''shall not'' requirement that appears outside of a constraint or runtime- constraint is violated, the behavior is undefined.

Since a null pointer does not point to a valid object, address computations and accesses are not valid on null pointers, thus passing a null pointer to fread() or fwrite() violates the "shall" of §7.1.4, so the behavior is undefined.

like image 151
ad absurdum Avatar answered Sep 20 '25 06:09

ad absurdum