# Unused local variables. use base ("Understand::Codecheck"); use strict; sub name{ return '21.1 Minimisation of run-time failures shall be ensured by the use of static analysis tools'; } sub description { return "21.1 (Required) Minimisation of run-time failures shall be ensured by the use of at least one of: (a) static analysis tools/techniques; (b) dynamic analysis tools/techniques; (c) explicit coding of checks to handle run-time faults."; } sub detailed_description { return <<"END_DESC"

Rule
Minimisation of run-time failures shall be ensured by the use of at least one of
  (a) static analysis tools/techniques;   (b) dynamic analysis tools/techniques;   (c) explicit coding of checks to handle run-time faults.

Rationale
Run-time checking is an issue, which is not specific to C, but it is an issue which C programmers need to pay special attention to. This is because the C language is weak in its provision of any run-time checking. C implementations are not required to perform many of the dynamic checks that are necessary for robust software. It is therefore an issue that C programmers need to consider carefully, adding dynamic checks to code wherever there is potential for run-time errors to occur.

Where expressions consist only of values within a well-defined range, a run-time check may not be necessary, provided it can be demonstrated that for all values within the defined range the exception cannot occur. Such a demonstration, if used, should be documented along with the assumptions on which it depends. However if adopting this approach, be very careful about subsequent modifications of the code which may invalidate the assumptions, or of the assumptions changing for any other reason.

The following notes give some guidance on areas where consideration needs to be given to the provision of dynamic checks.

Arithmetic Errors
This includes errors occurring in the evaluation of expressions, such as overflow, underflow, divide by zero or loss of significant bits through shifting. In considering integer overflow, note that unsigned integer calculations do not strictly overflow (producing undefined values), but the values wrap around (producing defined, but possibly wrong, values).

Pointer Arithmetic
Ensure that when an address is calculated dynamically the computed address is reasonable and points somewhere meaningful. In particular it should be ensured that if a pointer points within a structure or array, then when the pointer has been incremented or otherwise altered it still points to the same structure or array. See restrictions on pointer arithmetic – Rules 17.1, 17.2 and 17.4.

Array Bound Errors
Ensure that array indices are within the bounds of the array size before using them to index the array.

Function Parameters
See Rule 20.3.

Pointer Dereferencing
Where a function returns a pointer and that pointer is subsequently de-referenced the program should first check that the pointer is not NULL. Within a function, it is relatively straightforward to reason about which pointers may or may not hold NULL values. Across function boundaries, especially when calling functions defined in other source files or libraries, it is much more difficult.

/* Given a pointer to a message, check the message header and return 
   a pointer to the body of the message or NULL if the message is 
   invalid. */ 
const char_t *msg_body (const char_t *msg) 
{ 
   const char_t *body = NULL;
   if (msg != NULL)
   { 
      if (msg_header_valid (msg))
      { 
         body = &msg[MSG_HEADER_SIZE]; 
      } 
   } 
   return (body); 
}
...
      char_t msg_buffer[MAX_MSG_SIZE]; 
const char_t *payload; 
... 
payload = msg_body (msg_buffer); 
if (payload != NULL) 
{ 
   /* process the message payload */ 
} 

The techniques that will be employed to minimise run-time failures should be planned and documented, e.g. in design standards, test plans, static analysis configuration files, code review checklists. END_DESC } sub test_language { my $language = shift; return $language eq "C++"; } sub test_entity { return 0; } sub test_global { return 1; } sub check { my $check = shift; #Never returns error, the act of running the test indicates you are using a static analysis tool and pass the test }