exponenta event banner

Правило AUTOSAR C++ 14 M0-3-2

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

Описание

Определение правила

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

Объяснение

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

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

  • void

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

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

Внедрение Polyspace

Проверка вызывает нарушение, когда:

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

    • Игнорировать возвращаемое значение.

      Вы просто не назначаете возвращаемое значение переменной или явно приводите возвращаемое значение к void.

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

    Средство проверки считает функцию чувствительной, если вызов функции подвержен сбою по следующим причинам:

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

    • Изменены привилегии или разрешения.

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

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

    Некоторые из этих функций могут выполнять критически важные задачи, такие как:

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

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

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

    • Создание резьбы (например, pthread_create)

    • Блокировать или разблокировать мьютекс (например, pthread_mutex_lock)

    • Блокировать или разблокировать сегменты памяти (например, mlock)

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

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

    Задаваемые функции errno к ошибкам относятся:

    • fgetwc, strtol, и wcstol.

      Полный список функций см. в документации по errno.

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

Поиск неисправностей

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

Примеры

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

#include <pthread.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();
    }
}

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

Для соответствия можно явно привести возвращаемое значение к void или проверьте возвращаемое значение pthread_attr_init и проверьте наличие ошибок.

#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