CertC-ARR36¶
Do not subtract or compare two pointers that do not refer to the same array
Required inputs: IR, StaticSemanticAnalysis
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.6 [ ISO/IEC 9899:2011]); the result is the difference of the subscripts of the two array elements. Otherwise, the operation is undefined behavior. (See undefined behavior 48.)
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 48 and
undefined
behavior 53.)
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:
#include <stddef.h>
enum { SIZE = 32 };
void func(void) {
int nums[SIZE];
int end;
int *next_num_ptr = nums;
size_t free_elements;
/* Increment next_num_ptr as array fills */
free_elements = &end - 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 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.
#include <stddef.h>
enum { SIZE = 32 };
void func(void) {
int nums[SIZE];
int *next_num_ptr = nums;
size_t free_elements;
/* Increment next_num_ptr as array fills */
free_elements = &(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.
Risk Assessment
| Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
| ARR36-C | Medium | Probable | Medium | P8 | L2 |
Related Guidelines
| 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 |
Bibliography
| [ Banahan 2003] |
Section 5.3, "Pointers" Section 5.7, "Expressions Involving Pointers" |
| [ ISO/IEC 9899:2011] | 6.5.6, "Additive Operators" |
Possible Messages
Key |
Text |
Severity |
Disabled |
|---|---|---|---|
possible_unrelated_ptr_comparison |
Comparing possibly unrelated pointers |
None |
False |
possible_unrelated_ptr_subtraction |
Subtracting possibly unrelated pointers |
None |
False |
unrelated_ptr_comparison |
Comparing unrelated pointers |
None |
False |
unrelated_ptr_subtraction |
Subtracting unrelated pointers |
None |
False |
Options¶
This rule shares the following common options: exclude_in_macros, exclude_messages_in_system_headers, excludes, extend_exclude_to_macro_invocations, includes, justification_checker, languages, post_processing, provider, report_at, severity
The following places define options that affect this rule: Stylechecks, Analysis-GlobalOptions
check_non_array_pointers¶
check_non_array_pointers : bool = False
report_empty_points_to_sets¶
report_empty_points_to_sets : bool = False