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

Compare with Current View Page History

« Previous Version 30 Next »

It is only appropriate to perform arithmetic on pointers to elements of array objects.

C99, Section 6.5.6, has the following to say about pointer arithmetic:

When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression.

Noncompliant Code Example

In this noncompliant code example, the programmer tries to access elements of the structure using pointer arithmetic. This is dangerous because fields in a structure are not guaranteed to be contiguous.

struct numbers {
  int num1;
  int num2;
  /* . . . */
  int num9;
};

int sum_numbers(const struct numbers *numb){
  int total = 0;
  const int *numb_ptr;

  for (numb_ptr = &numb->num1; 
       numb_ptr <= &numb->num3; 
       numb_ptr++) 
  {
    total += *(numb_ptr);
  }

  return total;
}

int main(void) {
  struct numbers my_numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9  };
  sum_numbers(&my_numbers);
  return 0;
}

Compliant Solution

It is possible to use the -> operator to dereference each element of the structure; for example:

total = numb->num1 + numb->num2 + /* ... */ numb->num9;

However, this is likely to be exactly the sort of painful experience the programmer who wrote the noncompliant code example was trying to avoid.

A better solution is to use an array, as in this compliant solution:

int sum_numbers(const int *numb, size_t dim) {
  int total = 0;
  const int *numb_ptr;

  for (numb_ptr = numb; numb_ptr < numb + dim; numb_ptr++) {
    total += *(numb_ptr);
  }

  return total;
}

int main(void) {
  int my_numbers[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  sum_numbers(
    my_numbers, 
    sizeof(my_numbers)/sizeof(my_numbers[0])
  );
  return 0;
}

Array elements are guaranteed to be contiguous in memory, so this solution is completely portable.

Risk Assessment

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

ARR37-C

medium

probable

medium

P8

L2

Automated Detection

Compass/ROSE can detect simple violations of this rule.

Related Vulnerabilities

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

Other Languages

This rule appears in the C++ Secure Coding Standard as ARR37-CPP. Do not add or subtract an integer to a pointer to a non-array object.

References

[[Banahan 03]] Section 5.3, "Pointers," and Section 5.7, "Expressions involving pointers"
[[ISO/IEC 9899:1999]] Section 6.5.6, "Additive operators"
[[MITRE 07]] CWE ID 469, "Use of Pointer Subtraction to Determine Size"
[[VU#162289]]


      06. Arrays (ARR)       ARR38-C. Do not add or subtract an integer to a pointer if the resulting value does not refer to a valid array element

  • No labels