Company:

NASA JPL Industry:

Aerospace Company size:

10,000+ Location:

Pasadena, CA Semmle product(s):

QL, LGTM

In creating technology for NASA JPL’s space and planetary exploration missions, the NASA JPL team relies on Semmle to spot and eliminate mission-critical code problems, such as the crashing bug that could have ended the Curiosity Rovers mission before it had begun.

Introduction From Explorer 1 to the ongoing Mars expeditions, NASA’s Jet Propulsion Laboratory is responsible for many of the most famous and celebrated space and planetary exploration missions the world has seen. Modern space exploration projects require highly specialized software development that works in unison with the custom-made hardware that is built and optimized for each individual space project. Even the smallest flaw in the JPL software can cause the hardware to malfunction or behave unexpectedly, ultimately causing the mission to go up in smoke.

The challenge With hundreds of millions of taxpayer dollars invested in each mission, and groundbreaking scientific endeavors at stake, NASA space missions have no margin for error. Consequently, NASA JPL’s testing process for software is among the most demanding in the world, with extensive standards and rules to be followed without exception by the flight software developers who create the mission software. JPL have good reason for a strict enforcement of their extensive coding standards. Klaus Havelund and Gerard J. Holzmann, leaders of NASA JPL’s Laboratory for Reliable Software (LaRS) at the time of Curiosity’s travel towards Mars, published a paper explaining the motivations for the stringent software certification implemented at NASA. In their paper they write:

We can often point at a mission anomaly or mission loss that was caused by the violation of the underlying principle

Despite rigorous testing and reviewing, serious bugs may surface: When the Curiosity Rover was on its way to Mars in 2012, a flight software developer at NASA JPL discovered a mission-critical bug through manual code review. The problem occurred in Curiosity’s Entry, Descent and Landing software - the software responsible for the rovers descent through the Martian atmosphere and landing it safely on surface of Mars. The bug, which had gone undetected by traditional solutions, was likely to prevent the capsule’s parachutes from opening, resulting in the Rover crashing onto the red planet’s rocky surface. The problem stems from a peculiarity of the C language that allows you to declare parameters to have array types (with stated sizes), but that means nothing: the parameter type degrades to a raw pointer type with no size information.

void fire_thrusters(double vectors[12]) { for (int i = 0; i < 12; i++) { … vectors[i] … } } double thruster[3] = … ; fire_thrusters(thruster); The pseudo code illustrates the problem. The function is declared to take an array of length 12. However, there’s no sanity checking, and a developer might call it with an array that’s too short, holding direction information for only one of the thrusters. The function will then read past the end of the array, and unpredictable results occur.

Patching is still possible mid-flight, but patching the problem would not guarantee the mission. The team needed to know if any variants of the problem existed other places in the code. Why Semmle A while before Curiosity left Planet Earth, Havelund and Holzmann got acquainted with Semmle. They did a thorough assessment of Semmle QL and recognized the value of creating custom analyses to identify variants and implement NASA’s coding standards, and as a result, NASA partnered with Semmle. This soon proved to be of great value to the agency. Once the mission critical bug was discovered on the Curiosity, JPL contacted Semmle for help discovering whether variants of the problem might exist in the Curiosity control software.

In 20 minutes, research engineers from Semmle produced a QL query and shared it with the JPL team.



import cpp from Function f, FunctionCall c, int i, int a, int b where f = c.getTarget() and a = ((ArrayType)c.getArgument(i).getType()).getArraySize() and b = ((ArrayType)f.getParameter(i).getType()).getArraySize() and a < b select c.getArgument(i), "Array of size " + a + " passed to $@, which expects an array of size " + b + ".", f, f.getName() QL query that find the original problem, along with more than30 variants. Complete text of analysis.