Main Content

AUTOSAR C++14 Rule M5-0-16

A pointer operand and any pointer resulting from pointer arithmetic using that operand shall both address elements of the same array

Since R2021a

Description

Rule Definition

A pointer operand and any pointer resulting from pointer arithmetic using that operand shall both address elements of the same array.

Rationale

It is undefined behavior when the result of a pointer arithmetic operation that uses a pointer to an array element does not point to either:

  • An element of the array.

  • One past the last element of the array. For instance:

    int arr[3];
    int* res;
    res = arr+3; // res points to one beyond arr

The rule applies to these operations. ptr is a pointer to an array element and int_exp is an integer expression.

  • ptr + int_exp

  • int_exp + ptr

  • ptr - int_exp

  • ptr + +

  • ++ptr

  • --ptr

  • ptr--

  • ptr [ int_exp ]

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 pointer ptr_to_one because it points to one past the last element of arr_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] in f1 is compliant when you pass an array to f1.

    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 inside myStruct, even if it points outside myStruct.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 of multi_arr. The assignment to variable arr_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 of ptr 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:

    void g(int *p);
    
    void add(int* p, int n) {
        g(p + n); //Compliant
    }
    
    void foo() {
        add(nullptr, 0); 
        
    }
    The pointer arithmetic in add() results in a nullptr. 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 Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

void f_incr(int* x)
{
    int* ptr_to_one = x;
    ++ptr_to_one;  // Compliant
}

void f1(int* const a1)
{
    int* b = &a1[2]; // Compliant
}

int main()
{

    int arr_one = 1; // Equivalent to array of one element
    f_incr(&arr_one);

    int arr[3] {};
    f1(arr);

    struct {
        char elem1[10];
        char elem2[10];
    } myStruct;

    char* ptr_to_struct = &myStruct.elem1[11]; // Compliant
    ptr_to_struct = &myStruct.elem2[11]; //Non-compliant

    int tab[3] {1, 2, 3};
    int* ptr =  &tab[2];
    int res = tab[2];
    ++ptr; // Compliant
    res = *ptr; //Non-compliant

    return 0;
}

In this example:

  • The increment of ptr_to_one inside f_incr() is compliant because the operation results in a pointer that points to one past the last element of array x. The integer that is passed to f_incr() is equivalent to an array of one element.

  • The operation on pointer parameter a1 inside f1() is compliant because the pointer points to array arr.

  • The first assignment of ptr_to_struct is compliant because elem1[11] is still inside myStruct. The second assignment of ptr_to_struct is not compliant because the result of the operation does not point to either inside myStruct or to one past the last element of myStruct.

  • The increment of ptr is compliant because the result of the operation points to one past the last element of tab. The dereference of ptr on the next line is not compliant.

Check Information

Group: Expressions
Category: Required, Automated

Version History

Introduced in R2021a

expand all