Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: REM Cost Reform

...

This noncompliant code example attempts to determine whether the pointer test is within the range [r, r + n]. However, when test does not point within the given range, as in this example, it results undefined the subtraction produces undefined behavior.

Code Block
bgColor#ffcccc
langcpp
#include <cstddef>
#include <iostream>
 
template <typename Ty>
bool in_range(const Ty *test, const Ty *r, size_t n) {
  return 0 < (test - r) && (test - r) < (std::ptrdiff_t)n;
}
 
void f() {
  double foo[10];
  double *x = &foo[0];
  double bar;
  std::cout << std::boolalpha << in_range(&bar, x, 10);
}

...

In this noncompliant code example, the in_range() function is implemented using a comparison expression instead of subtraction. The C++ Standard, [expr.rel], paragraph 4 [ISO/IEC 14882-2014], states the following:

If two operands p and q compare equal, p<=q and p>=q both yield true and p<q and p>q both yield false. Otherwise, if a pointer p compares greater than a pointer q, p>=q, p>q, q<=p, and q<p all yield true and p<=q, p<q, q>=p, and q>p all yield false. Otherwise, the result of each of the operators is unspecified.

Page properties
hiddentrue

The "Thus" statement below is incomplete. What is required to make such a statement is p3, which is a total mess because it doesn't say WHAT should happen when two pointers not of the same container are compared. The assumption is that this is what causes us to fall into the final "otherwise" clause of p4, but I think a core issue may be in order. Once that is resolved, we can update this section accordingly.

...

This noncompliant code example is roughly equivalent to the previous example, except that it uses iterators in place of raw pointers. As with the previous example, the in_range_impl() function exhibits unspecified behavior when the iterators do not refer into the same container because the operational semantics of a < b on a random access iterator are b - a > 0, and >= is implemented in terms of <.

Code Block
bgColor#ffcccc
langcpp
#include <iostream>
#include <iterator>
#include <vector>

template <typename RandIter>
bool in_range_impl(RandIter test, RandIter r_begin, RandIter r_end, std::random_access_iterator_tag) {
  return test >= r_begin && test < r_end;
}
 
template <typename Iter>
bool in_range(Iter test, Iter r_begin, Iter r_end) {
  typename std::iterator_traits<Iter>::iterator_category Catcat;
  return in_range_impl(test, r_begin, r_end, Catcat);
}
 
void f() {
  std::vector<double> foo(10);
  std::vector<double> bar(1);
  std::cout << std::boolalpha << in_range(bar.begin(), foo.begin(), foo.end());
}

...

In this noncompliant code example, std::less<> is used in place of the < operator. The C++ Standard, [comparisons], paragraph 14 [ISO/IEC 14882-2014], states the following:

For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.

...

Code Block
bgColor#ffcccc
langcpp
#include <functional>
#include <iostream>
 
template <typename Ty>
bool in_range(const Ty *test, const Ty *r, size_t n) {
  std::less<const Ty *> less;
  return !less(test, r) && less(test, r + n);
}
 
void f() {
  double foo[10];
  double *x = &foo[0];
  double bar;
  std::cout << std::boolalpha << in_range(&bar, x, 10);
}

Compliant Solution

In this This compliant solution , demonstrates a fully portable, but likely inefficient equality comparing , implementation of in_range() that compares test against each possible address in the range [r, n] is used to implement the in_range() function:. A compliant solution that is both efficient and fully portable is currently unknown.

Code Block
bgColor#ccccff
langcpp
#include <iostream>
 
template <typename Ty>
bool in_range(const Ty *test, const Ty *r, size_t n) {
  auto *cur = reinterpret_cast<const unsigned char *>(r);
  auto *end = reinterpret_cast<const unsigned char *>(r + n);
  auto *test_ptrtestPtr = reinterpret_cast<const unsigned char *>(test);
 
  for (; cur != end; ++cur) {
    if (cur == test_ptrtestPtr) {
      return true;
    }
  }
  return false;
}
 
void f() {
  double foo[10];
  double *x = &foo[0];
  double bar;
  std::cout << std::boolalpha << in_range(&bar, x, 10);
}

Risk Assessment

Rule

Severity

Likelihood

Detectable

Remediation Cost

Repairable

Priority

Level

CTR54-CPP

Medium

Probable

No

Medium

No

P8

P4

L2

L3

Automated Detection

Tool

Version

Checker

Description

PRQA QA-C++

Include PagePRQA QA-C++_vPRQA QA-C++_v

2761, 2762, 2763,   
2766,
2767, 2768,
2771, 2772, 2773

Astrée

Include Page
Astrée_V
Astrée_V

invalid_pointer_subtraction
invalid_pointer_comparison

CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.STRUCT.CUP
LANG.STRUCT.SUP

Comparison of Unrelated Pointers
Subtraction of Unrelated Pointers

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

DF2668, DF2761, DF2762, DF2763, DF2766, DF2767, DF2768


LDRA tool suite
Include Page
LDRA_V
LDRA_V

70 S, 87 S, 437 S, 438 S

Enhanced Enforcement

Parasoft C/C++test

Include Page
Parasoft_V
Parasoft_V

CERT_CPP-CTR54-a
CERT_CPP-CTR54-b
CERT_CPP-CTR54-c

Do not compare iterators from different containers
Do not compare two unrelated pointers
Do not subtract two pointers that do not address elements of the same array

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C++: CTR54-CPPChecks for subtraction or comparison between iterators from different containers (rule partially covered).
 

Related Vulnerabilities

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

Related Guidelines

Bibliography

[Banahan
03
2003]Section 5.3, "Pointers"
Section 5.7, "Expressions Involving Pointers" 
[ISO/IEC 14882-2014]

Subclause 5.7, "Additive Operators"
Subclause 5.9, "Relational Operators"
Subclause 20.9.5, "Comparisons"

...


...

Image Modified Image Modified Image Modified