A practical guide to make your legacy codebase MISRA C 2012 compliant
Re-use of legacy code is a reality, but re-using legacy code in a safety critical software project and achieving full MISRA C 2012 compliance is a daunting task.
The original MISRA principles were created to be applied as code being developed. Even the document itself has a warning:
"...a project that checks for MISRA C compliance late in its cycle is likely to spend a considerable amount of time re-coding, re-reviewing and re-testing. It's therefore expected that the software development process will require the early application of MISRA C principles."
Because many organizations do need to re-use their legacy codebases for business reasons, the MISRA Compliance: 2016 guidance document was created in response to these challenges. In it, there is clear distinction between the new, native code that is developed in the scope of a current project, and the "adopted" code, which was developed outside of the scope of the project. In this post, I explain a practical approach to dealing with legacy code and MISRA C compliance.
The shades of gray of following MISRA guidelines
Although it seems like it should be simple to understand what type of code you're dealing with, the situation in many cases isn't black and white. For example, an initial prototype that was developed without following MISRA guidelines is productized, and then management realizes that compliance is a requirement for the intended marketplace. Typically, the legacy codebase was never developed with any coding guidelines in mind. Therefore, a codebase cannot be automatically classified as “adopted code” if updates are required in the context of a new project. This can get complex.
All too often, initial scans of a large codebase via a static analysis tool with all MISRA C 2012 rules enabled, including Amendment 1, produces tens of thousands of violations. After the initial shock, teams begin to find “creative” ways of addressing the violations. It’s important for development teams not to be deterred – there is light at the end of the tunnel.
Over time, I’ve collected and identified best practices and approaches that development teams have used to make the code compliant while not interfering with the ongoing development velocity. In this post, I’m sharing some practical, balanced approaches to make existing codebases MISRA compliant.
Use the MISRA Compliance:2016 framework
MISRA C 2012 is a set of coding guidelines for the C programming language. The focus of the standard is increasing safety of software by preemptively preventing programmers from making coding mistakes that can lead to runtime failures (and possible safety concerns) by avoiding known problem constructs in the C language. Over the years, many developers of embedded systems were (and still are) complaining that MISRA C was too stringent of a standard and that the cost of writing fully compliant code was difficult to justify. Realistically, given that MISRA C is applied in safety-critical software, the value of applying the standard to a project depends on factors such as:
- Risk of a system malfunction because of a software failure
- Cost of a system failure to the business
- Development tools and target platform
- Level of developer's expertise
So programmers must find a practical middle ground that satisfies the spirit of the standard and still claim MISRA compliance without wasting effort on non-value-added activities.
In the document MISRA Compliance: 2016 the MISRA Consortium provides the response that was needed by the community, with a reasonably well-defined framework of what the statement "MISRA Compliant" truly means. The document is helping organization to use a common language articulating the compliance requirements by defining the following artifacts:
- Guideline Enforcement Plan - demonstrates how each MISRA guideline is verified.
- Guideline Re-categorization Plan - communicates the agreed upon severity of individual rules in the guidelines as part of the vendor/client relationship.
- Deviations report - documents the violations of guidelines with appropriate rationale.
- Guidelines compliance summary - is the primary record of overall project compliance.
To focus on what to do with a legacy codebase, the key document is the Guideline Re-categorization plan. This document captures all directives and rules and identifies which categories have been re-categorized. For example, the following diagram shows part of a re-categorization plan:
First, for the “adopted” legacy code, the MISRA 2016: Compliance document suggests against re-categorizations from a less stringent to a more stringent classification. In addition, it’s possible to dis-apply Advisory rules all together after reviewing the types of violations with the team.
The requirement to document deviations is only necessary for all Required rules. Any violations in adopted code should be reviewed, and deviations need to clearly state that violations do not compromise safety and security. Regardless of re-categorization, if there is a finding that compromises the safety or security of the system, the issue must be fixed. Also, modifications to the legacy code may introduce other issues not clearly seen by the developer.
Begin with the end in mind
A key problem that developers of safety critical software encounter is how to demonstrate and prove compliance at the end of the project. This can be a contentious issue resulting in wasted time and effort if the evaluation criteria are based on subjective opinions from the various stakeholders. This is a situation that the MISRA Compliance: 2016 document helped to clear up.
A recommended approach to improving the evaluation of compliance readiness is to use existing templates for both the final compliance and tool qualification report. There is also a tendency to add more information into the reports than is required. If the information is not required by the standard, avoid embellishment. Adding extra information is not only a waste of time, but also introduces a risk of delaying an audit process.
The required information that to include in the final report is provided by MISRA Compliance 2016:
- Guideline Enforcement Plan
- Guideline Compliance Summary
- Details of all Approved deviation permits
- Deviation records covering all violations of guidelines re-categorized as Required.
The example below from Parasoft’s tool shows an HTML format, with links to appropriate sections:
Establish the End Goal Early
In addition to the above recommendations, there are a few other important points to consider:
- Has the GRP (Guideline Re-categorization Plan) been established at the beginning of the project? According to the MISRA standard, negotiation with the acquirer is possible, as is the creation of multiple GRP's for the adopted code that is used without any modifications and native code which are the files actively modified during the project.
- For every incremental change, is there visibility into how many items of work are remaining to get to full compliance? This helps to plan the work accordingly and set the right expectations with the management.
- Have the GPS (Guidelines Compliance Summary) report templates been reviewed with the acquirer at the beginning of the project and were they found acceptable and complete?
A Phased Approach: Divide and Conquer
Alhtough the initial scan of existing code by a static analysis tool tends to produce thousands of violations (particularly when using a default set of rules), it's impractical to stop new development efforts to focus on fixing all these violations. In fact, I've seen cases where regressions were introduced when significant changes to the codebase were made to fix the static analysis violations. Therefore, it's important to establish a workflow to fix the violations over time, without disrupting the development process and degrading the quality of the software.
Some key recommendations when using static analysis tools for the first time in a project are stated below:
- Baselining. After the initial scan of the code, mark all the initial violations as “to be addressed later” and set as a baseline. From that point forward when updating existing code and/or developing new code, maintain a policy of "no new violations allowed." This policy can be enforced by the code review process or a Continuous Integration (CI) tool like Jenkins or Bamboo. When developers have a few hour or days to spare, they can resolve remaining violations marked from the baseline. Organizations can prioritize this approach based on current code under development, on code review findings, or by relying on metrics (e.g. complexity) to suggest the next violation to resolve.
- Line in the sand. The development sets a date, “the line in the sand.” After this date, every translation unit (individual source file) modified must have all violations addressed. All unmodified translation units automatically fall under the true “adopted” code definition from the MISRA Compliance document.
- Severity based prioritization. The developer fixes all mandatory findings for the module assigned to them. Over time, they address all Required violations as time permits based on a priority selected by the team lead.
For any of the approaches described above, it’s important for technical leads and management to constantly monitor the progress and project compliance status via a centralized dashboard. For example, Parasoft’s reporting hub provides the following pre-configured compliance status dashboard:
A less obvious component of MISRA compliance, often left till the end of the project, is the recognition that development tools used in the product need to be qualified (proven fit for purpose) for intended use. If a tool needs qualification, what level of validation needs to be performed?
While in many instances tool qualification is required, the method which is used to perform tool qualification varies depending on the risk associated with the tool malfunction and the software criticality level. Parasoft provides a qualification kit and certifications for specific safety standards and their requirements. In the absence of this efficient kit, software teams must consider tool qualification costs when evaluating commercial, free, and open source tools.
Some standards like ISO 26262 and DO-178B/C provide reasonable guidance on tool qualification requirements. Regardless of the method, the goal of the tool qualification process is to state that “Tool is valid for intended use” and provide a proof and rationale of how the team came to this conclusion.
Here are some recommended steps to follow for a tool qualification process:
- Specify tool requirements for your intended use
- Identify a subset of features in the product that are used. Reduce the qualification process to only the features used
- Outline a qualification plan
- Outline the set of qualification steps (which may include tests performed by the team) that verify that the tool meets the requirements
- Automatically execute test cases which can be automated
- Provide a framework to input results of manual testing steps
- Report templates to reduce the amount of text needed to be entered by developers.
- Review the report with stakeholders and sign off.
Overlooking the tool qualification from the start might lead to project delays late in the cycle.
Staff Competency and Training
The expertise and training of development staff is another key factor overlooked by software organizations and frequently being identified by auditors as number one issue when evaluating the readiness of a product.
According to MISRA Guidelines, staff competency is an important part of the MISRA compliance. It's best to conduct training in the beginning of the project and have a training date recorded with all the developers signed off that they received the training. At the end of the project the development team should be able to prove that:
- Staff that approved deviations understands and has been trained to recognized the risks associated with the violation
- Staff has been trained to properly configure and use the static analysis and development tools prior to use.
In practice, training for an experienced team is relatively short, but a few days invested in the beginning of the project saves weeks of rework after a project deadline has been missed.
There is no silver bullet that makes achieving MISRA compliance of legacy code easy in safety-critical projects. However, along with the introduction of the MISRA Compliance 2016 framework, using the practical phased approach with a clearly defined end point in mind, as outlined in this post, software development teams can achieve compliance without significantly disrupting their development process. The bottom line is that there is still a fair amount of work to achieve compliance, but with intelligent planning and the right approach, a minimal and balanced set of tasks can be established to make both legacy and newly developed code safe and secure.
Andrey is a Senior Solution Architect at Parasoft, where he focuses on automated tools and methodologies, working with customers to identify best technical and business approaches for efficient testing of heterogeneous applications.