CERT C++: INT32-C

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

Описание

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

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

Реализация Polyspace

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

  • Целочисленное переполнение.

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

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

Примеры

расширить все

Проблема

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

Точное выделение ресурсов хранения для различных типов с плавающей точкой зависит от процессора. См. Target processor type (-target).

Риск

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

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

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

Исправить дефект можно путем:

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

  • Проверка значений, которые приводят к переполнению, и выполнение соответствующей обработки ошибок.

Чтобы избежать переполнения в целом, попробуйте один из следующих методов:

  • Сохраните целое число значений переменных ограниченным в пределах половины областью значений целых чисел со знаком.

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

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

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

Пример - Сложение максимального целого числа
#include <limits.h>

int plusplus(void) {

    int var = INT_MAX;
    var++;             
    return var;
}

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

Коррекция - разный тип склада

Одной из возможных коррекций является изменение типов данных. Сохраните результат операции в большем типе данных (Обратите внимание, что на 32-разрядной машине int и long имеет тот же размер). В этом примере на 32-битной машине путем возврата long long вместо int, ошибка переполнения исправлена.

#include <limits.h>

long long plusplus(void) {

    long long lvar = INT_MAX;
    lvar++;
    return lvar;
}
Проблема

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

Риск

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

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

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

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

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

Пример - Деление аргументов функции
#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;
}
Проблема

Испорченный операнд по модулю проверяет операнды остальных % операции. Bug Finder помечает операции с модулем с одним или несколькими испорченными операндами.

Риск

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

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

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

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

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

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

Пример - По модулю с аргументами функции
#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;
}

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

Группа: 03. Целые числа (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 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

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

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