Гарантируйте, что библиотечные функции не формируют недопустимые указатели
Не сочетайтесь между длиной данных, и размер ищет функции копирования памяти, такие как 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 Адреса Через Исправления ошибок или Комментарии.
#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
.
Одно возможное исправление должно изменить значение offset
.
#include <stdio.h> #define offset 2 void func(void) { char buffer[20]; char *fmt_string ="Text"; sprintf(&buffer[offset], fmt_string); }
Группа: 04. Контейнеры (CTR) |
[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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.
Это программное обеспечение и сопоставленная документация не были рассмотрены, ни являются подтвержденным Университетом Карнеги-Меллон или его Институтом программной инженерии.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.