CERT C++: INT31-C

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

Описание

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

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

Реализация Polyspace

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

  • Переполнение целочисленного преобразования.

  • Вызовите memset с непреднамеренным значением.

  • Изменение знака целого числа переполнение преобразования.

  • Преобразование изменения тонированного знака.

  • Переполнение беззнакового целочисленного преобразования.

Примеры

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

Проблема

Переполнение целочисленного преобразования происходит при преобразовании целого числа в меньший целый тип. Если переменной не хватает байтов, чтобы представлять исходное значение, преобразование переполнено.

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

Риск

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

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

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

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

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

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

В целом избегайте преобразований в меньшие целые типы.

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

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

Пример - Преобразование из int на char
char convert(void) {

    int num = 1000000;

    return (char)num;
}

В операторе return целочисленная переменная num преобразуется в char. Однако 8-битный или 16-битный символ не может представлять 1000000, потому что он требует по меньшей мере 20 бит. Поэтому операция преобразования переполнена.

Коррекция - Изменение типа преобразования

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

long convert(void) {

    int num = 1000000;

    return (long)num;
}
Проблема

Вызов memset с непреднамеренным значением происходит, когда Polyspace® Bug Finder™ обнаруживает использование memset или wmemset функция с возможно неправильными аргументами.

void *memset (void *ptr, int value, size_t num) заполняет первый num байты блока памяти, который ptr точки с заданным value. Если аргумент value неправильный, блок памяти инициализирован с непреднамеренным значением.

Непреднамеренная инициализация может происходить в следующих случаях.

ПроблемаРискВозможное исправление
Второй аргумент '0' вместо 0 или '\0'.Значение ASCII символьных '0' является 48 (десятичный), 0x30 (шестнадцатеричный), 069 (октальный), но не 0 (или '\0') .Если вы хотите инициализировать с '0', используйте одно из значений ASCII. В противном случае используйте 0 или '\0'.
Второй и третий аргументы, вероятно, противоположны. Например, третий аргумент является буквальным, а второй аргумент не является буквальным.Если порядок отменен, блок памяти непреднамеренного размера инициализируется с неправильными аргументами.Измените порядок аргументов на противоположный.
Второй аргумент не может быть представлен в байте.Если второй аргумент не может быть представлен в байте, и вы ожидаете, что каждый байт блока памяти будет заполнен этим аргументом, инициализация происходит не так, как предполагалось.

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

Для образца замените memset(a, -13, sizeof(a)) с memset(a, (-13) & 0xFF, sizeof(a)).

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

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

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

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

Пример - Значение не может быть представлено в байте
#include <string.h>

#define SIZE 32
void func(void) {
    char buf[SIZE];
    int c = -2;
    memset(buf, (char)c, sizeof(buf));
}

В этом примере (char)c не может быть представлен в байте.

Коррекция - Применить Bit Mask

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

#include <string.h>

#define SIZE 32
void func(void) {
    char buf[SIZE   ];
    int c = -2;
    memset(buf, c & 0xFF, sizeof(buf));
}
Проблема

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

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

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

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

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

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

Пример - Преобразование из unsigned char на char
char sign_change(void) {
    unsigned char count = 255;

    return (char)count;
}

В операторе возврата беззнаковая символьная переменная count преобразуется в символ со знаком. Однако char имеет 8 биты, 1 для знака константы и 7 для представления числа. Операция преобразования переполнена, потому что 255 использует 8 биты.

Коррекция - Изменение типов преобразования

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

int sign_change(void) {
    unsigned char count = 255;

    return (int)count;
}
Проблема

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

Для примера функций, которые используют size_t как аргументы неявно преобразуют аргумент в беззнаковое целое число. Некоторые функции, которые неявно преобразуют size_t являются:

bcmp
memcpy
memmove
strncmp
strncpy
calloc
malloc
memalign

Риск

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

  • Стандартные программы размера памяти - вызывают проблемы с выделением памяти.

  • Стандартные программы манипуляции строками - вызывает переполнение буфера.

  • Контуры цикла - вызывает бесконечные циклы.

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

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

Пример - Установите значение памяти с аргументом Size
#include <stdlib.h>
#include <string.h>

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

void bug_taintedsignchange(int size) {
    char str[SIZE128] = "";
    if (size<SIZE128) {
        memset(str, 'c', size); 
    }
}

В этом примере a char буфер создается и заполняется с помощью memset. Аргумент в виде memset является входной параметр к функции.

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

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

Одной из возможных коррекций является проверка, size ли находится внутри допустимой области значений. Эта коррекция проверяет, size ли больше нуля и меньше, чем buffer size перед вызовом memset.

#include <stdlib.h>
#include <string.h>

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

void corrected_taintedsignchange(int size) {
    char str[SIZE128] = "";
    if (size>0 && size<SIZE128) {
        memset(str, 'c', size);  
    }
}
Проблема

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

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

Риск

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

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

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

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

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

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

В целом избегайте преобразований в меньшие целые типы.

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

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

Пример - Преобразование из int на char
unsigned char convert(void) {
    unsigned int unum = 1000000U;

    return (unsigned char)unum;  
}

В операторе return беззнаковая целочисленная переменная unum преобразуется в беззнаковый тип символов. Однако преобразование переполнено, потому что 1000000 требует по меньшей мере 20 бит. Стандарт языка программирования C не рассматривает беззнаковое переполнение как ошибку, потому что программа автоматически уменьшает результат по модулю максимальное значение плюс 1. В этом примере unum уменьшается по модулю 2^8 поскольку тип символьных данных может представлять только 2^8-1.

Коррекция - Изменение типа преобразования

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

unsigned long convert(void) {
    unsigned int unum = 1000000U;

    return (unsigned long)unum;  
}

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

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

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

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