﻿# V2671\. MISRA\. Pointers returned by the function 'localeconv' / 'getenv' / 'setlocale' / 'strerror' should be used as if they have pointer to const\-qualified type\.

Диагностическое правило основано на руководстве [MISRA](https://misra.org.uk/) \(Motor Industry Software Reliability Association\) по разработке программного обеспечения\.

Правило актуально только для языка C\.

Указатели, возвращаемые из функций [`localeconv`](https://cppreference.com/w/c/locale/localeconv.html), [`getenv`](https://en.cppreference.com/w/c/program/getenv.html), [`setlocale`](https://en.cppreference.com/w/c/locale/setlocale.html), [`strerror`](https://en.cppreference.com/w/c/string/byte/strerror.html), должны быть использованы как указатели на `const`\-квалифицированный тип\.

Согласно стандарту C поведение не определено \(C23, Annex J, J\.2, пп\. [119](https://open-std.org/JTC1/SC22/WG14/www/docs/n3220.pdf#page=607), [121](https://open-std.org/JTC1/SC22/WG14/www/docs/n3220.pdf#page=607), [189](https://open-std.org/JTC1/SC22/WG14/www/docs/n3220.pdf#page=610)\), если программа модифицирует:

* объект типа [`lconv`](https://cppreference.com/w/c/locale/lconv.html) через указатель, полученный путём вызова `localeconv`;
* строку через указатель, полученный путём вызова одной из функций: `getenv`, `setlocale` или `strerror`\.

Рассмотрим пример:

```cpp
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`\. Она возвращает указатель на внутренний буфер, в котором программист заменяет все вхождения символа `\` на `/`\. Затем полученный буфер возвращают из функции через указатель\. Так как это внутренний буфер, используемый стандартной библиотекой, он может быть использован другими функциями\. Его прямая модификация ведёт к неопределённому поведению\.

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

```cpp
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;
}
```