exponenta event banner

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

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

Описание

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

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

Внедрение Polyspace

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

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

  • Операнд запятнанной дивизии.

  • Запятнанный по модулю операнд.

Примеры

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

Проблема

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

Риск

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

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

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

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

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

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

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

Пример - Деление целого числа на ноль
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. Проверьте оба операнда на наличие отрицательных значений.

Пример - Modulo с UInsecure Input
#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 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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