Environment pointer invalidated by previous operation

Вызов setenv или putenv функция семейства изменяет окружение, на которую указывает указатель

Описание

Этот дефект возникает, когда вы используете третий аргумент main () в размещённом окружении для доступа к окружению после изменения операции окружения. В размещённом окружении многие реализации C поддерживают нестандартный синтаксис:

main (int argc, char *argv[], char *envp[])
Вызов setenv или putenv функция семейства изменяет окружение, на которую указывает *envp.

Риск

Когда вы изменяете окружение через вызов setenv или putenv family function, память окружения потенциально может быть перераспределена. Размещенный указатель окружения не обновляется и может указывать на неправильное расположение. Вызов этого указателя может вернуть неожиданные результаты или вызвать ненормальное завершение программы.

Зафиксировать

Не используйте размещенный указатель окружения. Вместо этого используйте глобальную внешнюю переменную environ в Linux®, _environ или _wenviron в Windows®или их эквивалент. При изменении окружения эти переменные обновляются.

Примеры

расширить все

#include <stdio.h>
#include <stdlib.h>

extern int check_arguments(int argc, char **argv, char **envp);
extern void use_envp(char **envp);

/* envp is from main function */
int func(char **envp) 
{
    /* Call to setenv may cause environment
     *memory to be reallocated 
     */
    if (setenv(("MY_NEW_VAR"),("new_value"),1) != 0) 
    {
        /* Handle error */
        return -1;
    }
    /* envp not updated after call to setenv, and may
     *point to incorrect location.
     **/
    if (envp != ((void *)0)) { 
        use_envp(envp);
/* No defect on second access to
*envp because defect already raised */
    }
    return 0;
}

void  main(int argc, char **argv, char **envp)
{
    if (check_arguments(argc, argv, envp))
    {
        (void)func(envp);
    }
}

В этом примере envp обеспечивается доступ внутри func() после вызова на setenv который может перераспределить память окружения. envp может указать на неправильное расположение, поскольку оно не обновляется после setenv изменяет окружение. Дефект не поднимается, когда use_envp() вызывается, поскольку дефект уже возник в предыдущей строке кода.

Коррекция - Используйте глобальную внешнюю переменную environ

Одной из возможных коррекций является доступ к окружению с помощью переменной, которая всегда обновляется после вызова setenv. Например, в следующем коде указатель envp все еще доступен у main(), но доступ к окружению осуществляется в func() через глобальную внешнюю переменную environ.

#include <stdio.h>
#include <stdlib.h>
extern char **environ;

extern int check_arguments(int argc, char **argv, char **envp);
extern void use_envp(char **envp);

int func(void)
{
    if (setenv(("MY_NEW_VAR"), ("new_value"),1) != 0) {
        /* Handle error */
        return -1;
    }
  /* Use global external variable environ
   *which is always updated after a call to setenv */
    
    if (environ != NULL) { 
        use_envp(environ);
    }
    return 0;
}

void  main(int argc, char **argv, char **envp)
{
    if (check_arguments(argc, argv, envp))
    {
        (void)func();
    }
} 

Информация о результатах

Группа: Программирование
Язык: C | C++
По умолчанию: On для рукописного кода, off для сгенерированного кода
Синтаксис командной строки : INVALID_ENV_POINTER
Влияние: Средний
ИДЕНТИФИКАТОР CWE: 825
Введенный в R2018a