| Warning | ||
|---|---|---|
| ||
This is new rule and not yet ready for review. |
When two pointers are subtracted, both must point to elements of the same array object , or just one past the last element of the array object (C Standard, 6.5.7 [ISO/IEC 9899:2024]); the result is the difference of the subscripts of the two array elements. This restriction exists because pointer subtraction in C produces the number of objects between the two pointers, not the number of bytes.Similarly comparing pointers can tell you the relative positions of the pointers in term of Otherwise, the operation is undefined behavior. (See undefined behavior 45.)
Similarly, comparing pointers using the relational operators <, <=, >=, and > gives the positions of the pointers relative to each other. Subtracting or comparing pointers
...
that do not refer to the same array
...
is undefined behavior. (See undefined behavior 45 and undefined behavior 50.
...
)
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.
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 | ||||
|---|---|---|---|---|
| ||||
#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; /*perform operations onIncrement next_num_ptr as array fills */ free_byteselements = strings &end - next_num_ptr; |
In this non-compliant code example pointer subtraction is used to determine how many free elements are left in the nums array. The first incorrect assumption is that nums and strings arrays will be next to each other in memory. The second is that free_bytes will be the number of bytes available. The subtraction will return the number of elements between next_num_ptr and strings.
} |
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 memory.
Compliant Solution
In this compliant solution, the number of free elements is computed 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 | ||||
|---|---|---|---|---|
| ||||
#include <stddef.h> enum { SIZE = 32 }; void func(void) { int nums nt nums[SIZE]; char *strings[SIZE]; int *next_num_ptr = nums; int size_t free_elements =SIZE; /*perform operationsIncrement on next_num_ptr as array fills */ decrement free_elements as it fills */ = &(nums[SIZE]) - next_num_ptr; } |
Exceptions
ARR36-C-EX1: Comparing two pointers to distinct members of the same struct object is allowed. Pointers to structure members declared later in the structure compare greater-than pointers to members declared earlier in the structure.In the 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 if bytes. This prevents further mathematical errors.
Risk Assessment
Rule | Severity | Likelihood |
|---|
Detectable | Repairable | Priority | Level | |||
|---|---|---|---|---|---|---|
ARR36-C | Medium | Probable | No | No | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Astrée |
| pointer-subtraction | Partially checked | ||||||
| Axivion Bauhaus Suite |
| CertC-ARR36 | Can detect operations on pointers that are unrelated | ||||||
| CodeSonar |
| LANG.STRUCT.CUP LANG.STRUCT.SUP | Comparison of Unrelated Pointers |
2 (medium)
2 (probable)
2 (medium)
P6
L2
Subtraction of Unrelated Pointers | |||||||||
| Coverity |
| MISRA C 2004 17.2 MISRA C 2004 17.3 MISRA C 2012 18.2 MISRA C 2012 18.3 | Implemented | ||||||
| Cppcheck |
| comparePointers | |||||||
| Cppcheck Premium |
| comparePointers | |||||||
| Helix QAC |
| C0487, C0513 DF2668, DF2669, DF2761, DF2762, DF2763, DF2766, DF2767, DF2768, DF2771, DF2772, DF2773 | |||||||
| Klocwork |
| MISRA.PTR.ARITH | |||||||
| LDRA tool suite |
| 437 S, 438 S | Fully implemented | ||||||
| Parasoft C/C++test |
| CERT_C-ARR36-a CERT_C-ARR36-b | Do not subtract two pointers that do not address elements of the same array | ||||||
| Checks for subtraction or comparison between pointers to different arrays (rule partially covered) | ||||||||
| PVS-Studio |
| V736, V782 | |||||||
| RuleChecker |
| pointer-subtraction | Partially checked | ||||||
| Security Reviewer - Static Reviewer | 6.02 | C24 C107 | Fully Implemented | ||||||
| TrustInSoft Analyzer |
| differing_blocks | Exhaustively verified (see the compliant and the non-compliant example). |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
| Wiki Markup |
|---|
\[[Banahan 03|AA. C References#Banahan 03]\] [Section 5.3, "Pointers,"|http://publications.gbdirect.co.uk/c_book/chapter5/pointers.html] and [Section 5.7, "Expressions involving pointers"|http://publications.gbdirect.co.uk/c_book/chapter5/pointer_expressions.html]
\[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.5.6, "Additive operators" |
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
|---|---|---|
| CERT C | CTR54-CPP. Do not subtract iterators that do not refer to the same container | Prior to 2018-01-12: CERT: Unspecified Relationship |
| ISO/IEC TS 17961 | Subtracting or comparing two pointers that do not refer to the same array [ptrobj] | Prior to 2018-01-12: CERT: Unspecified Relationship |
| CWE 2.11 | CWE-469, Use of Pointer Subtraction to Determine Size | 2017-07-10: CERT: Exact |
| CWE 3.11 | CWE-469, Use of Pointer Subtraction to Determine Size | 2018-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
| [Banahan 2003] | Section 5.3, "Pointers" Section 5.7, "Expressions Involving Pointers" |
| [ISO/IEC 9899:2024] | 6.5.7, "Additive Operators" |
...
ARR35-C. Do not allow loops to iterate beyond the end of an array 06. Arrays (ARR)