Software Standards Compliance 101: Implementing a programming standard

In the mid-1990s, a formal investigation was conducted into a series of fatal accidents with the Therac-25 radiotherapy machine. Led by Nancy Leveson of the University of Washington, the investigation resulted in a set of recommendations on how to create safety-critical software solutions in an objective manner. Since then, industries as disparate as aerospace, automotive and industrial control have encapsulated the practices and processes for creating safety- and/or security-critical systems in an objective manner into industry standards.

Although subtly different in wording and emphasis, the standards across industries follow a similar approach to ensuring the development of safe and/or secure systems. This common approach includes ten phases:

  1. Perform a system safety or security assessment
  2. Determine a target system failure rate
  3. Use the system target failure rate to determine the appropriate level of development rigor
  4. Use a formal requirements capture process
  5. Create software that adheres to an appropriate coding standard
  6. Trace all code back to their source requirements
  7. Develop all software and system test cases based on requirements
  8. Trace test cases to requirements
  9. Use coverage analysis to assess test completeness against both requirements and code
  10. For certification, collect and collate the process artifacts required to demonstrate that an appropriate level of rigor has been maintained.

Phase 5 is discussed in the main body of this article. A key topic in creating safe and secure systems is building quality and security into software. This is done by adopting an enforceable coding standard that has the additional benefit of greatly reducing the cost of development, especially when it comes to meeting corporate and/or industry software quality, safety and security requirements.


Incorporating appropriate coding standards into software development serves to reduce defects by building quality into the software as it is being written. The challenge in identifying a solution hinges on the fact that quality means different things in different applications. It’s the consequences or impact of software failure that defines the level of quality needed. For example, the huge settlement Toyota recently made in response to the “unintended acceleration” lawsuit that was decided against it came because Toyota’s software failure resulted in multiple deaths. In contrast, a software security failure typically only results in lost money. Cloudfare recently announced that the remediation costs associated with the Open SSL “Heartbleed” vulnerability cost them many millions of dollars.

Companies adopt and apply coding standards to mitigate these types of software defect as the software is being written. Coding standards encapsulate a governing organization’s wisdom and years of expertise and experience programming in a given language for a given domain and provide guidance for the creation of good code.

At their most basic, programming standards help to ensure the consistency of new code, and that the code output from one developer can be read by any other developer in the organization, facilitating code reviews and downstream maintenance. This is especially beneficial during the defect identification and isolation process, assisting in the reduction of latent defects and therefore lowering overall software costs. Programming standards can also help organizations avoid areas of significant programming risk by improving the overall quality of the code and avoiding the “undefined behaviors” associated with certain language semantics.

How Do the Errors Get Started?
One of the most revered and widely used programming languages in use today, the C programming language was originally designed as a lightweight language with a small footprint. However, C’s flexibility carries some inherent risks. For instance, multiple versions of an international C language standard have been ratified, with the latest in 2011 (C11). All versions identify specific language semantics referred to as “undefined behavior,” described in C11 as:

Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

Not only does the list of undefined behavior semantics change from version to version, the implementation also changes from compiler to compiler. Many programmers use these undefined behaviors to optimize their application for a specific platform where the code is compiled with a particular version of the compiler. However, if you compile the code for another platform or using a different compiler, these optimizations may result in defects.

Now add C++, Ada, Java, and the multitude of other languages being used in projects today, and the areas of risk increase exponentially. Not all of these languages display the same type of undefined behaviors that C does, but they all have risks associated with their use. Implementing coding standards encapsulate the risks inherent to domain-specific applications.

Given that most safety-critical devices are designed to be fail-safe (i.e., when failures do occur, they are detected and the system responds to them in a manner that ensures the safety of the users), there’s no room for these kinds of “undefined behaviors.” And, even security-critical applications have no room for these kinds of errors since failures can be the way that system vulnerabilities are exploited. While the level of risk associated with creating a safety-critical device is not the same as the level of risk associated with creating a secure device with security, the lines are blurring as more and more devices become network-enabled. Bottomline: Safe software cannot exist with undefined behavior.

Next page >>

Standards Aimed at Correcting Programming Errors
So what programming standards are available? As interest in the topic heats up, the publication of programming standards has surged over the past 10 years resulting in this long list:

Name

Programming Language

Date of Most Recent Version

Description

secureC

C

2013

C Secure Coding Rules (ISO/IEC 17961:2013). A set of rules regarding the creation of secure code in the C programming language.

CERT C

C

2013

Secure Coding Standard from the Computer Emergency Response Team (CERT) Division of the Software Engineering Institute at Carnegie Mellon University that provides rules and recommendations (collectively called guidelines) for secure coding in the C programming language.

MISRA-C

C

2012

A Motor Industry Software Reliability Association (MISRA) standard that enables developers to take advantage of most ISO C programming language features while helping them mitigate risk for safety-critical automotive, medical, industrial or mil/aero applications.

Embedded C Coding Standard

C

2011

Designed to help minimize bugs in firmware, this Barr Group coding standard details a set of guidelines for the use of specific C language concepts such as data types, functions, preprocessor macros, and variables.

JPL

C

2009

Jet Propulsion Laboratory Institutional Coding Standard. Based on MISRA-2004 and the rules laid out in an article entitled “The Power of 10: Rules for Developing Safety-Critical Code,” IEEE Computer, June 2006, pp. 93-95, this standard collects the best available insights for improving the safety and reliability of code written in the C Programming language and extends them to address the risks related to the use of multi-threaded software.

CERT C++

C++

2013

This CERT Secure Coding Standard provides guidelines for secure coding in the C++ programming language.

MISRA-C++

C++

2008

MISRA standard that enables developers to take advantage of most ISO C++ programming language features while helping them mitigate risk for safety-critical automotive, medical, industrial or mil/aero applications.

CERT Java

Java

2011

This CERT Secure Coding Standard provides guidelines for secure coding in the Java programming language.

CERT Perl

Perl

Under development

This CERT Secure Coding Standard provides guidelines for secure coding in the Perl programming language.

Spark Ada Subset

Ada

2014

A subset of the Ada programming language intended for the development of high-integrity software helps developers mitigate risk for systems where predictable and highly reliable operation is essential.

Ravenscar Profile

Ada

2005

A subset of the Ada programming language includes tasking features designed for safety-critical, hard real-time computing. It’s now incorporated into the Ada 2005 Standard.

Common Weakness Enumeration

Multiple

2014

The Common Weakness Enumeration (CWE) dictionary is a formal list of common software weaknesses that have been known to occur in software’s architecture, design, code or implementation that can lead to exploitable security vulnerabilities. Software weaknesses are flaws, faults, bugs, vulnerabilities, and other errors in software implementation, code, design, or architecture that if left unaddressed could result in systems and networks being vulnerable to attack.

Implementing the Chosen Standard
Once a project/company chooses a coding standard, they need to balance the strictness of the guidelines against the effort required to follow them. Strict enforcement of a coding standard may be idealistically desirable, but it’s not always practical. Some products can effectively use a subset of the guidelines to better meet project cost without compromising reliability and safety and security requirements.

A programming standard needs to allow some flexibility so that deviations can occur in a controlled way. Decisions around flexibility and tradeoffs should be made early enough that deviations can be analyzed and determined, and rules established that define the appropriate use of that deviation throughout the project team.

While it is possible to enforce coding standards via manual inspection, this process is not only slow and inefficient, but it is also not consistent or rigorous enough to uncover the variety of defects that can result in a safety or security vulnerability. In practice, coding standards are never fully implemented unless they are automated. The larger and more complex the software applications, the more impossible manual inspection becomes. As a result, coding standards are best enforced by the use of static analysis tools, which help to identify both known and unknown vulnerabilities while also eliminating latent errors in code (see Figure 1). Additionally, the use of these tools helps to ensure that even novice secure software developers can benefit from the experience and knowledge encapsulated within the standards.

click for larger image

Figure 1: An automated check via software is the only way to efficiently and reliably check the compliance of code to a particular programming standard. LDRA TBvision displays the results of code checked for MISRA compliance using static analysis.
 (Source: LDRA)

Static code analysis tools parse through the code under development and help to identify sections of code that do not comply with the programming standard. The more advanced static analysis tools go beyond the simple semantic parsing of the code and consider the code in context, helping to introduce new programming standard concepts. For instance, advanced static analysis tools, such as those pictured in Figure 2, can be used to help identify the following issues that can compromise code quality, and should be considered for inclusion by any organization seeking to adopt a coding standard:

  • Areas of excess code complexity
  • Unreachable code
  • Unintentional data coupling

Notably, programming standards don’t make code testing redundant. Defects can stem from higher-level process issues, such as requirements misinterpretation, just as much from coding errors.

click for larger image

Figure 2: Overly complex code is harder to debug, maintain, and port. Advanced static analysis tools, such as LDRA tool suite, not only can apply programming standards, but provide code complexity metrics that help development teams deliver better quality code that is less likely to break. (Source: LDRA)

In the next articles in this series, we’ll reach beyond the code to look at how to build processes that are also bullet proof.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.