V2671. MISRA. Pointers returned by the function 'localeconv' / 'getenv' / 'setlocale' / 'strerror' should be used as if they have pointer to const-qualified type.
Диагностическое правило основано на руководстве MISRA (Motor Industry Software Reliability Association) по разработке программного обеспечения.
Правило актуально только для языка C.
Указатели, возвращаемые из функций localeconv, getenv, setlocale, strerror, должны быть использованы как указатели на const-квалифицированный тип.
Согласно стандарту C поведение не определено (C23, Annex J, J.2, пп. 119, 121, 189), если программа модифицирует:
- объект типа
lconvчерез указатель, полученный путём вызоваlocaleconv; - строку через указатель, полученный путём вызова одной из функций:
getenv,setlocaleилиstrerror.
Рассмотрим пример:
char *GetPath(void)
{
char *path = getenv("PATH"); // <=
if (path == NULL)
{
return NULL;
}
for (size_t i = 0; i < strlen(path); ++i)
{
if (path[i] == '\\')
{
path[i] = '/';
}
}
return path;
}
Из переменной окружения PATH получают значение с помощью функции getenv. Она возвращает указатель на внутренний буфер, в котором программист заменяет все вхождения символа \ на /. Затем полученный буфер возвращают из функции через указатель. Так как это внутренний буфер, используемый стандартной библиотекой, он может быть использован другими функциями. Его прямая модификация ведёт к неопределённому поведению.
Корректная реализация предполагает копирование строки в отдельный буфер, который затем будет модифицирован:
char *GetPath(void)
{
const char * const path = getenv("PATH");
if (path == NULL)
{
return NULL;
}
size_t len = strlen(path);
char *buffer = malloc((len + 1) * sizeof(char));
if (buffer == NULL)
{
return NULL;
}
buffer[len] = '\0';
for (size_t i = 0; i < len; ++i)
{
if (path[i] == '\\')
{
buffer[i] = '/';
}
else
{
buffer[i] = path[i];
}
}
return buffer;
}
Данная диагностика классифицируется как:
|