This rule is part of MISRA C++:2023.
Usage of this content is governed by Sonar’s terms and conditions. Redistribution is
prohibited.
Rule 8.7.1 - Pointer arithmetic shall not form an invalid pointer
[expr.add] Undefined 4
Category: Required
Analysis: Undecidable,System
Amplification
This rule applies to all forms of pointer arithmetic, including array indexing:
integer_expression + pointer_expression
pointer_expression + integer_expression
pointer_expression - integer_expression
pointer_expression += integer_expression
pointer_expression -= integer_expression
++pointer_expression
--pointer_expression
pointer_expression++
pointer_expression--
pointer_expression [ integer_expression ]
integer_expression [ pointer_expression ]
A pointer resulting from pointer arithmetic is invalid if it does not point to:
- An element of the same array as the original pointer; or
- One past the end of the same array as the original pointer.
This rule also applies to pointer arithmetic that occurs within the C++ Standard Library functions. In addition, it is assumed that the
implementation of the functions listed below perform pointer arithmetic on their pointer parameters:
memchr, memcmp, memcpy, memmove, memset, strncat,
strncmp, strncpy, strxfrm
Note: a pointer to an object that is not an array is treated as if it were a pointer to the first element of an array with a
single element.
Rationale
Undefined behaviour occurs if the result obtained from one of the above expressions is not a pointer to an element of the array pointed to
by pointer_expression, or a pointer to one beyond the end of that array.
Note: dereferencing an invalid pointer, including a pointer to one past the end of an array, results in undefined
behaviour — this is targeted by M23_393: MISRA C++ 2023 Rule 4.1.3.
Example
int32_t * f1( int32_t * const a1, int32_t a2[ 10 ], int32_t ( &a3 )[ 10 ] )
{
a1[ 3 ] = 0; // Compliant only if the array pointed
// to by 'a1' has at least 4 elements
*( a2 + 9 ) = 0; // Compliant only if the array pointed
// to by 'a2' has at least 10 elements
return a3 + 9; // Compliant
}
void f2()
{
int32_t a1[ 10 ] = { };
int32_t * p1 = &a1[ 0 ]; // Compliant
int32_t * p2 = a1 + 10; // Compliant - points to one beyond and
int32_t i = *p2; // dereferencing is undefined behaviour
int32_t * p3 = a1 + 11; // Non-compliant - points to two beyond, resulting
// in undefined behaviour
p1++; // Compliant
a1[ -1 ] = 0; // Non-compliant - exceeding array bounds results
// in undefined behaviour
i = *( &i + 0 ); // Compliant - 'i' is treated as an array
// of size 1
// This declaration has 6 arrays:
// 1 array of 5 elements of type array of int32_t
// 5 arrays of 2 elements of type int32_t
int32_t a2[ 5 ][ 2 ] = { };
a2[ 3 ][ 1 ] = 0; // Compliant
i = *( *( a2 + 3 ) + 1 ); // Compliant
i = a2[ 2 ][ 3 ]; // Non-compliant - exceeding array bounds results
// in undefined behaviour
int32_t * p4 = a2[ 1 ]; // Compliant
i = p4[ 1 ]; // Compliant - p4 addresses an array of size 2
}
The following example illustrates pointer arithmetic applied to members of a structure. Because each member is an object in its own right, this
rule prevents the use of pointer arithmetic to move from one member to the next.
struct
{
uint16_t x;
uint16_t y;
uint16_t a[ 10 ];
} s;
void f3()
{
uint16_t * p { &s.x };
++p; // Compliant - p points one past the end of s.x,
// but this cannot be assumed to point to s.y
*p = 0; // and dereferencing is undefined behaviour
++p; // Non-compliant - more than one past the end
p = &s.a[ 0 ]; // Compliant - p points into s.a
p = p + 8; // Compliant - p still points into s.a
p = p + 3; // Non-compliant - more than one past the end
}
The following example shows that the implicit pointer arithmetic within library functions can lead to accesses beyond the end of an array:
uint8_t buf1[ 5 ] = { 1, 2, 3, 4, 5 };
uint8_t buf2[ 7 ] = { 1, 2, 3, 4, 5, 6, 7 };
void f4()
{
if ( std::memcmp( buf1, buf2, 5 ) == 0 ) {} // Compliant
if ( std::memcmp( buf1, buf2, 7 ) == 0 ) {} // Non-compliant
auto p1 = std::next( buf1, 3 ); // Compliant
auto p2 = std::next( buf1, 7 ); // Non-compliant
}
Copyright The MISRA Consortium Limited © 2023