Versions Compared

Key

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

Pointer arithmetic is only appropriate when only when the pointer argument refers to an array (see ARR37-C. Do not add or subtract an integer to a pointer to a non-array object), including an array of bytes. When performing pointer arithmetic, the size of the value to add to or subtract to from a pointer is automatically scaled to the size of the type of the referenced array object. Adding or subtracting a scaled integer value to or from a pointer is insecure invalid because it may result in yield a pointer that does not point to an element within or one past the end of the array. This is contraindicated by ARR38(See ARR30-C. Do not add or subtract an integer to a pointer if the resulting value does not refer to a valid array element.form or use out-of-bounds pointers or array subscripts.)

Adding a pointer to an array of a type other than character to the result of the sizeof operator or offsetof macro, which returns a size and an offset, respectively, violates this rule. However, adding an array pointer to the number of array elements, for example, by using the arr Wiki MarkupViolations of this guidelines are indicated when a pointer to an array is added to the result of the {{sizeof}} operator or {{offsetof}} macro which return a size and offset, respectively. However, adding an array pointer to the number of array elements, for example by using the {{arr\[sizeof(arr)/sizeof(arr\[0\])\])}} idiom, is allowed , provided that {{arr}} refers to an array and not a pointer.

Noncompliant Code Example

In this noncompliant code example, the pointer sizeof(buf) is added to sizeof(the array buf). This is  This example is noncompliant because sizeof(buf) is scaled by int and is then scaled again when added to buf.

Code Block
bgColor#FFCCCC
langc
enum { INTBUFSIZE = 80 };

extern int getdata(void);
int buf[INTBUFSIZE];
 
void func(void) {
  int *buf_ptr = buf;

  while (havedata && buf_ptr < (buf + sizeof(buf))) {
    *buf_ptr++ = getdata();
  }
}

Compliant Solution

This compliant solution uses an unscaled integer to obtain a pointer to the end of the array:

Code Block
bgColor#ccccff
langc
enum { INTBUFSIZE = 80 };

extern int getdata(void);
int buf[INTBUFSIZE];

void = parseint(getdata);
}
func(void) {
  int *buf_ptr = buf;

  while (buf_ptr < (buf + INTBUFSIZE)) {
    *buf_ptr++ = getdata();
  }
}

Noncompliant Code Example

In this noncompliant code example, skip is added to the pointer s. However, skip represents the byte offset of ull_2b in struct big. When added to s, skip is scaled by the size of struct big.

Code Block
bgColor#FFCCCC
langc
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
 
struct big {
  unsigned long long ull_1a;
 /* typicallyunsigned 8long bytes */long ull_b;
  unsigned long long ull_2; /* typically 8 bytes */
  unsigned long long ull_3; /* typically 8 bytes */
  int si_4;                 /* typically 4 bytes */
  int si_5;                 /* typically 4 bytes */
};
/* ... */
c;
  int si_e;
  int si_f;
};

void func(void) {
  size_t skip = offsetof(struct big, ull_b);
  struct big *s = (struct big *)malloc(sizeof(struct big));
  if (s == NULL) {
    /* Handle malloc() error */
  }

  memset(s + skip, 0, sizeof(struct big) - skip);
  /* ... */
  free(s);
  s = NULL;
}

Compliant Solution

This compliant solution uses an unsigned char * to calculate the offset instead of using a struct big *, which would result in scaled arithmetic:

Code Block
bgColor#ccccff
langc
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
 
struct big {
  unsigned long long ull_a;
  unsigned long long ull_b;
  unsigned long long ull_c;
  int si_d;
  int si_e;
};

void func(void) {
  size_t skip = offsetof(struct big, ull_2b);
struct  unsigned bigchar *sptr = (structunsigned bigchar *)malloc(
    sizeof(struct big)
  );
  if (!sptr == NULL) {
     /* Handle malloc() error */
  }

  memset(sptr + skip, 0, sizeof(struct big) - skip);
  /* ... */
  free(sptr);
s  ptr = NULL;
}

Noncompliant Code Example

In this noncompliant code example, wcslen(error_msg) * sizeof(wchar_t) bytes are scaled by the size of wchar_t when added to error_msg.:

Code Block
bgColor#FFCCCC
langc
#include <wchar.h>
#include <stdio.h>
 
enum { WCHAR_BUF = 128 };
 
void func(void) {
  /* ... */
wchar_t error_msg[WCHAR_BUF];

  wcscpy(error_msg, L"Error: ");
  fgetws(error_msg + wcslen(error_msg) * sizeof(wchar_t), 
         WCHAR_BUF - 7, stdin);
  /* ... */

Bibliography

}

Compliant Solution

This compliant solution does not scale the length of the string; wcslen() returns the number of characters and the addition to error_msg is scaled:

Code Block
bgColor#ccccff
langc
#include <wchar.h>
#include <stdio.h>

enum { WCHAR_BUF = 128 };
const wchar_t ERROR_PREFIX[7] = L"Error: ";

void func(void) {
  const size_t prefix_len = wcslen(ERROR_PREFIX);
  wchar_t error_msg[WCHAR_BUF];

  wcscpy(error_msg, ERROR_PREFIX);
  fgetws(error_msg + prefix_len,
        WCHAR_BUF - prefix_len, stdin);
  /* ... */
}

Risk Assessment

Failure to understand and properly use pointer arithmetic can allow an attacker to execute arbitrary code.

Rule

Severity

Likelihood

Detectable

Repairable

Priority

Level

ARR39-C

High

Probable

No

No

P6

L2

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V
scaled-pointer-arithmetic

Partially checked

Besides direct rule violations, Astrée reports all (resulting) out-of-bound array accesses.

Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-ARR39Fully implemented
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.MEM.BO
LANG.MEM.BU
LANG.MEM.TBA
LANG.MEM.TO
LANG.MEM.TU
LANG.STRUCT.PARITH
LANG.STRUCT.PBB
LANG.STRUCT.PPE

Buffer overrun
Buffer underrun
Tainted buffer access
Type overrun
Type underrun
Pointer Arithmetic
Pointer before beginning of object
Pointer past end of object

Coverity
Include Page
Coverity_V
Coverity_V

BAD_SIZEOF

 

Partially implemented
Cppcheck Premium

Include Page
Cppcheck Premium_V
Cppcheck Premium_V

premium-cert-arr39-c
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

DF4955, DF4956, DF4957


Klocwork
Include Page
Klocwork_V
Klocwork_V

CERT.ARR.PTR.ARITH


LDRA tool suite
 
Include Page
LDRA_V
LDRA_V
47 S, 489 S, 567 S,
64 X, 66 X, 68 X,
69 X, 70 X, 71 X
Partially implemented
Parasoft C/C++test

Include Page
Parasoft_V
Parasoft_V

CERT_C-ARR39-a
CERT_C-ARR39-b
CERT_C-ARR39-c

Avoid accessing arrays out of bounds
Pointer arithmetic should not be used
Do not add or subtract a scaled integer to a pointer

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule ARR39-C

Checks for incorrect pointer scaling (rule fully covered).

RuleChecker

Include Page
RuleChecker_V
RuleChecker_V

scaled-pointer-arithmetic
Partially checked
TrustInSoft Analyzer

Include Page
TrustInSoft Analyzer_V
TrustInSoft Analyzer_V

index_in_address

Exhaustively detects undefined behavior (see one compliant and one non-compliant example).

Related Vulnerabilities

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

Related Guidelines

Key here (explains table format and definitions)

Taxonomy

Taxonomy item

Relationship

CERT C Secure Coding StandardARR30-C. Do not form or use out-of-bounds pointers or array subscriptsPrior to 2018-01-12: CERT: Unspecified Relationship
CERT C Secure Coding StandardARR37-C. Do not add or subtract an integer to a pointer to a non-array objectPrior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TR 24772:2013Pointer Casting and Pointer Type Changes [HFC]Prior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TR 24772:2013Pointer Arithmetic [RVG]Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012Rule 18.1 (required)Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012Rule 18.2 (required)Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012Rule 18.3 (required)Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012Rule 18.4 (advisory)Prior to 2018-01-12: CERT: Unspecified Relationship
CWE 2.11CWE-468, Incorrect Pointer Scaling2017-07-07: CERT: Exact

Bibliography

[Dowd 2006]Chapter 6, "C Language Issues"
[Murenin 07]


...

Image Added Image Added Image Added Wiki Markup\[[Dowd 06|AA. Bibliography#Dowd 06]\] Chapter 6, "C Language Issues" \[[ISO/IEC PDTR 24772|AA. Bibliography#ISO/IEC PDTR 24772]\] "HFC Pointer casting and pointer type changes" and "RVG Pointer Arithmetic" \[[MISRA 04|AA. Bibliography#MISRA 04]\] Rules 17.1-17.4 \[[MITRE 07|AA. Bibliography#MITRE 07]\] [CWE ID 468|http://cwe.mitre.org/data/definitions/468.html], "Incorrect Pointer Scaling" \[[Murenin 07|AA. Bibliography#Murenin 07]\]