The C standard Standard, subclause 7.21.8.2 [ISO/IEC 9899:2011], defines the fwrite() function as follows:
Synopsis
size_t fwrite(const void *restrict ptr, size_t size, size_tnitemsnmemb, FILE *restrict stream);Description
The
fwrite()function shall writewrites, from the array pointed to byptr, up tonitemsnmembelements whose size is specified bysize, to the stream pointed to bystream. For each object,sizecalls shall be calls are made to thefputc()function, taking the values (in order) from an array ofunsigned charexactly overlaying the object. The file - position indicator for the stream (if defined) shall be is advanced by the number of bytes successfully written. If an error occurs, the resulting value of the file - position indicator for the stream is unspecifiedindeterminate.
The definition does not state that the fwrite() function will stop copying characters into the file if a null character is encountered. Therefore, when writing a C null-terminated byte string in to a file using the fwrite() function, always use the size length of the buffer string plus 1 (to account for the null character) as the nitems the nmemb parameter.
Noncompliant Code Example
In the following piece of codethis noncompliant code example, the size of the buffer is stored in size1, but size2 number of characters are written in to the file. If size2 is greater than size1, write() will not stop copying characters at the null character.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> int main(){ char *buffer = NULL; long size1,size_t size1; size_t size2; FILE *filedes; /* ... * Assume size1 and size2 are appropriately initialized * ... */ filedes = fopen("out.txt", "w+"); if (filedes <== 0NULL) { /* Handle return 0; error */ } buffer = (char *)calloc( 1, size1); if (!buffer) == NULL) { /* Handle return 0;error */ } fwrite(buffer, sizeof(char)1, size2, filedes); free(buffer); buffer = NULL; fclose(filedes); return 0; } |
Compliant
...
Solution
This compliant solution ensures The following code will ensure that the right correct number of characters are written in to the file.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> int main(){ #include <string.h> char *buffer = NULL; long size1,size_t size1; size_t size2; FILE *filedes; /* ... * Assume size1 and size2 areis appropriately initialized * ... */ filedes = fopen("out.txt", "w+"); if (filedes <== 0NULL){ /* Handle return 0; error */ } buffer = (char *)calloc( 1, size1); if (!buffer) == NULL) { /* Handle return 0;error */ } /* ... * Accept characters in to the buffer. * Check for buffer overflow * ... */ size2 = strlen(buffer) + 1; fwrite(buffer, sizeof(char)1, size2, filedes); free(buffer); buffer = NULL; fclose(filedes); return 0; } |
References
Risk Assessment
Failure to follow the recommendation could result in a non-null-terminated string being written to a file, which will create problems when the program tries to read it back as a null-terminated byte string.
Recommendation | Severity | Likelihood | Detectable | Repairable | Priority | Level |
|---|---|---|---|---|---|---|
FIO18-C | Medium | Probable | No | No | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| LDRA tool suite |
| 44 S | Enhanced enforcement |
Related Guidelines
| SEI CERT C++ Coding Standard | VOID FIO18-CPP. Never expect write() to terminate the writing process at a null character |
Bibliography
| [ISO/IEC 9899:2011] | Subclause 7.21.8.2, "The fwrite Function" |
| [IEEE Std 1003.1:2013] | XSH, System Interfaces, fwrite |
...
\[1\] [http://www.opengroup.org/onlinepubs/009695399/functions/fwrite.html]Wiki Markup