CQM-RiskyCode

Typical fail-safe mechanisms are misused

Required inputs: IR

Misused fail-safe mechanisms include missing break statements and missing or empty default statements for switch statements, empty exception handlers and catch-all exception handlers before specific ones.
Motivation

Fail-safe mechanisms such as exception handling and default paths for switch statements ensure that in the event of unforeseen events (e.g. different input values), the application notifies the developer directly of the locations where the anomaly occurred. If these mechanisms are forgotten (e.g. missing default) or deliberately undermined (e.g. empty exception handler), possibly necessary changes of the program are concealed and the system could, under certain circumstances, supply wrong values much later at completely different locations.

For example, an empty catch block will cause all exceptions of a particular type to be ignored, regardless of what actually threw the exceptions. The problem is that assumptions can only be made about something that can be anticipated. An empty catch block, however, does not distinguish between foreseen and unforeseen exceptions, but ignores all of them. Missing default paths can cause the program to enter an undefined state due to changed input data, which only becomes apparent much later in the program flow. For safe queries of all possible values e.g. a default: ASSERT(FALSE) is helpful.

Missing breaks on the other hand cause a special control flow that is indistinguishable from the one where the break was forgotten.

This rule is based on the CQM Quality Indicator: Risikocode (p. 277-280).

Reference

Simon, Frank/ Seng, Olaf/ Mohaupt, Thomas (2006): Code-Quality-Management: Technische Qualität industrieller Softwaresysteme transparent und vergleichbar gemacht, 1st ed., Heidelberg, Germany: dpunkt.verlag GmbH.

Possible Messages

Key

Text

Severity

Disabled

catch_all_not_last

Catch-all shall occur as last handler.

None

False

empty_catch

Empty catch block.

None

False

empty_default

Default clause should contain a statement (in addition to break/return) or a comment.

None

False

missing_default

Switch has no “default” clause.

None

False

unterminated_case

This switch-case is not {}, last statement is {}.

None

False

unterminated_empty_case

This switch-case is empty, not {}.

None

False

Options

acceptable_end_items

acceptable_end_items : set[bauhaus.ir.PIR_Class_Name] = {'Exit_Switch'}

Allowed last items at the end of a switch.
 

acceptable_middle_items

acceptable_middle_items : set[bauhaus.ir.PIR_Class_Name] = {'Exit_Switch', 'Nondefault_Case_Label'}

Allowed last items in the middle of a switch.
 

allow_complete_enum

allow_complete_enum : bool = True

Whether a switch having a case for all enumerators is tolerated without a default.
 

allow_empty_blocks_including_comment

allow_empty_blocks_including_comment : bool = False

Whether empty blocks are allowed as long as they contain a comment.
 

allow_empty_default_case

allow_empty_default_case : bool = False

Whether a default case is allowed to be empty except for break/throw.

MISRA C:2012 Rule 16.4 requires a comment or statement in addition.
MISRA C++2008 does not.

 

allow_empty_statements

allow_empty_statements : bool = False

Whether empty statements at the end of switch-case should be ignored.
 

allow_fallthrough_comment

allow_fallthrough_comment : bool = True

Allow comments with text including both "fall" and "through" simultaneously.
 

allow_fallthrough_macro

allow_fallthrough_macro : bool = True

Allows the __fallthrough macro as marker for allowed fallthrough.
 

allow_if

allow_if : bool = False

Whether an if containing acceptable items at the end of both branches is accepted.
 

allow_noreturn_function_calls

allow_noreturn_function_calls : bool = False

Whether a function call to a [[noreturn]] function is considered a valid termination.
 

allow_switch

allow_switch : bool = False

Whether a switch containing acceptable items at the end of all cases is accepted.
 

comment

comment : set[str] = set()

The comment that indicates an intentional fallthrough. Can be a set of strings.