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

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

Описание

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

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

Примеры

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

Описание

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

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

Риск

Целочисленное преобразование переполняет результата в неопределенном поведении.

Фиксация

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

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

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

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

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

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

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

Пример - преобразовывающий от int до char

char convert(void) {

    int num = 1000000;

    return (char)num;
}

В операторе возврата целочисленная переменная 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 Bug Finder.

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

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

Пример - значение не может быть представлено в байте

#include <string.h>

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

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

Исправление — применяет бросок

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

#include <string.h>

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

Описание

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

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

Фиксация

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

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

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

Риск

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

  • Стандартные программы емкости памяти — причины, выделяющие проблемы памяти.

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

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

Фиксация

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

Пример - значение памяти аппарата с аргументом размера

#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, чем нуль и меньше, чем 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).

Риск

Целочисленное преобразование переполняет результата в неопределенном поведении.

Фиксация

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

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

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

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

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

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

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

Пример - преобразовывающий от int до char

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

    return (unsigned char)unum;  
}

В операторе возврата переменная 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 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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