Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: anchor links

The C standard library facilities setjmp() and longjmp() can be used to simulate throwing and catching exceptions. However, these facilities bypass automatic resource management and can result in undefined behavior, commonly including resource leaks, and denial-of-service attacks.

The C++ Standard, [support.runtime], paragraph 4 [ISO/IEC 14882-2014], states:

The function signature longjmp(jmp_buf jbuf, int val) has more restricted behavior in this International Standard. A setjmp/longjmp call pair has undefined behavior if replacing the setjmp and longjmp by catch and throw would invoke any non-trivial destructors for any automatic objects.

Do not call setjmp() or longjmp(); their usage can be replaced by more standard idioms such as throw expressions and catch statements.

Noncompliant Code Example

Calling longjmp() such that it would invoke a nontrivial destructor were the call replaced with a throw expression results in undefined behavior, as demonstrated in this noncompliant code example:

Code Block
bgColor#FFcccc
langcpp
#include <csetjmp>
#include <iostream>

static jmp_buf env;

struct Counter {
  static int instances;
  Counter() { ++instances; }
  ~Counter() { --instances; }
};

int Counter::instances = 0;

void f() {
  Counter c;
  std::cout << "f(): Instances: " << Counter::instances << std::endl;
  std::longjmp(env, 1);
}

int main() {
  std::cout << "Before setjmp(): Instances: " << Counter::instances << std::endl;
  if (setjmp(env) == 0) {
    f();
  } else {
    std::cout << "From longjmp(): Instances: " << Counter::instances << std::endl;
  }
  std::cout << "After longjmp(): Instances: " << Counter::instances << std::endl;
}

Implementation Details

The above code produces the following results when compiled with Clang 3.8 for Linux, demonstrating that the program, on this platform, fails to destroy the local Counter instance when the execution of f() is terminated. This is permissible as the behavior is undefined.

Code Block
Before setjmp(): Instances: 0
f(): Instances: 1
From longjmp(): Instances: 1
After longjmp(): Instances: 1

Compliant Solution

This compliant solution replaces the calls to setjmp() and longjmp() with a throw expression and a catch statement:

Code Block
bgColor#ccccff
langcpp
#include <iostream>

struct Counter {
  static int instances;
  Counter() { ++instances; }
  ~Counter() { --instances; }
};

int Counter::instances = 0;

void f() {
  Counter c;
  std::cout << "f(): Instances: " << Counter::instances << std::endl;
  throw "Exception";
}

int main() {
  std::cout << "Before throw: Instances: " << Counter::instances << std::endl;
  try {
    f();
  } catch (const char *E) {
    std::cout << "From catch: Instances: " << Counter::instances << std::endl;
  }
  std::cout << "After catch: Instances: " << Counter::instances << std::endl;
}

which produces the following output:

Code Block
Before throw: Instances: 0
f(): Instances: 1
From catch: Instances: 0
After catch: Instances: 0

Risk Assessment

Using setjmp() and longjmp() could lead to a denial-of-service attack due to resources not being properly destroyed.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

ERR52-CPP

Low

Probable

Medium

P4

L3

Automated Detection

Tool

Version

Checker

Description

Clang
Include Page
Clang_38_V
Clang_38_V
cert-err52-cppChecked by clang-tidy.
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

BADFUNC.LONGJMP
BADFUNC.SETJMP

Use of longjmp
Use of setjmp
LDRA tool suite
Include Page
LDRA_V
LDRA_V

43 S

Fully implemented

Parasoft C/C++test9.5MISRA2012-RULE-21_4_{a,b}, JSF-020 

PRQA QA-C++

Include Page
PRQA QA-C++_V
PRQA QA-C++_V

Secondary analysis

 

Related Vulnerabilities

Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

Bibliography

[Henricson 97]Rule 13.3, Do not use setjmp() and longjmp()
[ISO/IEC 14882-2014]Subclause 18.10, "Other Runtime Support"