Subclause 7.21.5.3 of the C Standard [ISO/IEC 9899:2011] places the following restrictions on update streams:
...
(See also undefined behavior 151 in Annex J of C11the C Standard.) Consequently, a call to fseek()
, fflush()
, or fsetpos()
is necessary between input and output to the same stream. (See FIO07-C. Prefer fseek() to rewind().)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h>
enum { BUFFERSIZE = 32 };
extern void initialize_data(char *data, size_t size);
void func(const char *file_name) {
char data[BUFFERSIZE];
char append_data[BUFFERSIZE];
FILE *file;
file = fopen(file_name, "a+");
if (file == NULL) {
/* Handle error */
}
initialize_data(append_data, BUFFERSIZE);
if (fwrite(append_data, BUFFERSIZE, 1, file) != BUFFERSIZE) {
/* Handle error */
}
if (fread(data, BUFFERSIZE, 1, file) != 0) {
/* Handle there not being data. */
}
fclose(file);
} |
However, because the stream is not flushed between the call to fread()
and fwrite()
, the behavior is undefined.
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h>
enum { BUFFERSIZE = 32 };
extern void initialize_data(char *data, size_t size);
void func(const char *file_name) {
char data[BUFFERSIZE];
char append_data[BUFFERSIZE];
FILE *file;
file = fopen(file_name, "a+");
if (file == NULL) {
/* Handle error */
}
initialize_data(append_data, BUFFERSIZE);
if (fwrite(append_data, BUFFERSIZE, 1, file) != BUFFERSIZE) {
/* Handle error */
}
if (fseek(file, 0L, SEEK_SET) != 0) {
/* Handle error */
}
if (fread(data, BUFFERSIZE, 1, file) != 0) {
/* Handle there not being data. */
}
fclose(file);
} |
Risk Assessment
...
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
FIO39-C | lowLow | likelyLikely | mediumMedium | P6 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Can detect simple violations of this rule | |||||||||
5.0 | Can detect violations of this rule with CERT C Rule Pack | ||||||||
| 84 D | Fully implemented |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
...
CERT C++ Secure Coding Standard | FIO39-CPP. Do not alternately input and output from a stream without an intervening flush or positioning call |
CERT C Secure Coding Standard | FIO07-C. Prefer fseek() to rewind() |
ISO/IEC TS 17961 (Draft) | Interleaving stream inputs and outputs without a flush or positioning call [ioileave] |
Bibliography
[ISO/IEC 9899:2011] | Subclause 7.21.5.3, "The fopen Function" |
...