MISRA C:2012 Rule 18.1
A pointer resulting from arithmetic on a pointer operand shall address an element of the same array as that pointer operand
Description
Rule Definition
A pointer resulting from arithmetic on a pointer operand shall address an element of the same array as that pointer operand.
Rationale
Using an invalid array subscript can lead to erroneous behavior of the program. Run-time derived array subscripts are especially troublesome because they cannot be easily checked by manual review or static analysis.
The C Standard defines the creation of a pointer to one beyond the end of the array. Dereferencing a pointer to one beyond the end of an array causes undefined behavior and is noncompliant.
If you convert a T*
pointer to a
char*
or unsigned
char*
pointer, the bound of the converted pointer
is considered sizeof(T)
. For instance, in this
code, array
accommodates 4
objects of type unsigned
char
.
unsigned int obj = 42; unsigned char *array = (unsigned char*) &obj; unsigned char small_obj = array[3];
Polyspace Implementation
Single objects that are not part of an array are considered arrays of one element. For instance, in this code example,
arr_one
is equivalent to an array of one element. Polyspace® does not flag the increment of pointerptr_to_one
because it points to one past the last element ofarr_one
.void f_incr(int* x){ int* ptr_to_one = x; ++ptr_to_one; // Compliant } void func(){ int arr_one=1; // Equivalent to array of one element f_incr(&arr_one); }
Polyspace does not flag the use of pointer parameters in pointer arithmetic operations when those pointers point to arrays. For instance, in this code snippet, the use of
&a1[2]
inf1
is compliant when you pass an array tof1
.void f1( int* const a1){ int* b= &a1[2]; // Compliant } void f2(){ int arr[3] {}; f1(arr); }
In structures with multiple elements, Polyspace does not flag the result of a pointer arithmetic operation on an element that results in a pointer that points to a different element if the pointer points within the allocated memory of the structure or to one past the last element of the structure.
For instance, in this code snippet, the assignment to
ptr_to_struct
is compliant because it remains insidemyStruct
, even if it points outsidemyStruct.elem1
. Using an index larger than the element dimension to access the content of that element is not compliant, even if the resulting address is within the allocated memory of the structure.void func(){ struct { char elem1[10]; char elem2[10]; } myStruct; char* ptr_to_struct = &myStruct.elem1[11]; //Compliant // Address of myStruct.elem1[11] is inside myStruct char val_to_struct = myStruct.elem1[11]; // Non-compliant }
In multidimensional arrays, Polyspace flags any use of indices that are larger than a subarray dimension to access an element of that subarray. Polyspace does not flag the assignment of the address of that same subarray element if the address is inside the allocated memory of the top-level array.
For example, in this code snippet, the assignment to pointer
ptr_to_arr
is compliant because the pointer points to an address that is within the allocated memory ofmulti_arr
. The assignment to variablearr_val
is not compliant because the index used to access the subarray element (3) is larger than the dimension of the subarray (2).void func(){ int multi_arr[5][2]; // Assigned memory is inside top level array int* ptr_to_arr = &multi_arr[2][3]; //Compliant // Use of index 3 with subarray of size 2 int arr_val = multi_arr[2][3]; // Non-compliant }
Polyspace flags the dereference of a pointer when that pointer points to one past the last element of an array. For instance, in this code snippet, the assignment of
ptr
is compliant, but the dereference ofptr
is not.tab+3
is one past the last element of tab.void derefPtr(){ int tab[3] {}; int* ptr = tab+3; //Compliant int res = *(tab+3); // Non-compliant }
Polyspace does not raise this checker when the result of a pointer arithmetic operation results in
nullptr
. For instance, consider this code:The pointer arithmetic invoid g(int *p); void add(int* p, int n) { g(p + n); //Compliant} void foo() { add(nullptr, 0); }
add()
results in anullptr
. Polyspace does not flag this operation.
Extend Checker
A default Bug Finder analysis might not raise a violation of this rule when the input values are unknown and only a subset of inputs can cause an issue. To check for violations caused by specific system input values, run a stricter Bug Finder analysis. See Extend Bug Finder Checkers to Find Defects from Specific System Input Values.
Troubleshooting
If you expect a rule violation but do not see it, refer to Diagnose Why Coding Standard Violations Do Not Appear as Expected.
Examples
Check Information
Group: Pointers and Arrays |
Category: Required |
AGC Category: Required |