AUTOSAR C++14 Rule 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];
}
#include <limits.h>
#include <stdio.h>

extern void print_int(int);

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

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

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

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

#include <limits.h>
#include <stdio.h>

extern void print_long(long);

int taintedintdivision(void) {
    long num, denum;
    scanf("%lf %lf", &num, &denum);
    long res= 0;
    if (denum!=0 && !(num==INT_MIN && denum==-1)) {
        res = num/denum;
    }
    print_long(res);
    return res;
}
#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;
}

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

Группа: Выражения
Категория: Необходимый, Автоматизированный
Введенный в R2019a