CERT C: Rule ARR38-C

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

Описание

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

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

Реализация Polyspace

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

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

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

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

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

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

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

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

Примеры

расширить все

Проблема

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

Риск

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

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

Этот дефект похож на ошибку 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);

}
Проблема

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

Риск

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

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

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

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

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

Пример - Недопустимое использование стандартной памяти библиотеки Стандартной программы Ошибки
#include <string.h>
#include <stdio.h>

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

  printf("Enter string:\n");
  scanf("%9s",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("%9s",str1);

  memcpy(str2,str1,6);
  return str2;
 }
Проблема

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

  • Вы используете sizeof оператор для имени параметра массива, ожидающий размера массива. Однако имя параметра массива само по себе является указателем. The 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 приводит к переполнению или нижнему потоку в аргументе буфера памяти.

Риск

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

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

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

Пример - переполнение буфера памяти
#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 для управления количеством скопированных байтов. Смотрите также Результаты интерпретации Bug Finder в интерфейсе пользователя Polyspace Desktop.

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

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

Коррекция - Изменение указателя на декремент

Одной из возможных коррекций является изменение значения 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 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

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

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