CERT C++: INT32-C

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

Описание

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

Гарантируйте, что операции на целых числах со знаком не приводят к переполнению. [1]

Примеры

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

Описание

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

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

Риск

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

Фиксация

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

Можно зафиксировать дефект:

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

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

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

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

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

Смотрите примеры мер ниже.

Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты 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 и числителей минимального целочисленного значения.

Пример - деление аргументов функции

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;
}

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

Группа: 03. Целые числа (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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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