...
Subclause 6.8.6.4, paragraph 3, of the C Standard [ISO/AA. Bibliography#ISO-IEC 9899:-2011] states:
If a return statement with an expression is executed, the value of the expression is returned to the caller as the value of the function call expression. If the expression has a type different from the return type of the function in which it appears, the value is converted as if by assignment to an object having the return type of the function.
...
Conversion as if by assignment to the type of the function is required if the return expression has a different type than the function but not if the return expression has a wider value only because of wide evaluation. This allows seemingly inconsistent and confusing behavior. Consider the following code as an example:
Code Block |
---|
float f(float x) {
return x * 0.1f;
}
float g(float x) {
return x * 0.1;
}
|
Function f()
is allowed to return a value wider than float
, but function g()
(which uses the wider constant) is not.
...
The C Standard, subclause F.6 [ISO/AA. Bibliography#ISO-IEC 9899:-2011], states:
If the return expression is evaluated in a floating-point format different from the return type, the expression is converted as if by assignment362 to the return type of the function and the resulting value is returned to the caller.
362) Assignment removes any extra range and precision.
...
Code Block | ||||
---|---|---|---|---|
| ||||
float calc_percentage(float value) {
return value * 0.1f;
}
void float_routine(void) {
float value = 99.0f;
long double percentage;
percentage = calc_percentage(value);
}
| ||||
Compliant Solution (within the Function)
This compliant solution casts the value of the expression in the return statement. It forces the return value to have the expected range and precision, as described in subclause 5.2.4.2.2, paragraph 9, of the C Standard [ISO/AA. Bibliography#ISO-IEC 9899:-2011].
Code Block | ||||
---|---|---|---|---|
| ||||
float calc_percentage(float value) {
return (float)(value * 0.1f);
}
void float_routine(void) {
float value = 99.0f;
long double percentage;
percentage = calc_percentage(value);
}
| ||||
Forcing the range and precision inside the calcPercentage()
function is a good way to fix the problem once without having to apply fixes in multiple locations (every time calcPercentage()
is called).
...
Code Block | ||||||
---|---|---|---|---|---|---|
| void float_routine(void) {
float value = 99.0f;
long double percentage;
percentage = (float) calc_percentage(value);
}
||||||
Risk Assessment
Failure to follow this guideline can lead to inconsistent results across different platforms.
...
Related Vulnerabilities
Search for vulnerabilities BB. Definitions#vulnerability resulting from the violation of this rule on the CERT website.
Bibliography
[ISO/AA. Bibliography#ISO-IEC 9899:-2011] | Subclause 6.8.6.4, "The return Statement"Annex F.6, "The return Statement" |
[WG14AA. Bibliography#WG14/N1396] |
...