Section Subclause 7.1921.7.11 of C99 defines {{ungetc()}} as follows: \[10 of the C Standard [ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\]2011] defines Wiki Markup ungetc()
as follows:
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 multiple calls to ungetc()
on the same stream must be separated by a call to a read function or a file-positioning function (which will discard any data pushed by ungetc()
).
...
Likewise, for ungetwc()
, C guarantees only one wide character of pushback (subclause 7.29.3.10). Consequently, multiple calls to ungetwc()
on the same stream must be separated by a call to a read function or a file-positioning function (which will discard any data pushed by ungetwc()
).
Noncompliant Code Example
In this non-compliant noncompliant code example, more than one character is pushed back on the stream referenced by fp
.:
Code Block | ||||
---|---|---|---|---|
| ||||
FILE *fp; char *file_name; /* initializeInitialize file_name */ fp = fopen(file_name, "rb"); if (fp == NULL) { /* handleHandle Errorerror */ } /* readRead data */ if (ungetc('\n', fp); ) == EOF) { /* Handle error */ } if (ungetc('\r', fp);) == EOF) { /* Handle error */ } /* continue onContinue */ |
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 applies only be used if the input is seekable.
Code Block | ||||
---|---|---|---|---|
| ||||
FILE *fp; fpos_t pos; char *file_name; /* initializeInitialize file_name */ fp = fopen(file_name, "rb"); if (fp == NULL) { /* handleHandle Errorerror */ } /* readRead data */ if (fgetpos(fp, &pos)) { /* handleHandle Errorerror */ } /* readRead the data that will be "pushed back" */ if (fsetpos(fp, &pos)) { /* handleHandle Errorerror */ } /* Continue on */ |
Remember to always call fgetpos()
before fsetpos()
. (see See FIO44-C. Only use values for fsetpos() that are returned from fgetpos().).
Risk Assessment
If used improperly, ungetc()
and ungetwc()
can cause data to be truncated or lost.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
FIO13- |
C |
Medium |
Probable |
High | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
CodeSonar |
| (customization) | Users can implement a custom check that triggers a warning when ungetc() is called twice on the same stream without an intervening call to a read function or a file-positioning function. | ||||||
Compass/ROSE | Can detect simple violations of this recommendation. In particular, it warns when two calls to | ||||||||
LDRA tool suite |
| 83 D | Partially implemented | ||||||
PC-lint Plus |
| 2470 | Fully supported |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Reference
...
Bibliography
...
...
2011] | Subclause 7.21.7. |
...
10, |
...
"The ungetc Function" |
...
{{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