0% found this document useful (0 votes)
211 views136 pages

Misra C

The document discusses the MISRA-C and CERT coding standards. It provides an introduction to MISRA and describes how the rules are classified as required or advisory. It then presents examples of specific rules covering areas like environment, language extensions, character sets, identifiers, types, constants, declarations, initialization, and expressions. The rules are presented in a standardized format indicating the rule number, category, text, and source.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
211 views136 pages

Misra C

The document discusses the MISRA-C and CERT coding standards. It provides an introduction to MISRA and describes how the rules are classified as required or advisory. It then presents examples of specific rules covering areas like environment, language extensions, character sets, identifiers, types, constants, declarations, initialization, and expressions. The rules are presented in a standardized format indicating the rule number, category, text, and source.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 136

MISRA-C and CERT coding

standards
Introduction
• MISRA- The Motor Industry Software Reliability
Association
• Every rule is classified as being either “required”
or “advisory”
• Required rules: These are mandatory
requirements placed on the programmer
• Advisory rules: These are requirements placed
on the programmer that should normally be
followed
09/20/2022 Embedded systems & IoT 2
Presentation of rules
• Rule <number> (<category>): <requirement text>
<number> Every rule has a unique number. This number
consists of a rule group prefix and a group member
suffix.
<category> is one of “required” or “advisory”,
<requirement text> The rule itself.
• <source ref> This indicates the primary source(s) where a
rule originates from one or more published sources
these are indicated in square brackets after the rule.
Rule 1.1 (req) [IEC 61508 Part 3]
09/20/2022 Embedded systems & IoT 3
typedef’d types
• char_t plain 8 bit character
• uint8_t unsigned 8 bit integer
• uint16_t unsigned 16 bit integer
• uint32_t unsigned 32 bit integer
• int8_t signed 8 bit integer
• int16_t signed 16 bit integer
• int32_t signed 32 bit integer
• float32_t 32 bit floating-point
• float64_t 64 bit floating-point
09/20/2022 Embedded systems & IoT 4
Environment

Rule 1.1 (req) All code shall conform to ISO/IEC 9899:1990


“Programming languages — C”, amended and corrected by ISO/IEC
9899/COR1:1995, ISO/IEC 9899/ AMD1:1995, and ISO/IEC
9899/COR2:1996

Rule 1.2 (req) No reliance shall be placed on undefined or unspecified


behavior.

Rule 1.3 (req) Multiple compilers and/or languages shall only be used
if there is a common defined interface standard for object code to
which the languages/compilers/ assemblers conform.
e.g. ELF (Extensible Linking Format) format - Executable and Linkable Format

09/20/2022 Embedded systems & IoT 5


Contd.
Rule 1.4 (req) The compiler/linker shall be checked to
ensure that 31 character significance and case
sensitivity are supported for external identifiers.
ANSI allows six significant characters in an external
identifier's name and 31 for names of internal (within
a function) identifiers

Rule 1.5 (adv) Floating-point implementations should


comply with a defined floating-point standard.
(ANSI/IEEE Std 754)
09/20/2022 Embedded systems & IoT 6
Language extensions
• Rule 2.1 (req) Assembly language shall be encapsulated and isolated
in (a) assembler functions, (b) C functions or (c) macros.

• Rule 2.2 (req) Source code shall only use /* … */ style comments.

• Rule 2.3 (req) The character sequence /* shall not be used within a
comment.
The double-slash comments (//) expire at the end of the
line. Slash-star (/*) comments are in effect until a closing comment
mark (*/)

• Rule 2.4 (adv) Sections of code should not be “commented out”.

09/20/2022 Embedded systems & IoT 7


Inline assembly code in C
void main() {
    int a = 3, b = 3, c;
    asm {
      mov ax,a
      mov bx,a
      add ax,bx
      mov c,ax
   }
    printf("%d",c);
}
#define NOP asm(" NOP")

09/20/2022 Embedded systems & IoT 8


Character sets
• Rule 4.1 (req) Only those escape sequences that are defined in the ISO C
standard shall be used.
• All “hexadecimal-escape-sequences” are prohibited.
• The “octal-escape-sequences” other than \0 are also prohibited
• Rule 4.2 (req) Trigraphs shall not be used.
Trigraphs are denoted by a sequence of 2 question marks followed by a
specified third character
(e.g. ??- represents a “~” (tilde) character and ??) represents a “]”).
They can cause accidental confusion with other uses of two question marks.
For example the string
"(Date should be in the form ??-??-??)"
would not behave as expected, actually being interpreted by the compiler as
"(Date should be in the form ~~]"

09/20/2022 Embedded systems & IoT 9


Identifiers
• Rule 5.1 (required):Identifiers (internal and external)
shall not rely on the significance of more than 31
characters.(internal identifiers to be distinct in the first 31
characters to guarantee code portability)
• Rule 5.2 (required):Identifiers in an inner scope shall
not use the same name as an identifier in an outer
scope, and therefore hide that identifier.
int16_t i;
{
int16_t i;
i = 3;
}
09/20/2022 Embedded systems & IoT 10
Contd.
Rule 5.3 (required):A typedef name shall be a unique
identifier
{
typedef unsigned char uint8_t;
}
{
unsigned char uint8_t; /* Not compliant - reuse of
uint8_t */
}

09/20/2022 Embedded systems & IoT 11


Contd.
Rule 5.4 (required):A tag name shall be a unique
identifier.

struct stag { uint16_t a; uint16_t b; };


void foo(void)
{
struct stag { uint16_t a; }; /* Not compliant - tag stag
redefined */
}

09/20/2022 Embedded systems & IoT 12


Contd.
Rule 5.5 (advisory):No object or function identifier with
static storage duration should be reused
• Regardless of scope, no identifier with static storage
duration should be re-used across any source files in
the system.
• This includes objects or functions with external
linkage and any objects or functions with the static
storage class specifier.
• One example of this confusion is having an identifier
name with internal linkage in one file and the same
identifier name with external linkage in another file.
09/20/2022 Embedded systems & IoT 13
Contd.
Rule 5.7 (advisory):No identifier name should be reused
struct air_speed
{
uint16_t speed; /* knots */
} * x;

struct gnd_speed
{
uint16_t speed; /* mph */
/* Not Compliant - speed is in different units */
} * y;

x->speed = y->speed;

09/20/2022 Embedded systems & IoT 14


Types
• Rule 6.1 (required):The plain char type shall be used only for
the storage and use of character values.

• Rule 6.2 (required):signed and unsigned char type shall be


used only for the storage and use of numeric values.

• Rule 6.3 (advisory):typedefs that indicate size and signedness


should be used in place of the basic numerical types
 typedef char char_t;
 typedef signed char int8_t;

09/20/2022 Embedded systems & IoT 15


Contd.
• Rule 6.4 (required):Bit fields shall only be defined to
be of type unsigned int or signed int
E.g. unsigned int d: 5;

• Rule 6.5 (required):Bit fields of signed type shall be


at least 2 bits long.

09/20/2022 Embedded systems & IoT 16


Constants
• Rule 7.1 (required):Octal constants (other than zero)
and octal escape sequences shall not be used.
code[1] = 109; /* equivalent to decimal 109 */
code[2] = 100; /* equivalent to decimal 100 */
code[3] = 052; /* equivalent to decimal 42 */
code[4] = 071; /* equivalent to decimal 57 */

09/20/2022 Embedded systems & IoT 17


Declarations and definitions
• Rule 8.1 (required):Functions shall have prototype
declarations and the prototype shall be visible at
both the function definition and call.

• Rule 8.2 (required): Whenever an object or function


is declared or defined, its type shall be explicitly
stated.
• static int16_t foo(void);

09/20/2022 Embedded systems & IoT 18


Contd.
• Rule 8.3 (required): For each function parameter the
type given in the declaration and definition shall be
identical, and the return types shall also be identical.

• Rule 8.11 (required): The static storage class specifier


shall be used in definitions and declarations of
objects and functions that have internal linkage.

09/20/2022 Embedded systems & IoT 19


example
#include<stdio.h>
/* function prototype, also called function declaration*/
float square ( float x );
float square ( float x )   /* function definition*/
{
    float p ;
    p = x * x ;
    return ( p ) ;
}
09/20/2022 Embedded systems & IoT 20
Contd.
int main( )              
{
    float m, n ;
    printf ( "\nEnter some number for finding square \n");
    scanf ( "%f", &m ) ;
    /* function call*/
    n = square ( m ) ;                      
    printf ( "\nSquare of the given number %f is %f",m,n );
}

09/20/2022 Embedded systems & IoT 21


Contd.
• Rule 8.12 (required): When an array is declared with
external linkage, its size shall be stated explicitly or
defined implicitly by initialisation.
 int array2[ ] = { 0, 10, 15 };
 extern int array2[ ];
 int array1[ 10 ];

09/20/2022 Embedded systems & IoT 22


Initialization
• Rule 9.1 (required): All automatic variables shall have
been assigned a value before being used.
• Rule 9.2 (required): Braces shall be used to indicate and
match the structure in the non-zero initialization of
arrays and structures.
• int16_t y[3][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
• int16_t y[3][2] = { 1, 2, 3, 4, 5, 6 };non-complaint

09/20/2022 Embedded systems & IoT 23


Expressions
• Rule 12.1 (advisory): Limited dependence
should be placed on C’s operator precedence
rules in expressions.
• x = a + b; /* acceptable */
• x = (a + b); /* () not required
• Do not add too many parentheses so as to clutter the
code and make it unreadable

09/20/2022 Embedded systems & IoT 24


Contd.
• Rule 12.3 (required): The sizeof operator shall not be
used on expressions that contain side effects.
 int32_t i;
 int32_t j;
 j = sizeof(i = 1234);

09/20/2022 Embedded systems & IoT 25


Contd.
• Rule 12.4 (required): The right-hand operand of a
logical && or || operator shall not contain side effects.
 if ( ishigh && ( x == i++ ) )
• if ( ishigh && ( x == f(x) ) ) /* Only acceptable if f(x) is
known to have no side effects */

• Rule 12.7 (required): Bitwise operators shall not be


applied to operands whose underlying type is signed.
• (~, <<, <<=, >>, >>=, &, &=, ^, ^=, | and |=) not
meaningful for signed integers
09/20/2022 Embedded systems & IoT 26
Contd.
• Rule 12.13 (advisory): The increment (++) and
decrement (--) operators should not be mixed with other
operators in an expression.
u8a = ++u8b + u8c--;
• The following sequence is clearer and therefore
safer:
++u8b;
u8a = u8b + u8c;
u8c--;
09/20/2022 Embedded systems & IoT 27
Control statement expressions
• Rule 13.1 (required): Assignment operators shall not
be used in expressions that yield a Boolean value.
x = y;
if ( x != 0 ) /* complaint*/
{
foo();
}

09/20/2022 Embedded systems & IoT 28


Contd.
if ( ( x = y ) != 0 ) /* Boolean by context */
{
foo();
}

09/20/2022 Embedded systems & IoT 29


Contd.
• Rule 13.3 (required): Floating-point expressions
shall not be tested for equality or inequality.
 float32_t x, y;
 /* some calculations in here */
 if ( x == y ) /* not compliant */
• Rule 13.4 (required): The controlling
expression of a for statement shall not contain
any objects of floating type.(Rounding and
truncation errors)
09/20/2022 Embedded systems & IoT 30
Contd.
• Rule 13.6 (required): Numeric variables being used
within a for loop for iteration counting shall not be
modified in the body of the loop.
flag = 1;
for ( i = 0; (i < 5) && (flag == 1); i++ )
{
flag = 0; /* Compliant - allows early termination of loop */
i = i + 3; /* Not compliant - altering the loop counter */
}

09/20/2022 Embedded systems & IoT 31


Control flow
• Rule 14.1 (required): There shall be no unreachable code. A portion of
code is unreachable if there is no control flow path from the relevant entry point to that
• code.
switch (event)
{
case E_wakeup:
do_wakeup();
break; /* unconditional control transfer */
do_more(); /* Not compliant - unreachable code */
/* ... */
default:
/* ... */
break;
}

09/20/2022 Embedded systems & IoT 32


Contd.
Rule 14.4 (required): The goto statement shall not be
used.
Rule 14.5 (required): The continue statement shall not
be used.
Rule 14.6 (required): For any iteration statement there
shall be at most one break statement used for loop
termination.

09/20/2022 Embedded systems & IoT 33


Contd.
• Rule 14.9 (required): An if (expression) construct
shall be followed by a compound statement. The else
keyword shall be followed by either a compound
statement, or another if statement.

09/20/2022 Embedded systems & IoT 34


Contd.
if ( test1 )
{
x = 1; /* Even a single statement must be in braces */
}
else if ( test2 )
{
x = 0; /* Single statement must be in braces */
}
else
x = 3; /* This was (incorrectly) not enclosed in braces */
y = 2;

09/20/2022 Embedded systems & IoT 35


Contd.
• Rule 14.10 (required): All if … else if constructs shall
be terminated with an else clause.
if ( x < 0 )
{
log_error(3);
x = 0;
} /* else not needed */

09/20/2022 Embedded systems & IoT 36


• This rule applies whenever an if statement is
followed by one or more else if statements;
the final else if shall be followed by an else
statement.
• In the case of a simple if statement then the
else statement need not be included.

09/20/2022 Embedded systems & IoT 37


Contd.
if ( x < 0 )
{
log_error(3);
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else {
x=1;
}

09/20/2022 Embedded systems & IoT 38


Switch statement
• Rule 15.5 (required): Every switch statement shall
have at least one case clause.
• Rule 15.4 (required): A switch expression shall not
represent a value that is effectively Boolean
switch (x == 0) /* not compliant - effectively Boolean */
{
• Rule 15.3 (required): The final clause of a switch
statement shall be the default clause.

09/20/2022 Embedded systems & IoT 39


Functions
• Rule 16.1 (required): Functions shall not be defined
with a variable number of arguments
• Rule 16.2 (required): Functions shall not call
themselves, either directly or indirectly.
• Rule 16.3 (required): Identifiers shall be given for all
of the parameters in a function prototype declaration

09/20/2022 Embedded systems & IoT 40


Contd.
• Rule 16.5 (required): Functions with no parameters
shall be declared and defined with the parameter list
void.
void myfunc ( void );

• Rule 16.6 (required): The number of arguments


passed to a function shall match the number of
parameters.

09/20/2022 Embedded systems & IoT 41


Contd.
• Rule 16.8 (required): All exit paths from a function
with non-void return type shall have an explicit
return statement with an expression.

09/20/2022 Embedded systems & IoT 42


Pointers and arrays
• Rule 17.1 (required): Pointer arithmetic shall only be
applied to pointers that address an array or array
element.
• Rule 17.2 (required): Pointer subtraction shall only
be applied to pointers that address elements of the
same array.

09/20/2022 Embedded systems & IoT 43


Contd.
• Rule 17.4 (required): Array indexing shall be
the only allowed form of pointer arithmetic.
void my_fn(uint8_t * p1, uint8_t p2[])
{
uint8_t index = 0U;
uint8_t * p3;
index ++;
index = index + 5U;
p3[index] = 0U;
09/20/2022 Embedded systems & IoT 44
Structures and unions
• Rule 18.2 (required): An object shall not be assigned
to an overlapping object.
• Rule 18.3 (required) An area of memory shall not be
reused for unrelated purposes.
• Rule 18.4 (required): Unions shall not be used.

09/20/2022 Embedded systems & IoT 45


Preprocessing directives
• Rule 19.1 (advisory): #include statements in a file
should only be preceded by other preprocessor
directives or comments.
• Rule 19.2 (advisory): Non-standard characters should
not occur in header file names in #include directives.
(', \, ", or /*)
• Rule 19.3 (required): The #include directive shall be
followed by either a <filename> or "filename"
sequence.

09/20/2022 Embedded systems & IoT 46


Contd.
• Rule 19.5 (required): Macros shall not be #define’d
or #undef’d within a block.

• Rule 19.6 (required): #undef shall not be used.

• Rule 19.7 (advisory): A function should be used in


preference to a function-like macro.

09/20/2022 Embedded systems & IoT 47


Standard libraries
• Rule 20.1 (required): Reserved identifiers, macros
and functions in the standard library, shall not be
defined, redefined or undefined.

• Rule 20.2 (required): The names of standard library


macros, objects and functions shall not be reused.
• functions provide a safer mechanism

09/20/2022 Embedded systems & IoT 48


Contd.
• Rule 20.4 (required): Dynamic heap memory
allocation shall not be used.

• Rule 20.5 (required): The error indicator errno shall


not be used.

• Rule 20.10 (required): The library functions atof, atoi


and atol from library <stdlib.h> shall not be used.

09/20/2022 Embedded systems & IoT 49


Contd.
• Rule 20.11 (required): The library functions abort,
exit, getenv and system from library <stdlib.h> shall
not be used.

• Rule 20.12 (required): The time handling functions of


library <time.h> shall not be used. Includes time,
strftime(need to know exact implementation of the
compiler)

09/20/2022 Embedded systems & IoT 50


CERT C Coding Standard

09/20/2022 Embedded systems & IoT 51


CERT C Programming Language Secure
Coding Standard
• The goal of these rules and recommendations is to
develop safe, reliable, and secure systems
• Each rule and recommendation is given a unique
identifier within a standard-eg.PRE04-A
• A three letter mneumonic representing the section of
the standard
• A two digit numeric value in the range of 00-99
• The letter "A" or "C" to indicate whether the coding
practice is an advisory recommendation or a
compulsory rule
09/20/2022 Embedded systems & IoT 52
Risk Assessment
• Each rule and recommendation in a secure
coding standard has an assigned priority.

• Priorities are assigned using a metric based on


Failure Mode, Effects, and Criticality Analysis
(FMECA)

09/20/2022 Embedded systems & IoT 53


Contd.
• Severity - how serious are the consequences
of the rule being ignored
 1 = low (denial-of-service attack, abnormal
termination)
 2 = medium (data integrity violation, unintentional
information disclosure)
 3 = high (run arbitrary code)

09/20/2022 Embedded systems & IoT 54


Contd.
• Likelihood - how likely is it that a flaw
introduced by ignoring the rule could lead to
an exploitable vulnerability ( a weakness
exploited by an attacker)
 1 = unlikely
 2 = probable
 3 = likely

09/20/2022 Embedded systems & IoT 55


Contd.
• Remediation cost – how expensive is it to
comply with the rule
 1 = high (manual detection and correction)
 2 = medium (automatic detection / manual
correction)
 3 = low (automatic detection and correction)

09/20/2022 Embedded systems & IoT 56


Contd.
• The three values are then multiplied together
for each rule.
• This product provides a measure that can be
used in prioritizing the application of the rules.
• These products range from 1 to 27(1, 2, 3, 4,
6, 8, 9, 12, 18, and 27) .

09/20/2022 Embedded systems & IoT 57


Priorities and Levels
High severity,
likely, L1 P12-P27
inexpensive to
repair flaws
L2 P6-P9

L3 P1-P4

Med severity, Low severity,


probable, med unlikely,
cost to repair expensive to
flaws repair flaws

09/20/2022 Embedded systems & IoT 58


Contd.
• Each rule consists of a title, a description, and
noncompliant code examples and compliant solutions.
• The title is a concise description of the rule.
• The description specifies the normative requirements
of the rule.
• The noncompliant code examples are examples of code
that would constitute a violation of the rule.
• The accompanying compliant solutions demonstrate
equivalent code that does not violate the rule or any
other rules in this coding standard.
09/20/2022 Embedded systems & IoT 59
Preprocessor (PRE)
• PRE31-C :- Avoid side effects in arguments to unsafe
macros .
• Never invoke an unsafe macro with arguments
containing an assignment, increment, decrement,
volatile access, input/output, or other expressions
with side effects.

09/20/2022 Embedded systems & IoT 60


Noncompliant Code:
Validate that n is within the desired range
#define ABS(x) (((x) < 0) ? -(x) : (x))
void func(int n)
{
int m = ABS(++n);
}
m = (((++n) < 0) ? -(++n) : (++n));

09/20/2022 Embedded systems & IoT 61


Compliant Solution
#define ABS(x) (((x) < 0) ? -(x) : (x))
void func(int n)
{
++n;
int m = ABS(n);
}

09/20/2022 Embedded systems & IoT 62


Risk Assessment
• PRE31-C Low Unlikely Low P3 L3

09/20/2022 Embedded systems & IoT 63


Contd.
• PRE32-C. Do not use preprocessor directives in
invocations of function-like macros

• The arguments to a macro must not include


preprocessor directives, such as #define, #ifdef,
and #include function like macros
• This rule also applies to the use of preprocessor
directives in arguments to a function.

09/20/2022 Embedded systems & IoT 64


Noncompliant Code Example
• Validate the source string; calculate size,.
#include <string.h>
void func(const char *src)
{
char *dest;
memcpy(dest, src,
#ifdef
PLATFORM1 12
#else
24
#endif );
);
09/20/2022 Embedded systems & IoT 65
Compliant code
#include <string.h>
void func(const char *src)
{
char *dest;
#ifdef
PLATFORM1
memcpy(dest, src, 12);
#else
memcpy(dest, src, 24);
#endif
}

09/20/2022 Embedded systems & IoT 66


Risk Assessment
• PRE32-C Low Unlikely Medium P2 L3

09/20/2022 Embedded systems & IoT 67


Declarations and Initialization (DCL)
• DCL30-C. Declare objects with appropriate storage
durations
• Every object has a storage duration that determines
its lifetime. Do not attempt to access an object
outside of its lifetime
• Every object has a storage duration that determines
its lifetime: static and automatic

09/20/2022 Embedded systems & IoT 68


Noncompliant Code Example (Differing
Storage Durations)
#include <stdio.h>
const char *p;
void dont_do_this(void)
{
const char str1[] = "This will change";
p = str1;
}
void innocuous(void)
{
printf("%s\n", p);
}

09/20/2022 Embedded systems & IoT 69


Contd.
int main(void)
{
dont_do_this();
innocuous();
return 0;
}

09/20/2022 Embedded systems & IoT 70


Compliant Solution (Same Storage
Durations)
void this_is_OK(void)
{
const char str1[] = "Everything OK";
const char *p = str1;
}

09/20/2022 Embedded systems & IoT 71


Compliant Solution (Differing Storage
Durations)
const char *p;
void is_this_OK(void)
{
const char str1[] = "Everything OK?";
p = str1;
p = NULL;
}
p can be set to NULL before str1 is destroyed
09/20/2022 Embedded systems & IoT 72
Noncompliant Code Example
char *init_array(void)
{
char array[10];
return array;
}
Some compilers generate a diagnostic message when a pointer to an
object with automatic storage duration is returned from a function.

09/20/2022 Embedded systems & IoT 73


Compliant Solution (Return Values)
#include <stddef.h>
void init_array(char *array, size_t len)
{
return;
}
int main(void)
{
char array[10];
init_array(array, sizeof(array) / sizeof(array[0]));
return 0;
}

09/20/2022 Embedded systems & IoT 74


Contd.
• DCL30-C High Probable High P6 L2

09/20/2022 Embedded systems & IoT 75


Contd.
• DCL31-C. Declare identifiers before using them
Noncompliant Code Example (Implicit int)
• C no longer allows the absence of type specifiers in a
declaration e.g extern foo;
Compliant Solution (Implicit int)
• extern int foo;

09/20/2022 Embedded systems & IoT 76


Contd.
• Noncompliant Code Example (Implicit Function
Declaration)
• Implicit declaration of functions is not allowed; every
function must be explicitly declared before it can be
called

09/20/2022 Embedded systems & IoT 77


Noncompliant code example
#include <stddef.h>
int main(void)
{
for (size_t i = 0; i < 100; ++i)
{
char *ptr = (char *)malloc(0x10000000);
*ptr = 'a';
}
return 0;
}
09/20/2022 Embedded systems & IoT 78
Compliant Solution (Implicit Function Declaration)

#include <stdlib.h>
int main(void)
{
for (size_t i = 0; i < 100; ++i)
{
char *ptr = (char *)malloc(0x10000000);
*ptr = 'a';
}
return 0;
}
09/20/2022 Embedded systems & IoT 79
Noncompliant Code Example (Implicit
Return Type)
#include <limits.h>
#include <stdio.h>
foo(void)
{
return UINT_MAX;
}
int main(void)
{
long long int c = foo();
printf("%lld\n", c);
return 0;
}
Do not declare a function with an implicit return type UINT_MAX is incorrectly
converted to −1

09/20/2022 Embedded systems & IoT 80


Compliant Solution (Implicit Return Type)
#include <limits.h>
#include <stdio.h>
unsigned int foo(void)
{
return UINT_MAX;
}
int main(void)
{
long long int c = foo();
printf("%lld\n", c);
return 0;
}
09/20/2022 Embedded systems & IoT 81
Contd.
• DCL31-C Low Unlikely Low P3 L3

09/20/2022 Embedded systems & IoT 82


DCL37-C. Do not declare or define a
reserved identifier
• All identifiers that begin with an underscore
and either an uppercase letter or another un-
derscore are always reserved for any use

09/20/2022 Embedded systems & IoT 83


Noncompliant Code Example (Header
Guard)
#ifndef _MY_HEADER_H_
#define _MY_HEADER_H_
#endif

09/20/2022 Embedded systems & IoT 84


Compliant Solution (Header Guard)

#ifndef MY_HEADER_H
#define MY_HEADER_H
#endif

09/20/2022 Embedded systems & IoT 85


Noncompliant Code Example
#include <stddef.h>
static const size_t _max_limit = 1024;
size_t _limit = 100;
unsigned int getValue(unsigned int count)
{
return count < _limit ? count : _limit;
}

09/20/2022 Embedded systems & IoT 86


Compliant Solution
#include <stddef.h>
static const size_t max_limit = 1024;
size_t limit = 100;
unsigned int getValue(unsigned int count)
{
return count < limit ? count : limit;
}

09/20/2022 Embedded systems & IoT 87


DCL39-C. Avoid information leakage when
passing a structure across a trust boundary
• When a value is stored in an object of structure or
union type, including in a member object, the bytes
of the object representation that correspond to any
padding bytes take unspecified values.

09/20/2022 Embedded systems & IoT 88


Noncompliant Code Example
Copies data from struct test to user space.
#include <string.h>
struct test
{
int a;
char b;
int c;
};
extern int copy_to_user(void *dest, void *src, size_t size);

09/20/2022 Embedded systems & IoT 89


Contd.
void do_stuff(void *usr_buf)
{
struct test arg = {.a = 1, .b = 2, .c = 3};
copy_to_user(usr_buf, &arg, sizeof(arg));
}
struct uart
   {
      unsigned baud : 3;
      unsigned parity : 2;
      unsigned unused : 2;
      unsigned interrupt_enable : 1;
   };
09/20/2022 Embedded systems & IoT 90
Compliant Solution
#include <stddef.h>
#include <string.h>
struct test
{
int a;
char b;
int c;
};
09/20/2022 Embedded systems & IoT 91
Contd.
extern int copy_to_user(void *dest, void *src,
size_t size);
void do_stuff(void *usr_buf)
{
struct test arg = {.a = 1, .b = 2, .c = 3};
unsigned char buf[sizeof(arg)];
size_t offset = 0;

09/20/2022 Embedded systems & IoT 92


Contd.
memcpy(buf + offset, &arg.a, sizeof(arg.a));
offset += sizeof(arg.a);
memcpy(buf + offset, &arg.b, sizeof(arg.b));
offset += sizeof(arg.b);
memcpy(buf + offset, &arg.c, sizeof(arg.c));
offset += sizeof(arg.c);
copy_to_user(usr_buf, buf, offset
}
09/20/2022 Embedded systems & IoT 93
Compliant Solution (Structure Packing—
GCC)
#include <stddef.h>
struct test
{ int a;
char b;
int c;
} __attribute__((__packed__));

09/20/2022 Embedded systems & IoT 94


Contd.
extern int copy_to_user(void *dest, void *src,
size_t size);
void do_stuff(void *usr_buf)
{
struct test arg = {.a = 1, .b = 2, .c = 3};
copy_to_user(usr_buf, &arg, sizeof(arg));
}

09/20/2022 Embedded systems & IoT 95


DCL40-C. Do not create incompatible
declarations of the same function or
object
/* In a.c */
extern int i;
int f(void)
{
return ++I;
}
/* In b.c */
short i;
Two or more incompatible declarations of the same function or
object must not appear in the same program because they result
in undefined behavior.

09/20/2022 Embedded systems & IoT 96


Compliant Solution (Incompatible Object
Declarations)
/* In a.c */
extern int i;
int f(void)
{ return ++i;
}
/* In b.c */
int i;

09/20/2022 Embedded systems & IoT 97


Noncompliant Code Example (Incompatible
Array Declarations)
/* In a.c */
extern int *a;
int f(unsigned int i, int x)
{
int tmp = a[i]; /* read access */
a[i] = x; /* write access */
return tmp;
}
/* In b.c */
int a[] = { 1, 2, 3, 4 };
variable a is declared to have a pointer type in file a.c but defined to have
an array type in file b.c.

09/20/2022 Embedded systems & IoT 98


Compliant Solution (Incompatible Array
Declarations)
/* In a.c */
extern int a[];
int f(unsigned int i, int x)
{
int tmp = a[i];
a[i] = x;
return tmp;
}
int a[] = { 1, 2, 3, 4 }; /* In b.c */
09/20/2022 Embedded systems & IoT 99
Noncompliant Code Example (Incompatible
Function Declarations)
/* In a.c */
extern int f(int a);
int g(int a)
{
return f(a); }
/* In b.c */
long f(long a)
{
return a * 2;
}
the function f() is declared in file a.c with one prototype but defined in file
b.c with another.

09/20/2022 Embedded systems & IoT 100


Compliant Solution (Incompatible Function
Declarations)
/* In a.c */
extern int f(int a);
int g(int a)
{
return f(a);
}/* In b.c */
int f(int a)
{
return a * 2;
}
09/20/2022 Embedded systems & IoT 101
DCL41-C. Do not declare variables inside a
switch statement before the first case label
• If a programmer declares variables, initializes
them before the first case statement, and then
tries to use them inside any of the case
statements, those variables will have scope
inside the switch block but will not be
initialized and will consequently contain
indeterminate values.

09/20/2022 Embedded systems & IoT 102


Noncompliant Code Example
#include <stdio.h>
extern void f(int i);
void func(int expr)
{
switch (expr)
{
int i = 4;
f(i);
case 0:
i = 17;
09/20/2022 Embedded systems & IoT 103
contd.
• /* Falls through into default code */ default:
printf("%d\n"., i); } }

09/20/2022 Embedded systems & IoT 104


Compliant Solution
#include <stdio.h>
extern void f(int i);
int func(int expr)
{ /** Move the code outside the switch block;
now the statements * will get executed. */
int i = 4;
f(i);

09/20/2022 Embedded systems & IoT 105


Contd.

switch (expr)
{ case 0: i = 17;
/* Falls through into default code */
default: printf(".oe%d\n"., i);
}
return 0;
}

09/20/2022 Embedded systems & IoT 106


Expressions (EXP)
EXP30-C. Do not depend on the order of evaluation for
side effects
Noncompliant Code Example
#include <stdio.h>
void func(int i, int *b)
{
int a = i + b[++i];
printf("%d, %d", a, i);
}
09/20/2022 Embedded systems & IoT 107
Compliant Solution
#include <stdio.h>
void func(int i, int *b)
{
int a;
++i;
a = i + b[i];
printf("%d, %d", a, i);
}
09/20/2022 Embedded systems & IoT 108
Call functions with the correct number and
type of arguments
• Do not call a function with the wrong number
or type of arguments

09/20/2022 Embedded systems & IoT 109


Noncompliant Code Example
#include <tgmath.h>
void func(void)
{ double complex c = 2.0 + 4.0 * I;
double complex result = log2(c);
}
Calling any of the following type-generic
functions with complex values is undefined
be-havior.
09/20/2022 Embedded systems & IoT 110
Compliant Solution (Complex Number)

#include <tgmath.h>
void func(void)
{ double complex c = 2.0 + 4.0 * I;
double complex result = log(c)/log(2);
}

09/20/2022 Embedded systems & IoT 111


EXP44-C Do not rely on side effects in
operands to sizeof
Noncompliant Code Example (sizeof)
#include <stdio.h>
void func(void)
{
int a = 14;
int b = sizeof(a++);
printf("%d, %d\n", a, b);
}
the operand is not evaluated
09/20/2022 Embedded systems & IoT 112
Compliant Solution (sizeof)
#include <stdio.h>
void func(void)
{
int a = 14;
int b = sizeof(a);
++a;
printf("%d, %d\n", a, b); }

09/20/2022 Embedded systems & IoT 113


EXP45-C. Do not perform assignments in
selection statements
Noncompliant Code Example
if (a = b) {.. }
Compliant Solution (Unintentional Assignment)
if (a == b)
..
}
if ((a = b) != 0) { /* ... */ }

09/20/2022 Embedded systems & IoT 114


Contd.
• do { /* ... */ } while (foo(), x = y); -NC
• do { /* ... */ } while (x = y, p == q); -C

09/20/2022 Embedded systems & IoT 115


EXP46-C. Do not use a bitwise operator with
a Boolean-like operand
• Noncompliant Code Example
• if (!(getuid() & geteuid() == 0)) { /* ... */ }
• Compliant Solution
• if (!(getuid() && geteuid() == 0)) { /* ... */ }
• Mixing bitwise and relational operators in the
same full expression can be a sign of a logic
error in the expression where a logical
operator is usually the intended operator
09/20/2022 Embedded systems & IoT 116
Integers(INT)
• INT30-C. Ensure that unsigned integer
operations do not wrap
• Noncompliant Code Example
• void func(unsigned int ui_a, unsigned int ui_b)
{ unsigned int usum = ui_a + ui_b; /* ... */ }

09/20/2022 Embedded systems & IoT 117


Compliant Solution (Precondition Test)

#include <limits.h>
void func(unsigned int ui_a, unsigned int ui_b) {
unsigned int usum;
if (UINT_MAX - ui_a < ui_b) { /* Handle error */ }
else
{ usum = ui_a + ui_b; }/* ... */ }

09/20/2022 Embedded systems & IoT 118


Noncompliant Code Example (Unsigned to
Signed)
#include <limits.h>
void func(void)
{ unsigned long int u_a = ULONG_MAX;
signed char sc;
sc = (signed char)u_a;
• /* Cast eliminates warning */ /* ... */ }
• Type range errors, including loss of data (truncation) and
loss of sign (sign errors), can occur when converting from
a value of an unsigned integer type to a value of a signed
integer type
09/20/2022 Embedded systems & IoT 119
Compliant Solution (Unsigned to Signed)

#include <limits.h>
void func(void)
{ unsigned long int u_a = ULONG_MAX;
signed char sc;
if (u_a <= SCHAR_MAX)
{ sc = (signed char)u_a; /* Cast eliminates warning */
}
else { /* Handle error */
}
}
09/20/2022 Embedded systems & IoT 120
INT32-C. Ensure that operations on signed
integers do not result in overflow
Noncompliant Code Example
void func(signed int si_a, signed int si_b)
{
signed int sum = si_a + si_b; /* ... */
}

09/20/2022 Embedded systems & IoT 121


Compliant Solution
#include <limits.h>
void f(signed int si_a, signed int si_b)
{ signed int sum;
if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
((si_b < 0) && (si_a < (INT_MIN - si_b))))
{ /* Handle error */ }
else
{
sum = si_a + si_b;
}/* ... */ }
09/20/2022 Embedded systems & IoT 122
Contd.
• INT34-C. Do not shift an expression by a negative
number of bits or by greater than or equal to the
number of bits that exist in the operand
• INT33-C. Ensure that division and remainder
operations do not result in divide-by-zero errors
• INT35-C. Use correct integer precisions. The
precision of an integer type is the number of bits
it uses to represent values, excluding any sign
and padding bits.
09/20/2022 Embedded systems & IoT 123
Floating Point (FLP)
FLP30-C. Do not use floating-point variables as loop
counters
Noncompliant Code Example
void func(void)
{
for (
float x = 0.1f; x <= 1.0f; x += 0.1f)
{ /* Loop may iterate 9 or 10 times */
}
}
09/20/2022 Embedded systems & IoT 124
Compliant Solution
#include <stddef.h>
void func(void)
{
for (size_t count = 1; count <= 10; ++count)
{ float x = count / 10.0f;
/* Loop iterates exactly 10 times */

09/20/2022 Embedded systems & IoT 125


Array (ARR)
• ARR30-C. Do not form or use out-of-bounds
pointers or array subscripts

09/20/2022 Embedded systems & IoT 126


Noncompliant Code Example (Apparently
Accessible Out-of-Range Index)
#include <stddef.h>
#define COLS 5
#define ROWS 7
static int matrix[ROWS][COLS];
void init_matrix(int x)
{
for (size_t i = 0; i < COLS; i++) {
for (size_t j = 0; j < ROWS; j++)
{ matrix[i][j] = x; }
}
}

09/20/2022 Embedded systems & IoT 127


Contd.
• the function iterates over the elements in
column-major order, and when the value of j
reaches the value COLS during the first
iteration of the outer loop, the function
attempts to access element matrix[0][5].

09/20/2022 Embedded systems & IoT 128


Compliant Solution
#include <stddef.h>
#define COLS 5
#define ROWS 7
static int matrix[ROWS][COLS];
void init_matrix(int x)
{
for (size_t i = 0; i < ROWS; i++)
{ for (size_t j = 0; j < COLS; j++)
{ matrix[i][j] = x;
}
}
}

09/20/2022 Embedded systems & IoT 129


Characters and Strings (STR)
• STR30-C. Do not attempt to modify string
literals
• Noncompliant Code Example
• char *p = "string literal"; p[0] = ‘S';

09/20/2022 Embedded systems & IoT 130


CONTD.
• Compliant Solution
• char a[] = "string literal"; a[0] = ‘S';
• This code creates a copy of the string literal in the
space allocated to the character array a. The
string stored in a can be modified safely.

• STR31-C. Guarantee that storage for strings has


sufficient space for character data and the null
terminator
09/20/2022 Embedded systems & IoT 131
NC
STR32-C. Do not pass a non-null-terminated
character sequence to a library function that
expects a string
#include <stdio.h>
void func(void)
{
char c_str[3] = "abc";
printf("%s\n", c_str);
}
09/20/2022 Embedded systems & IoT 132
C
#include <stdio.h>
void func(void)
{ char c_str[] = "abc";
printf("%s\n", c_str);
}

09/20/2022 Embedded systems & IoT 133


Memory Management (MEM)
• MEM30-C. Do not access freed memory
• MEM31-C. Free dynamically allocated
memory when no longer needed

09/20/2022 Embedded systems & IoT 134


NC
#include <stdlib.h> enum
{ BUFFER_SIZE = 32 };
int f(void)
{
char *text_buffer = (char *)malloc(BUFFER_SIZE);
if (text_buffer == NULL)
{ return -1;
}return 0;
}
09/20/2022 Embedded systems & IoT 135
C

#include <stdlib.h> enum


{ BUFFER_SIZE = 32 };
int f(void)
{
char *text_buffer = (char *)malloc(BUFFER_SIZE);
if (text_buffer == NULL)
{
return -1;
}
free(text_buffer);
return 0; }

09/20/2022 Embedded systems & IoT 136

You might also like