AUTOSAR C++ 14 правил A5-6-1

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

Описание

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

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

Объяснение

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

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

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

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

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

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

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

Реализация 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];
}
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;
}
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;
}

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

Группа: Выражения

Введенный в R2019a