Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The C Language standard library facilities setjmp() and longjmp() can be used to simulate the throwing and catching of exceptions, but they are very low-level facilities, and using them can bypass proper resource management and the proper calling of destructors. 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-2003, section 18.7 paragraph 4. says2014], states the following:

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

Non-Compliant Code Example

Calling longjmp() prevents local class variables from being properly destroyed, as can be demonstrated by the following code:

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

If a throw expression would cause a nontrivial destructor to be invoked, then calling longjmp() in the same context will result in undefined behavior. In the following noncompliant code example, the call to longjmp() occurs in a context with a local Counter object. Since this object’s destructor is nontrivial, undefined behavior results.

Code Block
bgColor#FFcccc
langcpp
Code Block
bgColor#ccccff

#include <csetjmp>
#include <iostream>
using namespace std;

static jmp_buf env;

classstruct Counter {
public:
  static int Instancesinstances;

  Counter() {Instances ++instances; }
  ~Counter() {Instances --instances; }
private:
  Counter(const Counter& that);
  Counter& operator=(const Counter& that);
};

int Counter::Instancesinstances = 0;
class Error {};

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

int main() {

  std::cout << "Before setjmp(): Instances: " << Counter::Instancesinstances << std::endl;
  if (setjmp(env) == 0) {
    funcf();
  } else {
    std::cout << "From longjmp(): Instances: " << Counter::Instancesinstances << std::endl;
  }

  std::cout << "After longjmp(): Instances: " << Counter::Instancesinstances << std::endl;
}

Implementation Details

The above code produces the following results when compiled with Clang 3.8 for Linux, on a Linux machine running g++ 4.3: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
Code Block

Before setjmp(): Instances: 0
funcf(): Instances: 1
From longjmp(): Instances: 1
After longjmp(): Instances: 1

Since the C++ standard leaves this behavior undefined, the compiler merely fails to invoke the destructor for the Counter object.

Compliant Solution

Use exceptions instead of This compliant solution replaces the calls to setjmp() and and longjmp(), as throwing exceptions will still invoke destructors of local class variables with a throw expression and a catch statement.

Code Block
bgColor#ccccff
langcpp

#include <iostream>
using namespace std;

class
struct Counter {
public:
  static int Instancesinstances;

  Counter() {Instances ++instances; }
  ~Counter() {Instances --instances;}
private:
  Counter(const Counter& that);
  Counter& operator=(const Counter& that); }
};

int Counter::Instancesinstances = 0;
class Error {};

void funcf() {
  Counter c;
  std::cout << "funcf(): Instances: " << Counter::Instancesinstances << std::endl;
  throw Error()"Exception";
}

int main() {

  std::cout << "Before trythrow: Instances: " << Counter::Instancesinstances << std::endl;
  try {
    funcf();
  } catch (...const char *E) {
    std::cout << "InFrom catch: Instances: " << Counter::Instancesinstances << std::endl;
  }

  std::cout << "After catch: Instances: " << Counter::Instancesinstances << std::endl;
}

On the same platform (Linux, g++ 4.3), this code produces:This solution produces the following output.

Code Block

Before trythrow: Instances: 0
funcf(): Instances: 1
InFrom catch: Instances: 0
After catch: Instances: 0

...

ERR34-EX1: The longjmp() function may be safely invoked if you can guarantee that no nontrivial destructors are bypassed between the longjmp() call and the corresponding setjmp().

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

RES39

ERR52-

C

1 (low)

2 (probable)

2 (medium)

CPP

Low

Probable

Medium

P4

L3

References

Wiki Markup
\[[ISO/IEC 14882-2003|AA. C++ References#ISO/IEC 14882-2003]\] Section 18.7
\[[Henricson 97|AA. C++ References#Henricson 97]\] Rule 13.3 Do not use {{setjmp()}} and {{longjmp()}}.

Automated Detection

Tool

Version

Checker

Description

Astrée

Include Page
Astrée_V
Astrée_V

include-setjmp
Fully checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC++-ERR52
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
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C++5015
Klocwork
Include Page
Klocwork_V
Klocwork_V
MISRA.STDLIB.LONGJMP
LDRA tool suite
Include Page
LDRA_V
LDRA_V

43 S

Fully implemented

Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_CPP-ERR52-a
CERT_CPP-ERR52-b

The facilities provided by <setjmp.h> should not be used
The standard header files <setjmp.h> or <csetjmp> shall not be used

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C++: ERR52-CPPChecks for use of setjmp/longjmp (rule fully covered)
RuleChecker
Include Page
RuleChecker_V
RuleChecker_V
include-setjmp
Fully checked
SonarQube C/C++ Plugin
Include Page
SonarQube C/C++ Plugin_V
SonarQube C/C++ Plugin_V
S982

Related Vulnerabilities

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

Bibliography

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


...

Image Added Image Added Image Added MSC16-CPP. Consider encrypting function pointers      49. Miscellaneous (MSC)      MSC18-CPP. Finish every set of statements associated with a case label with a break statement