You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

The range of valid enumeration values for an enumeration type is defined as follows in the C++ Working Draft Standard:

For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the
underlying type. Otherwise, for an enumeration where emin is the smallest enumerator and emax is the
largest, the values of the enumeration are the values in the range bmin to bmax, defined as follows: Let K
be 1 for a two’s complement representation and 0 for a one’s complement or sign-magnitude representation.
bmax is the smallest value greater than or equal to max(|emin| ? K, |emax|) and equal to 2^M ? 1, where
M is a non-negative integer. bmin is zero if emin is non-negative and ?(bmax + K) otherwise. The size of
the smallest bit-field large enough to hold all the values of the enumeration type is max(M, 1) if bmin is
zero and M + 1 otherwise. It is possible to define an enumeration that has values not defined by any of its
enumerators. If the enumerator-list is empty, the values of the enumeration are as if the enumeration had a
single enumerator with value 0.

According to the same standard, when converting an arithmetic or enumeration type to an enumeration type, the value will be unchanged if it is in the range of enumeration values of the enumeration type. Otherwise, the value is unspecified.

Therefore, to avoid unexpected behavior, the value being converted must be inside of the range of enumeration values. Futhermore, if it is necessary to check for out-of-range values dynamically, it must be done before the conversion.

Noncompliant Code Example (Bounds checking)

This noncompliant code exmample is trying to check for an out-of-bounds condition. However, it is doing so after the conversion, so the result of the conversion is unspecified and the statement may have no effect.

enum et1 {
  E_A,
  E_B
};

int i1 = -1;
et1 e1 = static_cast<et1>(i1);

if(e1 < 0) {
  /* error condition */
}

Compliant code example (Bounds checking)

This compliant solution checks for an out-of-bounds condition before the conversion to guarantee there is no unspecified result.

enum et1 {
  E_A,
  E_B
};

int i1 = -1;

if(i1 < 0 || i1 > E_C) {
  /* error condition */
}

et1 e1 = static_cast<et1>(i1);

Noncompliant Code Example (Switch-statement)

This noncompliant code may result in a truncation of the value of i1 when converted to type et1, thus causing the program to execute case E_A.

enum et1 {
  E_A,
  E_B
};

int i1 = 5;

switch(static_cast<et1>(i1)) {
  case E_A:
    /* some action A */
  case E_B:
    /* some action B */
}

Compliant Code Example (Switch-statement)

This compliant solution checks for an out-of-bounds condition before the conversion to guarantee there is no unspecified values, and therefore, no truncation.

enum et1 {
  E_A,
  E_B
};

int i1 = 5;

if(i1 < 0 || i1 > E_C) {
  /* error condition */
}

switch(static_cast<et1>(i1)) {
  case E_A:
    /* some action A */
  case E_B:
    /* some action B */
}

Risk Assessment

Unexpected behavior can lead to a buffer overflow and the execution of arbitrary code by an attacker.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

INT36-CPP

high

probable

high

P6

L2

References

Todo.

  • No labels