CERT C: Rule INT33-C

Убедитесь, что операции разделения и оставшиеся операции не приводят к ошибкам деления на нули

Описание

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

Убедитесь, что операции разделения и остальных операций не приводят к ошибкам деления на нули.[1]

Реализация Polyspace

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

  • Целое число, деление на нуль.

  • Испорченный операнд деления.

  • Испорченный операнд по модулю.

Примеры

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

Проблема

Integer division by zero происходит, когда знаменатель деления или операции с модулем может быть нулевым целым числом.

Риск

Деление на нули может привести к сбою программы.

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

Исправление зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Используйте этот список событий, чтобы определить, как переменная знаменателя получает нулевое значение. Вы можете реализовать исправление на любом событии в последовательности. Если сведения о результате не отображают историю событий, можно отследить их с помощью опций правого щелчка в исходном коде и просмотреть предыдущие связанные события. Смотрите также Результаты интерпретации Bug Finder в интерфейсе пользователя Polyspace Desktop.

Рекомендуется проверить нулевые значения знаменателя перед делением и обработать ошибку. Вместо непосредственного выполнения деления:

res = num/den;
используйте функцию библиотеки, которая обрабатывает нулевые значения знаменателя перед выполнением деления:
res = div(num, den);

См. примеры исправлений ниже.

Если вы не хотите устранять проблему, добавьте комментарии к своему результату или коду, чтобы избежать другой проверки. Смотрите Адрес Результаты Polyspace через исправления ошибок или обоснования.

Пример - Деление целого числа на нуль
int fraction(int num)
{
    int denom = 0;
    int result = 0;

    result = num/denom;

    return result;
}

Деление на нулевую ошибку происходит в num/denom потому что denom равен нулю.

Коррекция - Проверка перед делением
int fraction(int num)
{
    int denom = 0;
    int result = 0;

    if (denom != 0)
        result = num/denom;

    return result;
}

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

Коррекция - Изменение Знаменателя

Одной из возможных коррекций является изменение значения знаменателя так, чтобы denom не равен нулю.

int fraction(int num)
{
    int denom = 2;
    int result = 0;

    result = num/denom;

    return result;
}
Пример - Операция с модулем с нулем
int mod_arr(int input)
{
    int arr[5];
    for(int i = 0; i < 5; i++)
    {
        arr[i] = input % i;
    }

    return arr[0]+arr[1]+arr[2]+arr[3]+arr[4];
}

В этом примере Polyspace помечает операцию с модулем как деление на нуль. Поскольку модуль по своей сути является операцией деления, делитель (аргумент правой руки) не может быть нулем. В операцию с модулем используется for индекс цикла как делитель. Однако for цикл начинается с нуля, который не может быть итератором.

Коррекция - Проверяйте делитель перед операцией

Одной из возможных коррекций является проверка делителя перед операцией с модулем. В этом примере смотрите, является ли индекс i равен нулю перед операцией с модулем.

int mod_arr(int input)
{
    int arr[5];
    for(int i = 0; i < 5; i++)
    {
        if(i != 0)
        {
             arr[i] = input % i;
        }
        else
        {
             arr[i] = input;
        }
    }

    return arr[0]+arr[1]+arr[2]+arr[3]+arr[4];
}
Коррекция - Изменение делителя

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

int mod_arr(int input)
{
    int arr[5];
    for(int i = 0; i < 5; i++)
    {
         arr[i] = input % (i+1);
    }

    return arr[0]+arr[1]+arr[2]+arr[3]+arr[4];
}
Проблема

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

Риск

  • Если числитель является минимально возможным значением, и знаменатель -1Операция деления переполнена, поскольку результат не может быть представлен текущим размером переменной.

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

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

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

Перед выполнением деления проверьте значения операндов. Проверяйте на знаменатели 0 или -1, и числители минимального целого значения.

Пример - Деление аргументов функции
#include<stdio.h>
extern void print_int(int);

int taintedintdivision(void) {
    int num, den;
	scanf("%lf %lf",&num, &den);
	int r =  num/den; 
    print_int(r);
    return r;
}

Эта функция , взятая в качестве примера, делит две переменные аргумента, затем печатает и возвращает результат. Значения аргументов неизвестны и могут вызвать деление на ноль или целочисленное переполнение.

Коррекция - Проверяйте значения

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

#include<stdio.h>
#include <limits.h> 
extern void print_int(int);

int taintedintdivision(void) {
	int num, den;
	scanf("%lf %lf",&num, &den);
	int r = 0;
	if (den!=0 && !(num=INT_MIN && den==-1)){
		r =  num/den; 	
	}
	print_int(r);
	return r;
}
Проблема

Испорченный операнд по модулю проверяет операнды остальных % операции. Bug Finder помечает операции с модулем с одним или несколькими испорченными операндами.

Риск

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

  • Если второй оставшийся операнд -1Ваша оставшаяся операция может переполниться, если оставшаяся операция реализована на основе операции деления, которая может переполниться.

  • Если один из операндов отрицателен, результат операции неопределенен. Для C89 операция с модулем не стандартизирована, поэтому результат от отрицательных операндов задан как реализация.

Эти риски могут быть использованы злоумышленниками, чтобы получить доступ к вашей программе или цели в целом.

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

Перед выполнением операции с модулем проверьте значения операндов. Проверьте второй операнд на значения 0 и -1. Проверьте оба операнда на отрицательные значения.

Пример - Модуль с входом UInsecure
#include<stdio.h>
extern void print_int(int);

int taintedintmod(void) {
	int userden;
	scanf("%d",&userden);
    int rem =  128%userden; 
    print_int(rem);
    return rem;
}

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

Коррекция - Проверяйте значения операндов

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

#include<stdio.h>
extern void print_int(int);

int taintedintmod(void) {
	int userden;
	scanf("%d",&userden);
	int rem = 0;
    if (userden > 0) { 
        rem = 128 % userden; 
    }
    print_int(rem);
    return rem;
}

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

Группа: Правило 04. Целые числа (INT)
Введенный в R2019a

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

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

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