exponenta event banner

Указатель среды недействителен предыдущей операцией

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

Описание

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

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

Риск

При изменении среды с помощью вызова setenv или putenv функция семейства, память среды потенциально может быть перераспределена. Указатель размещенной среды не обновлен и может указывать на неправильное расположение. Вызов этого указателя может привести к неожиданным результатам или к аварийному завершению программы.

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

Не используйте указатель размещенной среды. Вместо этого используйте глобальную внешнюю переменную 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++
По умолчанию: Вкл для рукописного кода, выкл для сгенерированного кода
Синтаксис командной строки: INVALID_ENV_POINTER
Воздействие: среднее
CWE ID: 825
Представлен в R2018a