主要内容

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

MISRA C:2012 Dir 4.7

如果函数返回错误信息,则应测试该错误信息

描述

指令定义

如果函数返回错误信息,则应测试该错误信息 1 .

理由

如果未检查通过返回值指示错误信息的函数的返回值,程序可能会出现意外行为。这些函数的错误可能会传播到整个程序,导致输出错误、安全漏洞,甚至系统故障。

Polyspace 实现

当您调用返回可能错误信息的敏感标准函数并执行以下操作之一时,检查项会引发违规:

  • 忽略返回值。

    您只需不将返回值赋给变量,或显式将返回值转换为 void

  • 在未测试返回值是否出错的情况下使用函数的输出(返回值或通过引用传递的参量)。

如果函数调用由于以下原因容易失败,则检查项将该函数视为敏感函数:

  • 系统资源已用尽(例如,在分配资源时)。

  • 更改了特权或权限。

  • 在读取、写入或转换来自外部数据源的数据时,数据源可能存在污染。

  • 尽管存在相应的 API,但某些功能尚未支持。

检查项只考虑返回值为 return value 的函数,该值表示函数是否无错误地完成。

其中一些函数可以执行关键任务,例如:

  • 设置特权(例如,setuid

  • 创建一个监狱(例如,chroot

  • 创建一个进程(例如,fork

  • 创建一个线程(例如,pthread_create

  • 锁定或解锁互斥锁(例如 pthread_mutex_lock

  • 锁定或解锁内存段(例如 mlock

对于非关键函数,检查项允许将函数返回值转换为 void

此指令仅部分支持。

故障排除

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

示例

全部展开

#include <pthread.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <cstdlib>
#define fatal_error() abort()

void initialize_1() {
    pthread_attr_t attr;
    pthread_attr_init(&attr); //Noncompliant
}

void initialize_2() {
    pthread_attr_t attr;
   (void)pthread_attr_init(&attr); //Compliant
}

void initialize_3() {
    pthread_attr_t attr;
    int result;
    result = pthread_attr_init(&attr); //Compliant
    if (result != 0) {
        /* Handle error */
        fatal_error();
    }
}

int read_file_1(int argc, char *argv[])
{
  FILE *in;
  if (argc != 2) {
    /* Handle error */
  }

  in = fmemopen (argv[1], strlen (argv[1]), "r");   
  return 0; //Noncompliant
 
}
int read_file_2(int argc, char *argv[])
{
  FILE *in;
  if (argc != 2) {
    /* Handle error */
  }

  in = fmemopen (argv[1], strlen (argv[1]), "r"); //Compliant
  if (in==NULL){
	  // Handle error
  }
  return 0; 
}

此示例显示了对敏感函数 pthread_attr_initfmemopen 的调用。如果满足以下条件,Polyspace® 将设置标记:

  • 您隐式地忽略了敏感函数的返回值。显式地忽略敏感函数的输出不会被标记。

  • 您获得了敏感函数的返回值,但在退出相关范围之前未测试该值。该违规行为在退出语句中被触发。

为了合规,您可以显式地将它们的返回值转换为 void,或者测试返回值以检查错误。

#include <pthread.h>
extern void *start_routine(void *);

void returnnotchecked_1() {
    pthread_t thread_id;
    pthread_attr_t attr;
    void *res;

    (void)pthread_attr_init(&attr);
    (void)pthread_create(&thread_id, &attr, &start_routine, ((void *)0)); //Noncompliant
    pthread_join(thread_id,  &res); //Noncompliant
}

void returnnotchecked_2() {
    pthread_t thread_id;
    pthread_attr_t attr;
    void *res;
    int result;

    (void)pthread_attr_init(&attr);
    result = pthread_create(&thread_id, &attr, &start_routine, NULL); //Compliant
    if (result != 0) {
        /* Handle error */
        fatal_error();
    }

    result = pthread_join(thread_id,  &res); //Compliant
    if (result != 0) {
        /* Handle error */
        fatal_error();
    }
}

在此示例中,调用了两个关键函数:pthread_createpthread_join。将 pthread_create 转换为 void 时,其返回值会被忽略,但由于 pthread_create 是一个关键函数(不仅仅是一个敏感函数),因此规则检查项仍会触发违规。另一个关键函数 pthread_join 返回一个被隐式忽略的值。

为了确保合规,请检查这些关键函数的返回值,以验证函数是否按预期执行。

检查信息

组:代码设计
类别:必需
AGC 类别:必需

版本历史记录

在 R2017a 中推出

全部展开


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.