exponenta event banner

CERT C: Rec. STR07-C

Использование интерфейсов проверки границ для обработки строк

Описание

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

Используйте интерфейсы проверки границ для обработки строк. [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
Риск

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

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

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

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

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

Пример - использование 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 с размером буфера

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

#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;
}
Проблема

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

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

Риск

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

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

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

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

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

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

Другим возможным решением является увеличение размера буфера.

Пример - Переполнение буфера в 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);
}

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

Группа: Rec. 07. Символы и строки (STR)
Представлен в R2019a

[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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