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 operand1 .
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.
According to the C Standard, 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
Polyspace® reports a violation of this rule if:
An array index falls outside the range
[0...array_size-1]
during array access.A pointer is dereferenced outside its bounds.
When checking for violations of this rule, Polyspace takes these factors into consideration:
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.If Polyspace reports a violation of this rule on a pointer or array access, subsequent accesses of the pointer or array are no longer reported. For example, Polyspace reports violation of this rule on the first increment to
pointer2array
. Fixing this violation can also fix the subsequent out-of-bound accesses. If any out-of-bound accesses remain after you fix the reported issue, Polyspace reports those as violations.#include <stdint.h> int32_t data = 0; int32_t simple_array[ 10 ] = { 0 }; void Func(void) { int32_t *pointer2array = &simple_array[ 10 ]; pointer2array++; /* Noncompliant - accessing array out of bound */ data = *pointer2array; /* Noncompliant - pointer out of bounds after increment*/ pointer2array++; /* Violation no longer reported for out of bound access*/ }
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 |
Version History
1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.
The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:
MISRA C:2004
MISRA C:2012
MISRA C:2023
MISRA C++:2008
MISRA C++:2023
MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.