exponenta event banner

CERT C: ERR33-C правил

Обнаружение и обработка стандартных библиотечных ошибок

Описание

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

Обнаружение и обработка стандартных библиотечных ошибок [1 ].

Внедрение Polyspace

Эта проверка проверяет наличие следующих проблем:

  • Errno не проверено.

  • Возвращенное значение чувствительной функции не проверено.

  • Динамическое выделение памяти без резервирования.

Примеры

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

Проблема

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

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

  • fgetwc, strtol, и wcstol.

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

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

Риск

Чтобы убедиться, что вызов функции выполнен без ошибок, проверьте errno для значений ошибок.

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

  • void

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

Определить, произошла ли ошибка, можно только путем проверки errno.

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

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

Перед вызовом функции установите errno до нуля.

После вызова функции, чтобы увидеть, произошла ли ошибка, сравните errno до нуля. Также можно сравнить errno к известным значениям индикаторов ошибок. Например, strtol наборы errno кому ERANGE для индикации ошибок.

Сообщение об ошибке в результате Polyspace ® показывает значение индикатора ошибки, с которым можно сравнить.

Пример - errno Не проверено после вызова strtol
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>

int main(int argc, char *argv[]) {
    char *str, *endptr;
    int base;
    
    str = argv[1];
    base = 10;
    
    long val = strtol(str, &endptr, base);
    printf("Return value of strtol() = %ld\n", val);
}

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

Коррекция - проверка errno После вызова

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

#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<limits.h>

int main(int argc, char *argv[]) {
    char *str, *endptr;
    int base;
    
    str = argv[1];
    base = 10;
    
    errno = 0;
    long val = strtol(str, &endptr, base);
    if((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE) {
         printf("strtol error");
         exit(EXIT_FAILURE);
    }        
    printf("Return value of strtol() = %ld\n", val);
}
Проблема

Возвращенное значение не проверенной чувствительной функции возникает при вызове чувствительных стандартных функций, но вы:

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

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

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

Чувствительная функция - это стандартная функция, с которой можно столкнуться:

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

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

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

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

Критическая чувствительная функция - это чувствительная функция, выполняющая одну из следующих критических или уязвимых задач:

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

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

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

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

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

Риск

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

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

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

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

Пример - Возврат чувствительной функции проигнорирован
#include<stdio.h>
void initialize() {
	int n = 1;
	scanf("%d",&n); 
}

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

Коррекция - Приведение функции к (void)

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

#include<stdio.h>
void initialize() {
	int n = 1;
	(void) scanf("%d",&n); 
}
Коррекция - тестовое значение возврата

Одной из возможных корректировок является проверка возвращаемого значения scanf для проверки ошибок.

#include<stdio.h>
void initialize() {
	int n,flag ;
	flag = scanf("%d",&n); 
	if(flag>0){
		//...
	}
}
Пример - Критическая функция, возврат пропущен
#include <threads.h>
int thrd_func(void);
void initialize() {
    thrd_t thr;
	int n = 1;

    (void) thrd_create(&thr,thrd_func,&n); 
}

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

Коррекция - проверка возвращаемого значения критических функций

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

#include <threads.h>
int thrd_func(void);
void initialize() {
	thrd_t thr;
	int n = 1;
	if( thrd_success!= thrd_create(&thr,thrd_func,&n) ){
		// handle error
		
	}
}
Проблема

Незащищенное динамическое выделение памяти происходит, когда после динамического выделения памяти не проверяется, успешно ли оно выполнено.

Риск

При динамическом выделении памяти с помощью malloc, calloc, или realloc, возвращает значение NULL если запрошенная память недоступна. Если код, следующий за выделением, обращается к блоку памяти без проверки NULL значение, этот доступ не защищен от сбоев.

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

Проверьте возвращаемое значение malloc, calloc, или realloc для NULL перед доступом к выделенной ячейке памяти.

#DEFINE SIZE 8;

int *ptr = malloc(SIZE * sizeof(int));

if(ptr) /* Check for NULL */ 
{
   /* Memory access through ptr */
}

Пример - Ошибка выделения динамической памяти без резервирования
#include <stdlib.h>

void Assign_Value(void) 
{
  int* p = (int*)calloc(5, sizeof(int));

  *p = 2;  
  /* Defect: p is not checked for NULL value */

  free(p);
}

Если выделение памяти завершается неуспешно, функция calloc прибыль NULL кому p. Перед доступом к памяти через p, код не проверяет, p является NULL

Исправление - проверка значения NULL

Одной из возможных корректировок является проверка p имеет значение NULL перед исключением.

#include <stdlib.h>

void Assign_Value(void)
 {
   int* p = (int*)calloc(5, sizeof(int));

   /* Fix: Check if p is NULL */
   if(p!=NULL) *p = 2; 

   free(p);
 }

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

Группа: Правило 12. Обработка ошибок (ERR)
Представлен в R2019a

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

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

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