Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added Automated Detection table and Axivion Bauhaus entry

To Cast the return value of a function that returns a floating point type to ensure predictable program execution casts to type float must be present on all floating-point function calls..

Subclause Wiki MarkupThe C99 standard \[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] states in Section 6.8.6.4, Paragraph paragraph 3, of the C Standard [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. 142)

This paragraph is footnoted as is annotated (footnote 160) as follows:

142) The return statement is not an assignment. The overlap restriction of subclause 6.5.16.1 does not apply to the case of function return. The representation of floating-point values may have wider range or precision . A than implied by the type; a cast may be used to remove this extra range and precision.

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.

Although the current text standard does not require narrowing return expressions of the same type as the function, it does not clearly state what is allowed. Is it allowed to narrow the result? Is it allowed to narrow the result sometimes but not always? Is it allowed to partially narrow the result (e.g.for example, if the application binary interface [ABI] returns floats in double format, but a float function has a float return expression evaluated to wider than double)? An aggressive implementation could argue “yes” yes€ to all these questions, though the resulting behavior would complicate debugging and error analysis.

Footnote 142 160 in the C Standard says a cast may be used to remove extra range and precision from the return expression. This means that a predictable program must have casts on all floatingfunction calls that return floating-point function calls values (except where the function directly feeds an operator-like assignment that implies the conversion). With type-generic math (tgmath.h), the programmer has to reason through the tgmath.h resolution rules to determine which casts to apply. These are significant obstacles to writing predictable code.

NOTE: WG14 has voted to include the following text in C1X. This only impacts implementations that implement the optional Annex F "IEC 60559 floating-point arithmetic".

The C Standard, subclause F.6 [ISO/IEC 9899:2011], states:

Require return expressions to be converted as if by assignment to the type of the function, but only in Annex F. This is a compromise that addresses the problems for Annex F implementations while not impacting non-Annex F implementations that exercise the license for wide returns.

Insert the following new subclause after F.5 (and increment subsequent subclause numbers):

F.6 The return statement

If the return expression is evaluated in a floating-point format different from the return type, then the expression is converted as if by assignment362 to the return type of the function and the resulting value is returned to the caller.

Noncompliant Code Example

362) Assignment removes any extra range and precision.

This applies only to implementations that conforms to the optional Annex F, "IEC 60559 Floating-Point Arithmetic."  The macro __STDC_IEC_559__ can be used to determine whether an implementation conforms to Annex F.

Noncompliant Code Example

This noncompliant code example fails to The following example code has been constructed to illustrate an example that does not conform to this recommendation.  The code is non-conforming because it does not cast the result of the expression in the return statement and thereby guarantee that the range or precision is no wider than expected.   The uncertainty in this example is introduced by the constant 0.1f.   This constant may be stored with a range or precision that is greater than that of float.   Consequently, the result of x * 0.1f may also have a range or precision greater than that of float.   As described abovepreviously, this range or precision may not be reduced to that of a float and, thus,  so the caller of calcPercentage() may receive a value that is more precise than expected.   This may lead to inconsistent program execution across different platforms.

Code Block
bgColor#FFcccc
langc

float calcPercentagecalc_percentage(float value) {
   return value * 0.1f;
}

void floatRoutinefloat_routine(void) {
  float value = 99.0f;
  long floatdouble percentage;

  percentage = calcPercentagecalc_percentage(value);
}

Compliant

...

Solution (within the Function)

This compliant solution casts the The following code example remedies the above noncompliant code by casting the value of the expression in the return statement.   This It forces the return value to have the expected range and precision, as described in Section subclause 5.2.4.2.2 8 , paragraph 9, of the C StandardStandard [ISO/IEC 9899:2011].

Code Block
bgColor#ccccff
langc

float calcPercentagecalc_percentage(float value) {
   return (float)(value * 0.1f);
}

void floatRoutinefloat_routine(void) {
  float value = 99.0f;
  long floatdouble percentage;

  percentage = calcPercentagecalc_percentage(value);
}

Compliant Code Example (Alternate)


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).  

Compliant Solution (Outside the Function)

Source code to the called function may not always be available. This compliant solution casts the return value of the calcPercentage() function to float to force the correct range and precision when the source of the called function cannot be modified.Unfortunately, not all compilers may honor casts.  In this case the range and precision must be forced by assignment to a variable of the correct type.  The following code example illustrates this approach.

Code Block
bgColor#ccccff
langc
void float_routine
float calcPercentage(float value) {
  volatile float result;

  result = value * 0.1f;

  return result;
}

void floatRoutine(void) {
  float value = 99.0f;
  long floatdouble percentage;

  percentage = calcPercentage(float) calc_percentage(value);
}

Risk Assessment

Failure to follow this guideline can lead to inconsistent results across different platforms.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FLP37

FLP07-C

low

Low

unlikely

Probable

medium

Medium

P2

P4

L3

Automated Detection

Tool

Version

Checker

Description

Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-FLP07

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Other Languages

References

...

Bibliography

...

[ISO/IEC 9899:2011]Subclause 6.8.6.4, "The return Statement"
Annex F.6, "The return Statement"
[WG14/N1396]


...

Image Added Image Added Image Added 9899:1999|AA. C References#ISO/IEC 9899-1999]\] \[[WG14/N1396|http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1396.htm]\]