このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
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
説明
ルール定義
A pointer resulting from arithmetic on a pointer operand shall address an element of the same array as that pointer operand 1 .
根拠
無効な配列の添字を使用するとプログラムの誤動作につながる可能性があります。実行時に派生した配列の添字は、手動によるレビューまたは静的解析で容易にチェックできないため特に問題となります。
C 標準に従うと、配列の終わりを超えた要素を指すポインターのデリファレンスは未定義の動作を発生させるため、準拠しません。
ポインター T*
をポインター char*
または unsigned char*
に変換する場合、変換後のポインターの範囲は sizeof(T)
と見なされます。たとえば次のコードでは、array
は unsigned char
型のオブジェクト 4
を収容します。
unsigned int obj = 42; unsigned char *array = (unsigned char*) &obj; unsigned char small_obj = array[3];
Polyspace 実装
Polyspace® は、次の場合にこのルールの違反を報告します。
配列へのアクセス中に配列のインデックスが範囲
[0...array_size-1]
から外れた場合。ポインターがその範囲外でデリファレンスされた場合。
Polyspace は、このルールに対する違反をチェックする際に次の要因を考慮します。
配列の一部ではない単一のオブジェクトは、1 要素の配列と見なされます。たとえば、このコード例では
arr_one
は 1 要素の配列と等価です。Polyspace はポインターptr_to_one
のインクリメントにフラグを設定しません。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 は、ポインターが配列を指している場合、ポインター算術演算でのポインター パラメーターの使用にフラグを設定しません。たとえば、このコード スニペットで
f1
に配列を渡した場合、f1
の&a1[2]
はルールに準拠しています。void f1( int* const a1){ int* b= &a1[2]; // Compliant } void f2(){ int arr[3] {}; f1(arr); }
複数の要素を含む構造体で、要素に対するポインターが構造体に割り当てられたメモリ内を指していたり、構造体の最後の要素を超えた位置を指していたりする場合、Polyspace は、別の要素を指すポインターとなる要素のポインターに対する算術演算の結果にフラグを設定しません。
たとえばこのコード スニペットでは、
ptr_to_struct
への代入はルールに準拠しています。myStruct.elem1
の外部を指していますが、それでもmyStruct
の内部にとどまっているからです。最終結果としてのアドレスが構造体に割り当てられたメモリの内部であったとしても、要素の次元より大きいインデックスを使用して要素の内容にアクセスすることはルールに準拠していません。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 }
多次元配列では、Polyspace は、部分配列の要素へのアクセスに部分配列の次元より大きいインデックスを使用している箇所にフラグを設定します。Polyspace は、アドレスがトップレベルの配列に割り当てられたメモリの内部である場合、同じ部分配列のアドレスの代入にはフラグを設定しません。
たとえばこのコード スニペットでは、ポインター
ptr_to_arr
への代入はルールに準拠しています。このポインターはmulti_arr
に割り当てられたメモリの内部のアドレスを指しているからです。変数arr_val
への代入はルールに準拠していません。部分配列要素へのアクセスに使用されるインデックス (3) が部分配列の次元 (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 は、ポインターが配列の最後の要素を超えた位置を指す場合、そのポインターのデリファレンスにフラグを設定します。たとえばこのコード スニペットでは、
ptr
の代入はルールに準拠していますが、ptr
のデリファレンスは準拠していません。tab+3
は tab の最後の要素を超えた位置です。void derefPtr(){ int tab[3] {}; int* ptr = tab+3; //Compliant int res = *(tab+3); // Non-compliant }
ポインター算術演算の結果が
nullptr
になる場合、Polyspace はこのチェッカーを起動しません。たとえば、次のコードを考えます。void g(int *p); void add(int* p, int n) { g(p + n); //Compliant} void foo() { add(nullptr, 0); }
add()
でのポインター演算の結果はnullptr
になります。Polyspace は、この演算にフラグを設定しません。Polyspace がポインターまたは配列へのアクセスに対してこのルールの違反を報告する場合、それ以降のそのポインターまたは配列へのアクセスについては違反が報告されなくなります。たとえば、Polyspace は
pointer2array
への最初のインクリメントに対してこのルールの違反を報告します。この違反を修正すると、それ以降の範囲外のアクセスも修正できます。報告された問題を修正した後に範囲外のアクセスが残っている場合、Polyspace はそれらを違反として報告します。#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*/ }
チェッカーの拡張
入力値が不明であり、入力のサブセットのみがエラーの原因として考えられる場合、既定の Bug Finder 解析ではこのルールに対する違反が報告されない場合があります。特定のシステム入力値を原因とする違反の有無をチェックするには、より厳密な Bug Finder 解析を実行してください。特定のシステム入力値から欠陥を見つけるための Bug Finder チェッカーの拡張を参照してください。
トラブルシューティング
ルール違反を想定していてもその違反が表示されない場合、コーディング規約違反が想定どおりに表示されない理由の診断を参照します。
例
チェック情報
グループ: ポインターと配列 |
カテゴリ: 必要 |
AGC カテゴリ: 必要 |
バージョン履歴
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.