...
The ungetc()
function does not set the error indicator even when it fails, so it is not possible to check for errors reliably unless it is known that the argument is not equal to EOF
.
The C Standard 7.31.3.10 paragraph 3 [ISO/IEC 9899:20112024] states that "one
)ne wide character of pushback is guaranteed...
," so this should not be an issue if, at most, one character is ever pushed back before reading again. (See FIO13-C. Never push back anything other than one read character.)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h>
#include <string.h>
enum { SIG_DESC_SIZE = 32 };
typedef struct {
char sig_desc[SIG_DESC_SIZE];
} signal_info;
void func(size_t num_of_records, size_t temp_num,
const char *tmp2, size_t tmp2_size_bytes) {
signal_info *start = (signal_info *)calloc(num_of_records,
sizeof(signal_info));
if (tmp2 == NULL) {
/* Handle error */
} else if (temp_num > num_of_records || temp_num == 0) {
/* Handle error */
} else if (tmp2_size_bytes < SIG_DESC_SIZE) {
/* Handle error */
}
signal_info *point = start + temp_num - 1;
memcpy(point->sig_desc, tmp2, SIG_DESC_SIZE);
point->sig_desc[SIG_DESC_SIZE - 1] = '\0';
/* ... */
free(start);
} |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h>
#include <string.h>
enum { SIG_DESC_SIZE = 32 };
typedef struct {
char sig_desc[SIG_DESC_SIZE];
} signal_info;
void func(size_t num_of_records, size_t temp_num,
const char *tmp2, size_t tmp2_size_bytes) {
signal_info *start = (signal_info *)calloc(num_of_records,
sizeof(signal_info));
if (start == NULL) {
/* Handle allocation error */
} else if (tmp2 == NULL) {
/* Handle error */
} else if (temp_num > num_of_records || temp_num == 0) {
/* Handle error */
} else if (tmp2_size_bytes < SIG_DESC_SIZE) {
/* Handle error */
}
signal_info *point = start + temp_num - 1;
memcpy(point->sig_desc, tmp2, SIG_DESC_SIZE);
point->sig_desc[SIG_DESC_SIZE - 1] = '\0';
/* ... */
free(start);
} |
...
- that function cannot fail.
- its return value is inconsequential; that is, it does not indicate an error.
- it is one of a handful of functions whose return values are not traditionally checked.
These functions are listed in the following table:
Functions for which Return Values Need Not Be Checked
Function | Successful Return | Error Return |
---|---|---|
| Character written |
|
| Wide character written |
|
| Nonnegative |
|
| Nonnegative |
|
| Number of characters (nonnegative) | Negative |
| Number of wide characters (nonnegative) | Negative |
kill_dependency() | The input parameter | NA |
memcpy() , wmemcpy() | The destination input parameter | NA |
memmove() , wmemmove() | The destination input parameter | NA |
strcpy() , wcscpy() | The destination input parameter | NA |
strncpy() , wcsncpy() | The destination input parameter | NA |
strcat() , wcscat() | The destination input parameter | NA |
strncat() , wcsncat() | The destination input parameter | NA |
memset() , wmemset() | The destination input parameter | NA |
The return value of a call to fprintf()
or one of its variants (vfprintf()
, wfprintf()
, vwfprintf()
) or one of the file output functions fputc()
, fputwc()
, fputs()
, fputws()
may be ignored if the output is being directed to stdout
or stderr
. Otherwise, the return value must be checked.
If a function's return value is to be ignored, it is recommended that the function's return value should be explicitly cast to void to signify the programmer's intent: function's results should be explicitly cast to void
to signify programmer intent:
Code Block | ||||
---|---|---|---|---|
| ||||
int main() { (void) printffprintf(stdout, "Hello, world\n"); // printffprintf() return value safely ignored } |
...
Tool | Version | Checker | Description | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Astrée |
| error-information-unused error-information-unused-computed | Partially checked | |||||||||||||||||||||||||||||||||
Axivion Bauhaus Suite |
| CertC-ERR33 | ||||||||||||||||||||||||||||||||||
CodeSonar |
| LANG.FUNCS.IRV | Ignored return value Missing Test of Error Code Non-zero Error Code | |||||||||||||||||||||||||||||||||
Compass/ROSE | Can detect violations of this recommendation when checking for violations of EXP12-C. Do not ignore values returned by functions and EXP34-C. Do not dereference null pointers | |||||||||||||||||||||||||||||||||||
Coverity |
| MISRA C 2012 Rule 22.8 MISRA C 2012 Rule 22.9 MISRA C 2012 Rule 22.10 | ImplementedLDRA tool suite | |||||||||||||||||||||||||||||||||
Helix QAC |
| 80 D | Partially implemented | Parasoft C/C++test | ||||||||||||||||||||||||||||||||
Include Page | Parasoft_V | Parasoft_V | CERT_C-ERR33-a | The value returned by a function having non-void return type shall be used | Parasoft Insure++ | Runtime analysis | ||||||||||||||||||||||||||||||
Include Page | Polyspace Bug Finder_V | Polyspace Bug Finder_V | Return value of a sensitive function not checked | errno is not checked for error conditions following function call Sensitive functions called without checking for unexpected return values and errors Pointer returned from dynamic allocation not checked for The value returned by a function having non-void return type shall be used The value of | PRQA QA-C | |||||||||||||||||||||||||||||||
Include Page | PRQA QA-C_v | PRQA QA-C_v | 3200 | Partially implemented | PRQA QA-C++ | |||||||||||||||||||||||||||||||
Include Page | cplusplus:PRQA QA-C++_V | cplusplus:PRQA QA-C++_V | C3200 C++3802, C++3803, C++3804 DF2820, DF2821, DF2822, DF2823, DF2824, DF2930, DF2931, DF2932, DF2933, DF2934 | |||||||||||||||||||||||||||||||||
Klocwork |
| NPD.CHECK.MUST | ||||||||||||||||||||||||||||||||||
LDRA tool suite |
| 80 D | Partially implemented | |||||||||||||||||||||||||||||||||
Parasoft C/C++test |
| CERT_C-ERR33-a | The value returned by a standard library function that may return an error should be used | |||||||||||||||||||||||||||||||||
Parasoft Insure++ | Runtime analysis | |||||||||||||||||||||||||||||||||||
PC-lint Plus |
| 534 | Partially supported | |||||||||||||||||||||||||||||||||
| Checks for:
Rule partially covered. | |||||||||||||||||||||||||||||||||||
RuleChecker |
| error-information-unused | Partially checked | |||||||||||||||||||||||||||||||||
TrustInSoft Analyzer |
| pointer arithmetic | Exhaustively verified. |
Related Vulnerabilities
The vulnerability in Adobe Flash [VU#159523] arises because Flash neglects to check the return value from calloc()
. Even when calloc()
returns a null pointer, Flash writes to an offset from the return value. Dereferencing a null pointer usually results in a program crash, but dereferencing an offset from a null pointer allows an exploit to succeed without crashing the program.
...
[DHS 2006] | Handle All Errors Safely |
[Henricson 1997] | Recommendation 12.1, "Check for All Errors Reported from Functions" |
[ISO/IEC 9899:20112024] | Subclause 7.2131.73.10, "The ungetc Function" |
[VU#159523] |
...