Использование запятнанного значения для записи в объект с помощью форматированной функции ввода или вывода
Использование запятнанного значения для записи в объект с помощью форматированной функции ввода или вывода [1 ].
Эта проверка проверяет наличие следующих проблем:
Переполнение буфера из неверного спецификатора формата строки.
Переполнение буфера назначения при обработке строк.
Недопустимое использование стандартной библиотечной подпрограммы.
Недопустимое использование стандартной подпрограммы строки библиотеки.
Запятнанная строка NULL или строка, не являющаяся завершающей значение NULL.
Спецификатор затененного формата строки.
Недопустимое использование стандартной подпрограммы строки библиотеки.
Использование опасной стандартной функции.
Переполнение буфера из неверного спецификатора формата строки происходит, когда аргумент спецификатора формата для таких функций, как 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);
}Переполнение буфера назначения при обработке строк происходит, когда определенные функции обработки строк записывают в аргумент буфера назначения со смещением, большим, чем размер буфера.
Например, при вызове функции 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);
}Эта проблема возникает при использовании недопустимых аргументов с функцией из стандартной библиотеки. Этот дефект выявляет ошибки, связанные с другими функциями, не охватываемыми подпрограммами float, integer, memory или строковыми стандартными библиотеками.
Недопустимые аргументы стандартной библиотечной функции приводят к неопределенному поведению.
Исправление зависит от первопричины дефекта. Например, аргумент к printf функция может быть NULL потому что указатель был инициализирован с помощью NULL и значение инициализации не было перезаписано по определенному пути выполнения.
См. примеры исправлений ниже.
Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.
printf Без строки#include <stdio.h>
#include <stdlib.h>
void print_null(void) {
printf(NULL);
}
Функция printf принимает только входные аргументы строки или спецификаторы формата. В этой функции входное значение равно NULL, что не является допустимой строкой.
Одной из возможных корректировок является изменение входных аргументов в соответствии с требованиями стандартной библиотечной подпрограммы. В этом примере входной аргумент был изменен на символ.
#include <stdio.h>
void print_null(void) {
char zero_val = '0';
printf((const char*)zero_val);
}
При вызове функции библиотеки строк с недопустимыми аргументами происходит недопустимое использование стандартной подпрограммы строк библиотеки.
Риск зависит от типа недопустимых аргументов. Например, использование 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);
}
Эта проблема возникает, когда строки из небезопасных источников используются в подпрограммах обработки строк, которые неявно отменяют ссылку на буфер строк, например, strcpy или sprintf.
Средство проверки не вызывает дефектов для строки, возвращенной при вызове scanf-семейные вариадные функции. Аналогично, при передаче строки с помощью %s спецификатор для printf-семейные вариадные функции.
Если строка получена из небезопасного источника, возможно, что злоумышленник манипулировал строкой или направил указатель строки в другое место памяти.
Если строка имеет значение NULL, подпрограмма строки не может отменить привязку строки, что приводит к сбою программы. Если строка не оканчивается на NULL, программа строки может не знать, когда она закончится. Эта ошибка может привести к нарушению границ записи, что приведет к переполнению буфера.
Проверьте строку перед ее использованием. Проверьте, что:
Строка не имеет значение NULL.
Строка имеет нулевое окончание
Размер строки соответствует ожидаемому размеру.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SIZE128 128
#define MAX 40
extern void print_str(const char*);
void warningMsg(void)
{
char userstr[MAX];
read(0,userstr,MAX);
char str[SIZE128] = "Warning: ";
strncat(str, userstr, SIZE128-(strlen(str)+1));
print_str(str);
}
void errorMsg(void)
{
char userstr[MAX];
read(0,userstr,MAX);
char str[SIZE128] = "Error: ";
strncat(str, userstr, SIZE128-(strlen(str)+1));
print_str(str);
}В этом примере строка str сцеплен с аргументом userstr. Значение userstr неизвестно. Если размер userstr превышает доступное пространство, конкатенация переполняется.
Одной из возможных корректировок является проверка размера userstr и убедитесь, что строка оканчивается NULL, прежде чем использовать ее в strncat. В этом примере используется вспомогательная функция, sansitize_str, для проверки строки. Дефекты сосредоточены в этой функции.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SIZE128 128
#define MAX 40
extern void print_str(const char*);
int sanitize_str(char* s) {
int res = 0;
if (s && (strlen(s) > 0)) { // Defect only raised here
// - string is not null
// - string has a positive and limited size
// - TAINTED_STRING on strlen used as a firewall
res = 1;
}
return res;
}
void warningMsg(void)
{
char userstr[MAX];
read(0,userstr,MAX);
char str[SIZE128] = "Warning: ";
if (sanitize_str(userstr))
strncat(str, userstr, SIZE128-(strlen(str)+1));
print_str(str);
}Другой возможной поправкой является вызов функции errorMsg и warningMsg с определенными строками.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE128 128
extern void print_str(const char*);
void warningMsg(char* userstr)
{
char str[SIZE128] = "Warning: ";
strncat(str, userstr, SIZE128-(strlen(str)+1));
print_str(str);
}
void errorMsg(char* userstr)
{
char str[SIZE128] = "Error: ";
strncat(str, userstr, SIZE128-(strlen(str)+1));
print_str(str);
}
int manageSensorValue(int sensorValue) {
int ret = sensorValue;
if ( sensorValue < 0 ) {
errorMsg("sensor value should be positive");
exit(1);
} else if ( sensorValue > 50 ) {
warningMsg("sensor value greater than 50 (applying threshold)...");
sensorValue = 50;
}
return sensorValue;
}Эта проблема возникает, когда printfФункции -style используют спецификатор формата, созданный из небезопасных источников.
При использовании элементов внешнего управления для форматирования строки могут возникнуть проблемы переполнения буфера или представления данных. Злоумышленник может использовать эти элементы форматирования строк для просмотра содержимого стека с помощью %x или запись в стек с помощью %n.
Передача статической строки для форматирования строковых функций. Это исправление гарантирует, что внешний исполнитель не сможет управлять строкой.
Другое возможное исправление - разрешить только ожидаемое количество аргументов. По возможности используйте функции, которые не поддерживают уязвимых %n оператор в строках формата.
#include <stdio.h>
#include <unistd.h>
#define MAX 40
void taintedstringformat(void) {
char userstr[MAX];
read(0,userstr,MAX);
printf(userstr);
}В этом примере выполняется печать входного аргумента userstr. Строка неизвестна. Если он содержит такие элементы, как %, printf может интерпретировать userstr в виде строкового формата, а не строки, что приводит к аварийному завершению программы.
Одной из возможных корректировок является печать userstr явно в виде строки, чтобы не было неоднозначности.
#include <stdio.h>
#include <unistd.h>
#define MAX 40
void taintedstringformat(void) {
char userstr[MAX];
read(0,userstr,MAX);
printf("%.20s", userstr);;
}Проверка использования опасной стандартной функции выделяет использование функций, которые по своей природе являются опасными или потенциально опасными в определенных обстоятельствах. В следующей таблице перечислены возможные опасные функции, риски использования каждой функции и используемые функции.
| Опасная функция | Уровень риска | Более безопасная функция |
|---|---|---|
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;
}| Разрешимость: неразрешимая |
[1] Выдержки из стандарта «ISO/IEC TS 17961 Technical Specification - 2013-11-15» воспроизводятся с согласия AFNOR. Нормативную ценность имеет только оригинальный и полный текст стандарта, опубликованный изданиями AFNOR - доступный через веб-сайт www.boutique.afnor.org.
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.