exponenta event banner

Правило 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];
}
#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