CERT C: Rule ARR38-C

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

Описание

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

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

Реализация Polyspace

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

  • Не сочетайтесь между длиной данных и размером.

  • Недопустимое использование стандартной стандартной программы библиотеки memory.

  • Возможное неправильное употребление sizeof.

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

  • Недопустимое использование стандартной библиотеки представляет стандартную программу в виде строки.

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

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

Примеры

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

Проблема

Не сочетайтесь между длиной данных, и размер ищет функции копирования памяти, такие как memcpy, memset, или memmove. Если вы не управляете аргументом аргумента длины и буфера данных правильно, Средство поиска Ошибки повышает дефект.

Риск

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

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

Этот дефект похож на SSL ошибка Heartbleed.

Фиксация

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

Пример - буфер копии данных

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

typedef struct buf_mem_st {
    char *data;
    size_t max;     /* size of buffer */
} BUF_MEM;

extern BUF_MEM beta;

int cpy_data(BUF_MEM *alpha)
{
    BUF_MEM *os = alpha;
    int num, length;

    if (alpha == 0x0) return 0;
    num = 0;

    length = *(unsigned short *)os->data;
    memcpy(&(beta.data[num]), os->data + 2, length);

    return(1);
}

Эта функция копирует буферный alpha в буферный beta. Однако length переменная не связана с data+2.

Коррекция — длина буфера проверки

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

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

typedef struct buf_mem_st {
    char *data;
    size_t max;     /* size of buffer */
} BUF_MEM;

extern BUF_MEM beta;

int cpy_data(BUF_MEM *alpha)
{
    BUF_MEM *os = alpha;
    int num, length;

    if (alpha == 0x0) return 0;
    num = 0;

    length = *(unsigned short *)os->data;
    if (length<(os->max -2)) {
        memcpy(&(beta.data[num]), os->data + 2, length); 
    }

    return(1);

}

Проблема

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

Риск

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

Фиксация

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

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

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

Пример - недопустимое использование стандартной ошибки стандартной программы библиотеки Memory

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

char* Copy_First_Six_Letters(void)
 {
  char str1[10],str2[5];

  printf("Enter string:\n");
  scanf("%s",str1);

  memcpy(str2,str1,6); 
  /* Defect: Arguments of memcpy invalid: str2 has size < 6 */

  return str2;
 }

Размер строки str2 5, но шесть символов строки str1 копируются в str2 использование memcpy функция.

Коррекция — вызывает функцию с допустимыми аргументами

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

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

char* Copy_First_Six_Letters(void)
 {
  /* Fix: Declare str2 with size 6 */
  char str1[10],str2[6]; 

  printf("Enter string:\n");
  scanf("%s",str1);

  memcpy(str2,str1,6);
  return str2;
 }

Проблема

Возможное неправильное употребление sizeof происходит, когда Polyspace® Bug Finder™ обнаруживает возможно непреднамеренные результаты использования sizeof оператор. Например:

  • Вы используете sizeof оператор на имени параметра массива, ожидая размер массивов. Однако имя параметра массива отдельно является указателем. sizeof оператор возвращает размер того указателя.

  • Вы используете sizeof оператор на элементе массива, ожидая размер массивов. Однако оператор возвращает размер элемента массива.

  • Аргумент размера определенных функций, таких как strncmp или wcsncpy является неправильным, потому что вы использовали sizeof оператор ранее с возможно неправильными ожиданиями. Например:

    • В вызове функции strncmp(string1, string2, num), num получен из неправильного использования sizeof оператор на указателе.

    • В вызове функции wcsncpy(destination, source, num), num не количество широких символов, но размера в байтах, полученных при помощи sizeof оператор. Например, вы используете wcsncpy(destination, source, sizeof(destination) - 1) вместо wcsncpy(destination, source, (sizeof(desintation)/sizeof(wchar_t)) - 1).

Риск

Неправильное использование sizeof оператор может вызвать следующие проблемы:

  • Если вы ожидаете sizeof оператор к размеру возвращаемого массива и используют возвращаемое значение, чтобы ограничить цикл, количество запусков цикла меньше, чем, что вы ожидаете.

  • Если вы используете возвращаемое значение sizeof оператор, чтобы выделить буфер, buffer size меньше, чем, чего вы требуете. Недостаточный буфер может привести к результирующим слабым местам, таким как переполнение буфера.

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

Фиксация

Возможные меры:

  • Не используйте sizeof оператор на имени параметра массива или элементе массива, чтобы определить размер массивов.

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

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

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

#define MAX_SIZE 1024

void func(int a[MAX_SIZE]) {
    int i;

    for (i = 0; i < sizeof(a)/sizeof(int); i++)    {
        a[i] = i + 1;
    }
}

В этом примере, sizeof(a) возвращает размер указателя a а не размер массивов.

Коррекция — определяет размер массивов в другом отношении

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

#define MAX_SIZE 1024

void func(int a[MAX_SIZE]) {
    int i;

    for (i = 0; i < MAX_SIZE; i++)    {
        a[i] = i + 1;
    }
}

Проблема

Переполнение буфера от неправильного спецификатора формата строки происходит когда аргумент спецификатора формата для функций, таких как 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);
}

Проблема

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

Риск

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

Фиксация

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

char * strcpy(char * destination, const char* source)
попытки скопировать слишком много байтов в целевой аргумент по сравнению с доступным буфером, ограничьте исходный аргумент перед вызовом strcpy. В некоторых случаях можно использовать альтернативную функцию, чтобы избежать ошибки. Например, вместо strcpy, можно использовать strncpy управлять количеством скопированных байтов. См. также Интерпретируют Результаты Polyspace Bug Finder.

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

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

Пример - недопустимое использование стандартной ошибки стандартной программы строки библиотеки

 #include <string.h>
 #include <stdio.h>
 
 char* Copy_String(void)
 {
  char *res;
  char gbuffer[5],text[20]="ABCDEFGHIJKL";

  res=strcpy(gbuffer,text); 
  /* Error: Size of text is less than gbuffer */

  return(res);
 }

Строка text больше в размере, чем gbuffer. Поэтому функциональный strcpy не может скопировать text в gbuffer.

Коррекция — использует допустимые аргументы

Одна возможная коррекция должна объявить целевую строку gbuffer с равным или большим размером, чем исходная строка text.

#include <string.h>
 #include <stdio.h>
 
 char* Copy_String(void)
 {
  char *res;
  /*Fix: gbuffer has equal or larger size than text */
  char gbuffer[20],text[20]="ABCDEFGHIJKL";

  res=strcpy(gbuffer,text);

  return(res);
 }

Проблема

Целевое переполнение буфера в обработке строк происходит, когда определенные функции обработки строк пишут в свой целевой буферный аргумент при смещении, больше, чем 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);
}

Проблема

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

Например, для функционального sprintf(char* buffer, const char* format), вы получаете buffer от операции buffer = (char*)arr; ... buffer += offset;. arr массив и offset отрицательная величина.

Риск

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

Фиксация

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

Пример - недостаточное наполнение буфера в sprintf Использование

#include <stdio.h>
#define offset -2

void func(void) {
    char buffer[20];
    char *fmt_string ="Text";

    sprintf(&buffer[offset], fmt_string);     
}

В этом примере, &buffer[offset] при отрицательном смещении из памяти, выделенной buffer.

Коррекция — указатель изменения Decrementer

Одна возможная коррекция должна изменить значение offset.

#include <stdio.h>
#define offset 2

void func(void) {
    char buffer[20];
    char *fmt_string ="Text";

    sprintf(&buffer[offset], fmt_string);     
}

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

Группа: правило 06. Массивы (ARR)

Введенный в 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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