主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

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 char4 对象。

unsigned int obj = 42;
unsigned char *array = (unsigned char*) &obj;
unsigned char small_obj = array[3];

Polyspace 实现

Polyspace® 在以下情况下报告违反此规则:

  • 在数组访问期间,数组索引超出范围 [0...array_size-1]

  • 指针在超出其作用域范围外被解引用。

在检查是否违反本规则时,Polyspace 会考虑以下因素:

  • 不属于数组的单个对象被视为一个元素的数组。例如,在此代码示例中,arr_one 等同于一个元素的数组。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 内,即使它指向 myStruct.elem1 之外。使用大于元素维度的索引来访问该元素的内容是不合规的,即使结果地址在结构的分配内存范围内也是如此。

    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 超过选项卡中的最后一个元素。

    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 分析。请参阅Extend Bug Finder Checkers to Find Defects from Specific System Input Values

故障排除

如果您预期会出现违规,但未看到该违规,请参阅诊断为何编码规范违规未按预期显示

示例

全部展开

在此示例中,指针 pointer 最初指向缓冲区 array 末尾之后的一个元素。在 C 标准中,指向末尾之外的位置是允许的,但解引用该位置会导致未定义的行为,不合规。当代码解引用 *pointer*(pointer++) 时,Polyspace 会报告违规。

void foo ( void )
{
  int array[10] = {0};
  int* pointer = &array[10];
  int data1 = *(pointer++); /* Noncompliant*/
  int data2 = *(pointer); /* Noncompliant*/
  int data3 = *(pointer--); /* Compliant*/

}

检查信息

组:指针和数组
类别:必需
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.