MISRA C++:2008 Rule 0-3-2

Если функция сгенерирует информацию об ошибке, то та информация об ошибке должна быть протестирована

Описание

Управляйте определением

Если функция сгенерирует информацию об ошибке, то та информация об ошибке должна быть протестирована.

Объяснение

Если вы не проверяете возвращаемое значение функций, которые указывают на информацию об ошибке через их возвращаемые значения, ваша программа может неожиданно вести себя. Ошибки от этих функций могут распространить в программе, вызывающей неправильный выход, уязвимости системы обеспечения безопасности, и возможно системные отказы.

Для errno- установка функций, чтобы видеть, если вызов функции, завершенный без ошибок, проверяет errno для ошибочных значений. Возвращаемые значения их errno- устанавливающие функции не указывают на ошибки. Возвращаемое значение может быть одним из следующего:

  • void

  • Даже если ошибка происходит, возвращаемое значение может совпасть со значением от успешного вызова. Такие возвращаемые значения называются внутриполосными ошибочными индикаторами. Например, strtol преобразует строку в длинное целое и возвращает целое число. Если результат переполнения преобразования, функция возвращает LONG_MAX и наборы errno к ERANGE. Однако функция может также возвратить LONG_MAX от успешного преобразования. Только путем проверки errno можно ли различать ошибку и успешное преобразование.

Для errno- устанавливая функции, можно определить, произошла ли ошибка только путем проверки errno.

Реализация Polyspace

Средство проверки повышает нарушение когда:

  • Вы вызываете чувствительные функции, которые возвращают информацию о возможных ошибках, и затем вы игнорируете возвращаемое значение или используете выход функции, не тестируя возвращаемое значение.

    Средство проверки покрывает функцию от стандартной библиотеки и других известных библиотек, таких как библиотека POSIX или библиотека WinAPI. Polyspace® рассматривает функцию как чувствительную, если вызов функции подвержен отказу из-за причин, таких как:

    • Исчерпанные системные ресурсы (например, при выделении ресурсов).

    • Измененные привилегии или полномочия.

    • Испорченные источники при чтении, при записи или преобразовании данных из внешних источников.

    • Неподдерживаемые функции несмотря на существующий API.

    Polyspace считает функцию критическим чувствительным, когда они выполняют критические задачи, такие как:

    • Установите привилегии (например, setuid)

    • Создайте тюрьму (например, chroot)

    • Создайте процесс (например, fork)

    • Создайте поток (например, pthread_create)

    • Заблокируйте или разблокируйте взаимное исключение (например, pthread_mutex_lock)

    • Заблокируйте или разблокируйте сегменты памяти (например, mlock)

    Для функций, которые не очень важны, не отмечается средство проверки, если вы явным образом игнорируете возвращаемое значение путем кастинга его к void. Явным образом игнорирование возвращаемого значения критических чувствительных функций отмечается Polyspace.

  • Вы вызываете функцию, которая устанавливает errno указать на состояние ошибки, но не проверять errno после вызова. Для этих функций, проверяя errno единственный надежный путь состоит в том, чтобы определить, произошла ли ошибка.

    Функции, которые устанавливают errno при ошибках включайте:

    • fgetwc, strtol, и wcstol.

      Для всестороннего списка функций см. документацию о errno.

    • POSIX®errno- установка функций, таких как encrypt и setkey.

Поиск и устранение проблем

Если вы ожидаете нарушение правила, но не видите его, относитесь, чтобы Диагностировать, Почему Кодирующие Стандартные Нарушения Не Появляются как ожидалось.

Примеры

развернуть все

#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_init и fmemopen. Polyspace повышает флаг если:

  • Вы неявно игнорируете возврат чувствительной функции. Явным образом игнорирование выхода чувствительных функций не отмечается.

  • Вы получаете возвращаемое значение чувствительной функции, но не тестируете значение прежде, чем выйти из соответствующего осциллографа. Нарушение повышено на выходном операторе.

Чтобы быть совместимыми, можно явным образом бросить их возвращаемое значение к void или протестируйте возвращаемые значения, чтобы проверить ошибки.

#include <pthread.h>
#include <cstdlib>
#define fatal_error() abort()
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_create и pthread_join. Возвращаемое значение pthread_create проигнорирован путем кастинга, чтобы освободить, но потому что pthread_create критическая функция (не только чувствительная функция), средство проверки правила все еще повышает нарушение. Другая критическая функция, pthread_join, возвращает значение, которое проигнорировано неявно.

Чтобы быть совместимыми, проверяйте возвращаемое значение этих критических функций, чтобы проверить функцию, выполняемую как ожидалось.

#include<cstdlib>
#include<cerrno>
#include<climits>
#include<iostream>

int main(int argc, char *argv[]) {
    char *str, *endptr;
    int base;
    
    str = argv[1];
    base = 10;
    
    long val = strtol(str, &endptr, base); //Noncompliant
    std::cout<<"Return value of strtol() = %ld\n" << val;
    
    errno = 0;
    long val2 = strtol(str, &endptr, base); //Compliant
    if((val2 == LONG_MIN || val2 == LONG_MAX) && errno == ERANGE) {
         std::cout<<"strtol error";
         exit(EXIT_FAILURE);
    }        
    std::cout<<"Return value of strtol() = %ld\n" << val2;
}

В несовместимом примере, возвращаемом значении strtol используется, не проверяя errno.

Быть совместимым, прежде, чем вызвать strtol, установите errno обнулять. После вызова strtol, проверяйте возвращаемое значение на LONG_MIN или LONG_MAX и errno для ERANGE.

Проверяйте информацию

Группа: независимые от языка проблемы
Категория: необходимый
Введенный в R2020b