When engineering any kind of system, checking for and fixing errors early and often significantly reduces the amount of downstream work added to the project.
In software development, instead of engineering better software in the first place, we often take an approach that tries to test quality into a product through unit or functional testing. To build more quality into your software from the beginning, you can employ static analysis, which is the simplest and most effective activity that software engineers can perform to prevent defects and harden code while accelerating application delivery.
What is Static Code Analysis?
Static code analysis (or static analysis) is a development testing activity in which the code is analyzed for constructs known to be associated with software errors. When a high-risk construct is detected, the static analysis tool reports a violation. There are several types of static analysis, each with its own strengths and weaknesses.
Pattern-Based Static Analysis
In its simplest form, a static analysis tool scans the code and checks it against one or more sets of rules. For example, engineers sometimes make the mistake of using the string "\0" when the null character '\0' is actually intended. This mistake can result in memory corruption and cause the program to crash. A static analysis tool looks for these patterns in the code and reports them as possible errors. This kind of static analysis is known as pattern-based static analysis. Some patterns are simple syntax checkers, akin to a spell-checker when writing. Other patterns can be much more sophisticated and detect patterns associated with subtle problems. This kind of static analysis almost never suffers from false positives.
Modern software engineering standards like Motor Industry Software Reliability Association (MISRA) and Joint Strike Fighter (JSF) are based on the idea that certain constructs should be avoided in code that is safety critical, because of the possibility for that code to have problems.
By providing “safer” alternatives to “unsafe” facilities, known problems with low-level features are avoided. In essence, programs are written in a “safer” subset of a superset.
From Joint Strike Fighter Air Vehicle C++ Coding Standards - Introduction
Flow analysis, sometimes called control-flow or data-flow analysis, is somewhat different. This type of code analysis checks for problematic constructions against a set of rules, while simulating decision paths to dig deeper into the application and root out hard-to-find defects, such as null pointer dereferences, buffer overflows, and security defects such as tainted data. Flow analysis is great in that it can find real bugs, but a certain number of false positives are always part of this method.
Additional Analysis Types
There are other types of static analysis that achieve different types of goals. For example, metrics analysis tools measure code characteristics, such as lines of code and complexity. Coverage analysis tools track unit and application tests to enable a better understanding of how well the code is tested. When used together as part of an automated development testing process, these types of analyses provide significant visibility into the safety, security, and reliability of the application.
Risks of Failing to Run Static Analysis
Software is becoming more and more complex. Today, for example, the average automobile may contain over 1,000 code-executing MCUs and as much as 100 million lines of code! That much electronic surface area, especially in safety-critical applications, such as automotive, medical devices, or avionics, demands a rigorous engineering approach to software in order to approach defect-free code.
The good news is that organizations such as OWASP, CERT, and MITRE are committed to researching and publishing programming best practices to help software engineers succeed. There are also industry-specific standards organizations (such as MISRA, focusing on automotive software), which publish best practices that are often required by regulatory bodies. These best practices can be codified into static analysis tools as rules, that you can choose to implement as part of your organization's policy.
Using a static analysis tool that can implement these programming standards while integrating with your development process is critical. From a business perspective, failing to check your work with at least one static analysis tool significantly raises the risk of deploying or releasing your applications. Defects can lead to exploitable code that malicious hackers can use to crash the system, expose sensitive data, etc. In the case of safety-critical software, the consequences can be far more serious.
Benefits of Automated Static Analysis
Running static analysis on the desktop will provide some benefits and may work on a small team or project; however, in large organizations, static analysis should also be automated as part of nightly builds and continuous integration. When implemented as an integral part of the development process, static analysis provides a number of benefits, including the following:
Faster Development Cycle
Consistently running static analysis from the early stages of the project enables you to find and fix systemic defects when the cost of remediation is at its lowest. The process may initially take more time than rapidly developing the software without running analysis, but the gains in efficiency become exponential over the development lifecycle. Remember that some of the more dangerous errors may be difficult to address late in the cycle, so finding them early is crucial.
Good static analysis tools also include descriptive documentation about the programming standard being implemented, which extends software engineers’ programming knowledge and professional development. Over time, compliance with these standards improves the average quality of the code by improving the programmers through constant feedback. If your static analysis tool is part of a larger development testing platform that can automatically prioritize defect remediation tasks, then you’ll be able to deliver the software even faster.
Lower Defect Rate
Static analysis helps you find and fix defects early, which can prevent the recurrence of systemic defects downstream. With a policy of early detection, you can more easily implement a policy of defect prevention, which reduces the rate of defects over the development lifecycle. (Shameless plug: Parasoft C/C++test, which not only reports static analysis violations, but also integrates with an incredibly sophisticated analytics platform, can give you a broader understanding of all of the instances of the reported defect and its overall impact on the quality of your codebase.)
The term DevOps is often used to describe a collection of practices that facilitate the cross-departmental collaboration and communication necessary to help organizations optimize and accelerate their development and delivery processes. By sharing knowledge and tasks across departments, organizations create an efficient process for accelerating the SDLC while improving quality processes.
For this approach to be effective, however, an automated feedback loop must be implemented that enables the consistent application of quality policies as requirements progress from creation to production.
Automated static analysis is not only the mechanism for the feedback loop, but it also generates the data that other departments need to collaborate effectively under the DevOps model. Especially when used with unit and regression testing, static analysis serves a few roles, including:
- Ensuring code quality
- Providing the big data required to improve the development process
- Facilitating the machinations of the DevOps automated feedback loop
As a result, static analysis becomes an agent for continuous, automated process improvement. It provides a means for examining defects detected during release or QA to determine if there is a way to harden code and eliminate the possibility of these defects occurring in the future.
About Parasoft’s Static Analysis Solution
There are several static analysis tools on the market, ranging from open source utilities to full development testing suites. Parasoft’s development testing solution provides an integrated platform for automating a broad range of software quality practices, while providing meaningful, comprehensive reports and the option for intelligent analytics, powered by Parasoft DTP.
For C and C++, in addition to a full range of static code analysis capabilities and over 2,200 rules (the most of any tool on the market, based on implementations of MISRA, MISRA C++, FDA, Scott Meyers’ Effective C++, Effective STL, and other established sources), Parasoft C/C++test provides a unified solution for your development testing practices. It generates and executes unit tests; enables several types of code coverage, including line, statement, block, path, decision (branch), simple condition, and MC/DC coverage; provides runtime analysis; and comes with a tool qualification kit for complying with functional safety standards.Parasoft also has full static code analysis support for Java with Parasoft Jtest and .NET applications with Parasoft dotTEST. Just like with C and C++, these are fully integrated solutions that provide more than just static analysis, so you get a comprehensive solution to bring efficiency and ease to your software testing. You can analyze code with Parasoft static analysis on the desktop and also integrate it into your automated builds to enable you to prevent defects continuously and automatically.
Static code analysis is an important part of ensuring that applications function as expected. It not only improves the overall development team velocity, but also reduces risks associated with releasing potentially dangerous software. While some analysis is always better than no analysis, static analysis should be integrated into a larger software testing infrastructure to maximize the effectiveness of the practice. Parasoft offers an enterprise-grade code analysis and testing suite in C/C++test, Jtest, and dotTEST, as well as an advanced analytics and reporting system in DTP. Combining these technologies enables software engineering teams to accelerate software delivery, while ensuring that their applications function as expected.