Section 7.19.7.11 of C99 defines ungetc()
as follows: [[ISO/IEC 9899:1999]]
The
ungetc
function pushes the character specified byc
(converted to anunsigned char
) back onto the input stream pointed to bystream
. Pushed-back characters will be returned by subsequent reads on that stream in the reverse order of their pushing. A successful intervening call (with the stream pointed to bystream
) to a file positioning function (fseek
,fsetpos
, orrewind
) discards any pushed-back characters for the stream. The external storage corresponding to the stream is unchanged.One character of pushback is guaranteed.
Consequently, subsequent calls to ungetc()
must be separated by a call to a read function or a file-positioning function (which will discard any data pushed by ungetc()
).
Non-Compliant Code Example
In this non-compliant code example, more than one character is pushed back on the stream referenced by fp
.
FILE *fp; char *file_name; /* initialize file_name */ fp = fopen(file_name, "rb"); if (fp == NULL) { /* handle Error */ } /* read data */ ungetc('\n', fp); ungetc('\r', fp); /* continue on */
Compliant Solution
If more than one character needs to be pushed by ungetc()
, then fgetpos()
and fsetpos()
should be used before and after reading the data instead of pushing it back with ungetc()
. Note that this solution can only be used if the input is seekable.
FILE *fp; fpos_t pos; char *file_name; /* initialize file_name */ fp = fopen(file_name, "rb"); if (fp == NULL) { /* handle Error */ } /* read data */ if (fgetpos(fp, &pos)) { /* handle Error */ } /* read the data that will be "pushed back" */ if (fsetpos(fp, &pos)) { /* handle Error */ } /* Continue on */
Remember to always call fgetpos()
before fsetpos()
(see FIO44-C. Only use values for fsetpos() that are returned from fgetpos()).
Automated Detection
The tool Compass/ROSE can easily identify two instances of the ungetc()
function inside a function. Determining if one instance of ungetc()
being invoked twice is better handled by dynamic analysis.
Risk Assessment
If used improperly, ungetc()
can cause data to be truncated or lost.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
FIO13-A |
medium |
probable |
high |
P4 |
L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Reference
[[ISO/IEC 9899:1999]] Section 7.19.7.11, "The ungetc
function"
FIO12-A. Prefer setvbuf() to setbuf() 09. Input Output (FIO) FIO14-A. Understand the difference between text mode and binary mode with file streams