CERT C: Rule INT33-C

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

Описание

Управляйте определением

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

Реализация Polyspace

Это средство проверки проверяет на эти проблемы:

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

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

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

Примеры

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

Проблема

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

Риск

Деление на нуль может привести к катастрофическому отказу программы.

Фиксация

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

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

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, и числители минимального целочисленного значения.

Пример - деление аргументов функции
extern void print_int(int);

int taintedintdivision(int usernum, int userden) {
    int r =  usernum/userden; 
    print_int(r);
    return r;
}

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

Коррекция — контрольные числа

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

#include "limits.h"

extern void print_int(int);

int taintedintdivision(int usernum, int userden) {
    int r = 0;
    if (userden!=0 && !(usernum=INT_MIN && userden==-1)) {
        r = usernum/userden;
    }
    print_int(r);
    return r;
}
Проблема

Испорченный операнд по модулю проверяет операнды остатка % операции. Средство поиска ошибки отмечает операции с модулем с помощью одного или нескольких испорченных операндов.

Риск

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

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

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

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

Фиксация

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

Пример - по модулю с аргументами функции
extern void print_int(int);

int taintedintmod(int userden) {
    int rem =  128%userden; 
    print_int(rem);
    return rem;
}

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

Коррекция — значения операнда проверки

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

extern void print_int(int);

int taintedintmod(int userden) {
    int rem = 0;
    if (userden > 0) { 
        rem = 128 % userden; 
    }
    print_int(rem);
    return rem;
}

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

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

[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

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

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