exponenta event banner

CERT C: INT31-C правил

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

Описание

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

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

Внедрение Polyspace

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

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

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

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

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

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

Примеры

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

Проблема

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

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

Риск

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

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

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

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

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

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

В общем случае избегайте преобразований в более мелкие целочисленные типы.

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

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

Пример - Преобразование из 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)).

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

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

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

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

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

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

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

Коррекция - применение литейной формы

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

#include <string.h>

#define SIZE 32
void func(void) {
    char buf[SIZE   ];
    int c = -2;
    memset(buf, (unsigned char)c, sizeof(buf)); 
}
Исправление - избегайте использования memset

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

#include <string.h>

#define SIZE 32
void func(void) {
    char buf[SIZE   ];
    int c = -2;
    memset(buf, 0, sizeof(buf));//Compliant 
	/* After clearing buf, use it in operations*/
}
Проблема

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

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

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

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

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

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

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

    return (char)count;
}

В операторе return символьная переменная без знака 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

Риск

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

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

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

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

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

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

Пример - Задать значение памяти с аргументом размера
#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); 
    }
}

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

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

Коррекция - контрольное значение size

Одной из возможных корректировок является проверка size находится внутри допустимого диапазона. Эта коррекция проверяет, 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).

Риск

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

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

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

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

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

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

В общем случае избегайте преобразований в более мелкие целочисленные типы.

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

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

Пример - Преобразование из 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;  
}

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

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

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

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