CERT C++: ERR33-C

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

Описание

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

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

Реализация Polyspace

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

  • Эрно не проверяется.

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

  • Незащищенное динамическое выделение памяти.

Примеры

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

Проблема

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

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

  • fgetwc, strtol, и wcstol.

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

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

Риск

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

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

  • 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 не поднимает этот дефект для чувствительных функций, приведенных к пустоте. Это разрешение не принято для критически важных функций, потому что они выполняют более уязвимые задачи.

Пример - scanf Возврат функции проигнорирован
#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 <stddef.h>
#include <stdlib.h>

void unchecked_memory_allocation(void) {
  int * p = (int*)calloc(5, sizeof(int));// C-style allocation  
  *p = 2;                                   //Noncompliant
  //...
  delete[] p;
}

В этом примере память динамически выделяется для указателя мыши *p. Затем указатель используется без проверки выхода операции динамического выделения памяти. Polyspace повышает этот дефект, когда указатели используются после незакрытой операции динамического выделения памяти.

Коррекция - Проверка выхода динамического выделения памяти

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

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

void checked_memory_allocation(void) {
	int * p = new int[5];  
	if(p==NULL){// Check output of new
		//Handle memory allocation error
	}else{
		*p = 2; //Compliant                                   
		//...
		delete[] p;
	}

}
Проблема

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

Риск

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

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

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

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);
 }

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

Группа: 08. Исключения и обработка ошибок (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 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

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

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