CERT C++: FIO41-C

Не вызывайте getc (), putc (), getwc () или putwc () с потоковым аргументом, который имеет побочные эффекты

Описание

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

Не вызывайте getc (), putc (), getwc () или putwc () с потоковым аргументом, который имеет побочные эффекты.[1]

Реализация Polyspace

Эта проверка проверяет аргумент Stream с возможно непреднамеренными побочными эффектами.

Примеры

расширить все

Проблема

Аргумент Stream с возможно непреднамеренными побочными эффектами возникает при вызове getc(), putc(), getwc(), или putwc() с аргументом потока, который имеет побочные эффекты.

Аргумент Stream с возможно непреднамеренными побочными эффектами рассматривает следующие побочные эффекты Stream:

  • Любое назначение переменной потока, такого как FILE *, или любое назначение переменной более глубокого типа потока, такого как массив FILE *.

  • Любой вызов функции, которая манипулирует потоком или более глубоким типом потока.

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

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

Риск

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

Зафиксировать

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

Пример - Потоковый аргумент getc() Имеет побочный эффект fopen()
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

#define fatal_error() abort()

const char* myfile = "my_file.log";

void func(void)
{
    int c;
    FILE* fptr;
    /* getc() has stream argument fptr with
    * 2 side effects: call to fopen(), and assignment
    * of fptr
    */
     c = getc(fptr = fopen(myfile, "r"));
    if (c == EOF) {
        /* Handle error */
        (void)fclose(fptr);
        fatal_error();
    }
    if (fclose(fptr) == EOF) {
        /* Handle error */
        fatal_error();
    }
}

void main(void)
{
    func();

}

В этом примере getc() вызывается с аргументом stream fptr. Аргумент stream имеет два побочных эффекта: вызов fopen() и назначение fptr. Если getc() реализован как небезопасный макрос, побочные эффекты происходят несколько раз.

Коррекция - Используйте отдельный оператор для fopen()

Одной из возможных коррекций является использование отдельного оператора для fopen(). Вызов fopen() и назначение fptr происходит в этом операторе, поэтому нет побочных эффектов, когда вы проходите fptr на getc().

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

#define fatal_error() abort()


const char* myfile = "my_file.log";

void func(void)
{
    int c;
    FILE* fptr;

    /* Separate statement for fopen()
    * before call to getc()
    */
    fptr = fopen(myfile, "r");
    if (fptr == NULL) {
        /* Handle error */
        fatal_error();
    }
    c = getc(fptr);
    if (c == EOF) {
        /* Handle error */
        (void)fclose(fptr);
        fatal_error();
    }
    if (fclose(fptr) == EOF) {
        /* Handle error */
        fatal_error();
    }
}

void main(void)
{
    func();

}

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

Группа: 07. Входной выход (FIO)
Введенный в R2019a

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОН И/ИЛИ ЕГО ИНЖЕНЕРНОГО ИНСТИТУТА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ НА БАЗИСЕ «КАК ЕСТЬ». УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБОГО ВОПРОСА, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЮ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ КОММЕРЧЕСКОЙ ВЫГОДЫ, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Это программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллон или его Институтом программной инженерии.