MISRA.COMP.WRAPAROUNDWrap-around in a condition. MISRA C 2012 Rule 12.4: Evaluation of constant expressions should not lead to unsigned integerwrap-aroundCategory: Advisory Analysis: Decidable, Single Translation Unit Applies to: C90, C99 AmplificationThis rule applies to expressions that satisfy the constraints for a constant expression, whether or not they appear in a context that requires a constant expression. If an expression is not evaluated, for example because it appears in the right operand of a logical AND operator whose left operand is always false, then this rule does not apply. RationaleUnsigned integer expressions do not strictly overflow, but instead wrap-around. Although there may be good reasons to use modulo arithmetic at run-time, it is less likely for its use to be intentional at compile-time. ExampleThe expression associated with a case label is required to be a constant expression. If an unsigned wrap-around occurs during evaluation of a case expression, it is likely to be unintentional. On a machine with a 16-bit int type, any value of BASE greater than or equal to 65 024 would result in wrap-around in the following example: #define BASE 65024u switch ( x ) { case BASE + 0u: f ( ); break; case BASE + 1u: g ( ); break; case BASE + 512u: /* Non-compliant - wraps to 0 */ h ( ); break; } The controlling expression of a #if or #elif preprocessor directive is required to be a constant expression. #if 1u + ( 0u - 10u ) /* Non-compliant as ( 0u - 10u ) wraps */ In this example, the expression DELAY + WIDTH has the value 70 000 but this will wrap-around to 4 464 on a machine with a 16-bit int type. #define DELAY 10000u #define WIDTH 60000u void fixed_pulse ( void ) { uint16_t off_time16 = DELAY + WIDTH; /* Non-compliant */ } This rule does not apply to the expression c + 1 in the following compliant example as it accesses an object and therefore does not satisfy the constraints for a constant expression: const uint16_t c = 0xffffu; void f ( void ) { uint16_t y = c + 1u; /* Compliant */ } In the following example, the sub-expression ( 0u - 1u ) leads to unsigned integer wrap-around. In the initialization of x, the sub-expression is not evaluated and the expression is therefore compliant. However, in the initialization of y, it may be evaluated and the expression is therefore non-compliant. bool_t b; void g ( void ) { uint16_t x = ( 0u == 0u ) ? 0u : ( 0u - 1u ); /* Compliant */ uint16_t y = b ? 0u : ( 0u - 1u ); /* Non-compliant */ } MISRA-C 2004 Rule 12.11 (advisory): Evaluation of constant unsigned integer expressions should not lead to wrap-aroundThis rule is also covered by MISRA.ELIF.WRAPAROUND and MISRA.IF.WRAPAROUND. Because unsigned integer expressions do not strictly overflow, but instead wrap around in a modular way, any constant unsigned integer expressions which in effect "overflow" will not be detected by the compiler. Although there may be good reasons at run-time to rely on the modular arithmetic provided by unsigned integer types, the reasons for using it at compile-time to evaluate a constant expression are less obvious. Any instance of an unsigned integer constant expression wrapping around is therefore likely to indicate a programming error. This rule applies equally to all phases of the translation process. Constant expressions that the compiler chooses to evaluate at compile time are evaluated in such a way that the results are identical to those that would be obtained by evaluation on the target with the exception of those appearing in conditional preprocessing directives. For such directives, the usual rules of arithmetic (see section 6.4 of ISO/IEC 9899:1990 [2]) apply but the int and unsigned int types behave instead as if they were long and unsigned long respectively. ExampleFor example, on a machine with a 16-bit int type and a 32-bit long type: #define START 0x8000 #define END 0xFFFF #define LEN 0x8000 #if ((START + LEN) > END) #error Buffer Overrun /* OK because START and LEN are unsigned long */ #endif #if (((END - START) - LEN) < 0) #error Buffer Overrun /* Not OK: subtraction result wraps around to 0xFFFFFFFF */ #endif /* contrast the above START + LEN with the following */ if ((START + LEN) > END) { error ("Buffer overrun"); /* Not OK: START + LEN wraps around to 0x0000 due to unsigned int arithmetic */ } MISRA-C++ 2008 Rule 5-19-1 (advisory): Evaluation of constant unsigned integer expressions should not lead to wrap-around.This rule is also covered by MISRA.ELIF.WRAPAROUND and MISRA.IF.WRAPAROUND. RationaleUnsigned integer expressions do not strictly overflow, but instead wrap around in a modular way. Any constant unsigned integer expressions that in effect "overflow" will not be detected by the compiler. Although there may be good reasons at run-time to rely on the modular arithmetic provided by unsigned integer types, the reasons for using it at compile-time to evaluate a constant expression are less obvious. Any instance of an unsigned integer constant expression wrapping around is therefore likely to indicate a programming error. This rule applies equally to all phases of the translation process. Constant expressions that the compiler chooses to evaluate at compile time are evaluated in such a way that the results are identical to those that would be obtained by evaluation on the target, with the exception of those appearing in conditional preprocessing directives. For such directives, the usual rules of arithmetic apply but the int and unsigned int types behave instead as if they were long and unsigned long respectively. ExampleOn a machine with a 16-bit int type and a preprocessor using a 32-bit long type: #define START 0x8000 #define END 0xFFFF #define LEN 0x8000 #if ( ( START + LEN ) > END ) #error Buffer Overrun // OK as START and LEN are unsigned long #endif #if ( ( ( END — START ) — LEN ) < 0 ) #error Buffer Overrun // Not OK: subtraction result wraps around to 0xFFFFFFFF #endif // contrast the above START + LEN with the following void fn ( ) { if ( ( START + LEN ) > END ) { error ( "Buffer overrun" ); // Not OK: START + LEN wraps around to 0x0000 due to unsigned int // arithmetic } } |