Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

When two pointers are subtracted, both must point to elements of the same array object or to just one past the last element of the array object (C Standard, Section 6.5.6 7 [ISO/IEC 9899:20112024]); the result is the difference of the subscripts of the two array elements. Otherwise, the operation results in is undefined behavior. (See undefined behavior 48  of Appendix J.) This restriction exists because pointer subtraction in C produces the number of objects between the two pointers, not the number of bytes.45.)

...

...

...

Comparing pointers using the equality operators == and != has well-defined semantics regardless of whether or not either of the pointers is null, points into the same object, or points one past the last element of an array object or function.It is acceptable to subtract or compare two member pointers within a single struct object, suitably cast because any object can be treated as an array of unsigned char. However, when doing so remember to account for the effects of alignment and padding on the structure.

Noncompliant Code Example

In this noncompliant code example, pointer subtraction is used to determine how many free elements are left in the nums array.:

Code Block
bgColor#ffcccc
langc
#include <stddef.h>
 
enum { SIZE = 32 };
 
void func(void) {
  int nums[SIZE];
char *strings[SIZE]  int end;
  int *next_num_ptr = nums;
int  size_t free_byteselements;

  /* incrementIncrement next_num_ptr as array fills */

  free_byteselements = strings &end - (char **)next_num_ptr;
}

This program incorrectly assumes that the nums array is adjacent to the end variable in memory. A compiler is permitted to insert padding bits between these two variables or even reorder them in memoryThe first incorrect assumption is that the nums and strings arrays are necessarily contiguous in memory. The second is that free_bytes is the number of bytes available. The subtraction returns the number of elements between next_num_ptr and strings.

Compliant Solution

In this compliant solution, the number of free elements is kept as a counter and adjusted on every array operation. It is also calculated in terms of free elements instead of bytes. This prevents further mathematical errorscomputed by subtracting next_num_ptr from the address of the pointer past the nums array. While this pointer may not be dereferenced, it may be used in pointer arithmetic.

Code Block
bgColor#ccccff
langc
int nums[SIZE];
char *strings#include <stddef.h>
enum { SIZE = 32 };
 
void func(void) {
  int nums[SIZE];
  int *next_num_ptr = nums;
int  size_t free_byteselements;

  /* incrementIncrement next_num_ptr as array fills */

  free_byteselements = (&(nums[SIZE]) - next_num_ptr) * sizeof(int);
}

Exceptions

ARR36-C-EX1: Comparing two pointers within to distinct members of the same struct object is allowed.  
ARR36-EX2: Subtracting two pointers to char within the same object is allowed.  Pointers to structure members declared later in the structure compare greater-than pointers to members declared earlier in the structure.

Risk Assessment

Rule

Severity

Likelihood

Detectable

Remediation Cost

Repairable

Priority

Level

ARR36-C

Medium

medium

Probable

probable

No

medium

No

P8

P4

L2

L3

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V
pointer-subtractionPartially checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-ARR36Can detect operations on pointers that are unrelated
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.STRUCT.CUP

LANG.STRUCT.SUP

Comparison of Unrelated Pointers

Subtraction of Unrelated Pointers

Coverity
Include Page
Coverity_V
Coverity_V

MISRA C 2004 17.2

MISRA C 2004 17.3

MISRA C 2012 18.2

MISRA C 2012 18.3

Implemented
Cppcheck

Include Page
Cppcheck_V
Cppcheck_V

comparePointers
Cppcheck Premium

Include Page
Cppcheck Premium_V
Cppcheck Premium_V

comparePointers
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C0487, C0513

DF2668, DF2669, DF2761, DF2762, DF2763, DF2766, DF2767, DF2768, DF2771, DF2772, DF2773


Klocwork
Include Page
Klocwork_V
Klocwork_V

MISRA.PTR.ARITH


LDRA tool suite
Include Page
LDRA_V
LDRA_V

437 S, 438 S

Fully implemented

PRQA QA-C Include PagePRQA_VPRQA_V

0487
2771

Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V
CERT_C-ARR36-a
CERT_C-ARR36-b

Do not subtract two pointers that do not address elements of the same array
Do not compare two unrelated pointers

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule ARR36-C

Checks for subtraction or comparison between pointers to different arrays (rule partially covered)

PVS-Studio

Include Page
PVS-Studio_V
PVS-Studio_V

V736, V782
RuleChecker
Include Page
RuleChecker_V
RuleChecker_V
pointer-subtraction
Partially checked
Security Reviewer - Static Reviewer
6.02
C24
C107
Fully Implemented
TrustInSoft Analyzer

Include Page
TrustInSoft Analyzer_V
TrustInSoft Analyzer_V

differing_blocks

Exhaustively verified (see the compliant and the non-compliant example).

Fully implemented

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 Standard
ARR36
CTR54-CPP. Do not subtract
or compare two pointers or
iterators that do not refer to the same
array or container
containerPrior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TS 17961
 (Draft)
Subtracting or comparing two pointers that do not refer to the same array [ptrobj]
MITRE CWE
Prior to 2018-01-12: CERT: Unspecified Relationship
CWE 2.11CWE-469, Use of Pointer Subtraction to Determine Size

2017-07-10: CERT: Exact

CWE 3.11CWE-469, Use of
pointer subtraction to determine size
Pointer Subtraction to Determine Size2018-10-18:CERT:CWE subset of rule

CERT-CWE Mapping Notes

Key here for mapping notes

CWE-469 and ARR36-C

CWE-469 = Subset(ARR36-C)

ARR36-C = Union(CWE-469, list) where list =

  • Pointer comparisons using the relational operators <, <=, >=, and >, where the pointers do not refer to the same array

Bibliography

...

[ISO/IEC 9899:2024]

6.5.7, "Additive Operators"


...

Image Modified Image Modified Image Modified