CERT C++: STR50-CPP

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

Описание

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

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

Реализация Polyspace

Это средство проверки проверяет на эти проблемы:

  • Использование опасной стандартной функции.

  • Переполнение буфера от неправильного спецификатора формата строки.

  • Целевое переполнение буфера в обработке строк.

Примеры

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

Проблема

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

Опасная функцияРискните уровнемБолее безопасная функция
getsПо сути опасный — Вы не можете управлять длиной входа от консоли.fgets
cinПо сути опасный — Вы не можете управлять длиной входа от консоли.Избегайте или вызовы предисловий cin с cin.width.
strcpyВозможно опасный — Если исходная длина больше места назначения, переполнение буфера может произойти.strncpy
stpcpyВозможно опасный — Если исходная длина больше места назначения, переполнение буфера может произойти.stpncpy
lstrcpy или StrCpyВозможно опасный — Если исходная длина больше места назначения, переполнение буфера может произойти.StringCbCopy, StringCchCopy, strncpy, strcpy_s, или strlcpy
strcatВозможно опасный — Если конкатенированный результат больше места назначения, переполнение буфера может произойти.strncat, strlcat, или strcat_s
lstrcat или StrCatВозможно опасный — Если конкатенированный результат больше места назначения, переполнение буфера может произойти.StringCbCat, StringCchCat, strncay, strcat_s, или strlcat
wcpcpyВозможно опасный — Если исходная длина больше места назначения, переполнение буфера может произойти.wcpncpy
wcscatВозможно опасный — Если конкатенированный результат больше места назначения, переполнение буфера может произойти.wcsncat, wcslcat, или wcncat_s
wcscpyВозможно опасный — Если исходная длина больше места назначения, переполнение буфера может произойти.wcsncpy
sprintfВозможно опасный — Если продолжительность выхода зависит от неизвестных длин или значений, переполнение буфера может произойти.snprintf
vsprintfВозможно опасный — Если продолжительность выхода зависит от неизвестных длин или значений, переполнение буфера может произойти.vsnprintf
Риск

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

Фиксация

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

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

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

Пример - Используя sprintf
#include <stdio.h>
#include <string.h>
#include <iostream>

#define BUFF_SIZE 128


int dangerous_func(char *str)
{
    char dst[BUFF_SIZE];
    int r = 0;

    if (sprintf(dst, "%s", str) == 1)
    {
        r += 1;
        dst[BUFF_SIZE-1] = '\0';
    }
    
    return r;
}

Эта функция, взятая в качестве примера, использует sprintf скопировать строку str к dst. Однако, если str больше, чем буфер, sprintf может вызвать переполнение буфера.

Коррекция — использует snprintf с Buffer Size

Одна возможная коррекция должна использовать snprintf вместо этого и задайте buffer size.

#include <stdio.h>
#include <string.h>
#include <iostream>

#define BUFF_SIZE 128


int dangerous_func(char *str)
{
    char dst[BUFF_SIZE];
    int r = 0;

    if (snprintf(dst, sizeof(dst), "%s", str) == 1)
    {
        r += 1;
        dst[BUFF_SIZE-1] = '\0';
    }
    
    return r;
}
Проблема

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

Риск

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

Фиксация

Используйте спецификатор формата, который совместим с размером буфера памяти.

Пример - переполнение буфера памяти
#include <stdio.h>

void func (char *str[]) {
    char buf[32];
    sscanf(str[1], "%33c", buf);
}

В этом примере, buf может содержать 32 char элементы. Поэтому спецификатор формата %33c вызывает переполнение буфера.

Коррекция — использует меньшую точность в спецификаторе формата

Одна возможная коррекция должна использовать меньшую точность в спецификаторе формата.

#include <stdio.h>

void func (char *str[]) {
    char buf[32];
    sscanf(str[1], "%32c", buf);
}
Проблема

Целевое переполнение буфера в обработке строк происходит, когда определенные функции обработки строк пишут в свой целевой буферный аргумент при смещении, больше, чем buffer size.

Например, при вызове функционального sprintf(char* buffer, const char* format), вы используете постоянную строку format из большего размера, чем buffer.

Риск

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

Фиксация

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

  • Если вы используете sprintf чтобы записать отформатированные данные в строку, используйте snprintf, _snprintf или sprintf_s вместо этого осуществлять управление длиной. В качестве альтернативы используйте asprintf автоматически выделить память, требуемую для целевого буфера.

  • Если вы используете vsprintf чтобы записать отформатированные данные от списка аргументов переменной до строки, используйте vsnprintf или vsprintf_s вместо этого осуществлять управление длиной.

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

Другое возможное решение состоит в том, чтобы увеличить buffer size.

Пример - переполнение буфера в sprintf Использование
#include <stdio.h>

void func(void) {
    char buffer[20];
    char *fmt_string = "This is a very long string, it does not fit in the buffer";

    sprintf(buffer, fmt_string);
}

В этом примере, buffer может содержать 20 char элементы, но fmt_string имеет больший размер.

Коррекция — использует snprintf Вместо sprintf

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

#include <stdio.h>

void func(void) {
    char buffer[20];
    char *fmt_string = "This is a very long string, it does not fit in the buffer";

    snprintf(buffer, 20, fmt_string);
}

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

Группа: 05. Символы и строки (STR)
Введенный в 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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