Гарантировать, что библиотечные функции не образуют недопустимые указатели
Убедитесь, что библиотечные функции не образуют недопустимые указатели. [1 ]
Эта проверка проверяет наличие следующих проблем:
Несоответствие между длиной и размером данных.
Недопустимое использование стандартной подпрограммы библиотечной памяти.
Возможное неправильное использование sizeof.
Переполнение буфера из неверного спецификатора формата строки.
Недопустимое использование стандартной подпрограммы строки библиотеки.
Переполнение буфера назначения при обработке строк.
Переполнение буфера назначения при обработке строк.
Несоответствие между длиной и размером данных ищет функции копирования памяти, такие как memcpy, memset, или memmove. Если вы не управляете аргументом длины и аргументом буфера данных должным образом, Bug Finder вызывает дефект.
Если злоумышленник может манипулировать буфером данных или аргументом длины, он может вызвать переполнение буфера, сделав фактический размер данных меньше длины.
Это несоответствие длины позволяет злоумышленнику копировать память из буфера данных в новое местоположение. Если дополнительная память содержит конфиденциальную информацию, злоумышленник теперь может получить доступ к этим данным.
Этот дефект аналогичен ошибке SSL Heartbleed.
При копировании или манипулировании памятью вычислите аргумент length непосредственно на основе данных, чтобы размеры совпадали.
#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 копирование функций в массив, который не может вместить количество скопированных байт.
Использование функции библиотеки памяти с недопустимыми аргументами может привести к таким проблемам, как переполнение буфера.
Исправление зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Исправление может быть реализовано для любого события в последовательности. Если сведения о результатах не отображают историю событий, можно выполнить обратную трассировку, щелкнув правой кнопкой мыши параметры в исходном коде и просмотреть предыдущие связанные события. См. также раздел Интерпретация результатов поиска ошибок в интерфейсе пользователя Polyspace Desktop.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.
#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 оператор для имени параметра массива, ожидающий размер массива. Однако имя параметра массива само по себе является указателем. 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 для выделения буфера, размер буфера меньше требуемого. Недостаток буфера может привести к возникновению таких недостатков, как переполнение буфера.
Если используется возвращаемое значение 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 Desktop.См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.
#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);
}
Переполнение буфера назначения при обработке строк происходит, когда определенные функции обработки строк записывают в аргумент буфера назначения со смещением, большим, чем размер буфера.
Например, при вызове функции 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);
}Недоиспользование буфера назначения при обработке строк происходит, когда определенные функции обработки строк записывают в свой аргумент буфера назначения с отрицательным смещением от начала буфера.
Например, для функции 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) |
[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.
ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОНА И/ИЛИ ЕГО ПРОГРАММНОГО ИНЖЕНЕРНОГО ИНСТИТУТА, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ КАК ЕСТЬ. УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБЫХ ВОПРОСОВ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИИ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ ТОВАРНОЙ ПРИГОДНОСТИ, ИСКЛЮЧИТЕЛЬНОСТИ ИЛИ РЕЗУЛЬТАТОВ, ПОЛУЧЕННЫХ ОТ ИСПОЛЬЗОВАНИЯ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.
Данное программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллона или его Институтом разработки программного обеспечения.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.