Secure Code Warrior

MISRA C 2012 vs MISRA C2 - How to make a switch

In this post, we will compare the MISRA C 2012 standard with C2, and guide you through the journey of switching to the new standard. We will explain why MISRA's compliance is necessary to build secure embedded systems.

At Secure Code Warrior, we are always looking to expand our training coverage. To empower embedded developers and security managers to build secure embedded systems, we are tapping into the world of embedded systems security. In this post, we will talk about the MISRA C 2012 standard, and why its compliance is necessary to build secure embedded systems.

While writing code in C, it’s very easy to implement things that seemingly look right, but are inherently wrong. Your code may compile just fine, and even run well for a certain period of time. But the same code could crash, or exhibit undefined behavior, if your input size and/or memory grows. For example, a particular input number causing an integer to overflow, or a particular sequence of characters causing an array to go out-of-bounds.

This is where the MISRA C coding standard can help. The rules, guidelines, and best practices laid out by the standard, enable developers to write safe and reliable C code for embedded development. 

MISRA C 2012, the latest version of the standard, adds new rules, enhances existing ones, and addresses some discrepancies. If you are still using an older version, now would be a great time to switch. 

What is the MISRA C coding standard?

The MISRA C standard includes code safety, portability, and reliability guidelines for the C programming language. The first set of guidelines was released in 1998, which were specific to the C language. 

However, since then, the MISRA Consortium also develops coding standards for C++. Every MISRA C document contains a set of rules, non-compliant examples, and detailed sections on the background information that contributed to the development of said rules.

C and C++ are the most widely used languages to develop embedded software. One of the main reasons is that they are fast, having only 1 or 2 levels of abstraction over machine language. But this also means that writing safe code, particularly in C, is difficult, and prone-to-error. For example, in most high-level languages like Java and C#, you don’t have to worry about trivial things like garbage collection or dynamic typing. 

However, in C, there’s no predefined way to collect garbage, i.e. if you allocate a piece of memory for a data structure, you have to manually free it yourself, once you are done using it. If you don’t, C, unlike other languages, will not free the memory for you, which will lead to a memory leak.

MISRA C 2004 (C2) vs. MISRA C 2012 (C3) – What changed?

MISRA C: 2012, also known as C3, was first released in April 2013. Drawing knowledge from the works of thousands of people and organizations, C3 adds new rules, enhances the explanation and backgrounds of some existing rules, and closes some loopholes.

C3 supports the C99 version of the language, while also maintaining rules for the older ISO C90. The main focus area in C3 was to reduce the usual costs of rule enforcement, while also making the use of the C language safer in critical systems. All this makes it prudent to switch to the new standard, if you haven’t already.

Overall, here’s a list of the most significant changes:

  • Correct issues that were found in the 2004 version.
  • Significantly increase the number of decidable rules. A rule is decidable, if an analysis tool can help you determine conformity to it.
  • Rules are categorized as “required”, “advisory”, or “mandatory”. Mandatory rules must never be broken, under any circumstances. Required and advisory rules can be violated in special scenarios, provided the violation is justified.
  • Added guidance regarding how to apply rules to auto-generated code. This is very important because the same guidelines of human-written code, don’t always apply to that generated by a tool.
  • Remove the overly generalized rules that forbade reasonable user behavior. E.g. previously it was recommended to not use macros at all, since they can lead to various difficulties and confusion (can’t debug macros, macros don’t have namespaces etc.). This prevented the use of macros, even in situations where they could provide an elegant, safe, and convenient solution. In MISRA C: 2012, new rules regarding macros were introduced, allowing people to use them carefully, whenever applicable. See the following excerpt, taken from a MISRA C document, that recommends using a macro over a function.
Screenshot of MISRA C recommendation of using a macro over a function.

MISRA C rules in action

Enough talk, now it’s time to get hands-on with some MISRA C rules, with examples of how they apply.

Use compatible types as pointer arguments to memcpy, memmove, and memcmp

The standard library functions memcpy, memmove, and memcmp perform byte-by-byte move or comparison of the specified number of bytes. The Rule 21.15 of MISRA C 2012 standard dictates that the two function parameters should be pointers to the same type. A function call with incompatible pointer types could indicate a mistake. 

Consider the following image, taken from the official MISRA compliance document. The rule is required, decidable, and applies to both C90 and C99.

Screenshot of MISRA C Rule 21.15

An example follows the rule description.

Screenshot of a non-compliant solution.

As you can see, since the objects are of different types (uint8_t and uint16_t), this is a non-compliant solution.

String handling functions that don’t take length as input shall not result in out-of-bound access

String handling functions from <string.h> that don’t take the length as an input, shouldn’t result in out-of-bound access. The relevant functions are: strcat, strchr, strcmp, strcoll, strcpy, strcspn, strlen, strpbrk, strrchr, strspn, strrstr, and strtok. The rule is mandatory, meaning it can never be breached, under any circumstances. It applies to both C90 and C99, and is undecidable.

Screenshot of MISRA C rule 21.17.

The corresponding example is:

Screenshot of a correct example of string handling functions

As you can see, strcpy in function f1, will copy beyond the length of the string, which can only hold 5 characters. We also have a compliant and safe use of strcpy, where the string will only get copied, if the contents of “str” will fit.

Validate externally received data

Dir 4.14 recommends checking the validity of data received from “external” sources. External input can be:

  • Read from a file.
  • Read from an environment variable.
  • Any user input.
  • Anything received over a communication channel. E.g. over a TCP connection or HTTP API etc.

This directive falls in the required category, and is applicable to both C90 and C99. The rationale for this is that a program has no control over data received from external sources, which means that this data can be invalid or malicious. E.g. a program expects a user to input a number, but the user enters a string. Before processing the input, the program must verify that it’s indeed a number.

How to switch to MISRA C 2012

Switching to MISRA C 2012 will require an update in your coding guidelines document. If you don’t use one, and instead rely on a static analysis tool (which is the recommended choice), you may have to get a newer version of the tool. Here are three tools that check for MISRA C 2012 compliance:

  1. Cppcheck is an open-source tool that can check for MISRA rules, and also detect various kinds of bugs.
  2. PC-lint Plus is a paid tool that comes with a 30-day evaluation period. In addition to checking for MISRA C compliance, it can also help identify potential bugs and vulnerabilities.
  3. CodeSonar is another tool that checks for both MISRA C and C++ compliance.

There are also a few compilers that can test for MISRA compliance. In case a rule violation is detected, warnings or exceptions are raised accordingly. E.g. Green Hills Software provides compilers with support for all MISRA standards, for both 32-bit and 64-bit architectures.

Using Secure Code Warrior to upskill developers in MISRA C

Secure Code Warrior's flagship product - learning platform - has numerous interactive challenges, courses, and assessments that can help train developers to write secure C/C++ code. The content on the platform is framework-specific and highly engaging. Our C/C++:Embed coding challenges took inspirations from both MISRA C, AUTOSAR C++ (MISRA C++), and IEC.

Developers can embark on personalized learning journeys, where they identify C/C++-specific vulnerabilities and more importantly learn to fix those bugs. In this process, developers can keep track of their progress to identify their weaknesses, and even enjoy a friendly coding competitions with their peers. Find out more about how we help automotive and transportation industries with our solutions.

Want to find out how interactive and embed-focus our challenges are? Try some C/C++:Embed challenges on the learning platform today!