Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Coding style conformance

...

This noncompliant code example shows a function, insert_in_table(), that has two int parameters, pos and value, both of which can be influenced by data originating from untrusted sources. The function performs a range check to ensure that pos does not exceed the upper bound of the array, specified by table_size tableSize, but fails to check the lower bound. Because pos is declared as a (signed) int, this parameter can assume a negative value, resulting in a write outside the bounds of the memory referenced by table.

Code Block
bgColor#ffcccc
langcpp
#include <cstddef>
 
void insert_in_table(int *table, std::size_t table_sizetableSize, int pos, int value) {
  if (pos >= table_sizetableSize) {
    // Handle error
    return;
  }
  table[pos] = value;
}

...

Code Block
bgColor#ccccff
langcpp
#include <cstddef>
 
void insert_in_table(int *table, std::size_t table_sizetableSize, std::size_t pos, int value) {
  if (pos >= table_sizetableSize) {
    // Handle error
    return;
  }
  table[pos] = value;
}

...

Code Block
bgColor#ccccff
langcpp
#include <cstddef>
#include <new>

void insert_in_table(int *table, std::size_t table_sizetableSize, std::size_t pos, int value) { // #1
  if (pos >= table_sizetableSize) {
    // Handle error
    return;
  }
  table[pos] = value;
}

template <std::size_t N>
void insert_in_table(int (&table)[N], std::size_t pos, int value) { // #2
  insert_in_table(table, N, pos, value);
}
 
void f() {
  // Exposition only
  int table1[100];
  int *table2 = new int[100];
  insert_in_table(table1, 0, 0); // Calls #2
  insert_in_table(table2, 0, 0); // Error, no matching function call
  insert_in_table(table1, 100, 0, 0); // Calls #1
  insert_in_table(table2, 100, 0, 0); // Calls #1
  delete [] table2;
}

...

Code Block
bgColor#ffcccc
langcpp
#include <iterator>
 
template <typename ForwardIterator>
void f_imp(ForwardIterator Bb, ForwardIterator Ee, int Valval, std::forward_iterator_tag) {
  do {
    *Bb++ = Valval;
  } while (Bb != Ee);
}

template <typename ForwardIterator>
void f(ForwardIterator Bb, ForwardIterator Ee, int Valval) {
  typename std::iterator_traits<ForwardIterator>::iterator_category Catcat;
  f_imp(Bb, Ee, Valval, Catcat);
}

Compliant Solution

This compliant solution tests for iterator validity before attempting to dereference the forward iterator:

Code Block
bgColor#ccccff
langcpp
#include <iterator>
 
template <typename ForwardIterator>
void f_imp(ForwardIterator Bb, ForwardIterator Ee, int Valval, std::forward_iterator_tag) {
  while (Bb != Ee) {
    *Bb++ = Valval;
  }
}

template <typename ForwardIterator>
void f(ForwardIterator Bb, ForwardIterator Ee, int Valval) {
  typename std::iterator_traits<ForwardIterator>::iterator_category Catcat;
  f_imp(Bb, Ee, Valval, Catcat);
}

Risk Assessment

Using an invalid array or container index can result in an arbitrary memory overwrite or abnormal program termination.

...