Описание
Указатель среды, делаемый недействительным предыдущей операцией, происходит, когда вы используете третий аргумент основных () в размещенной среде, чтобы получить доступ к среде после того, как операция изменяет среду. В размещенной среде много реализаций C поддерживают нестандартный синтаксис:
main (int argc, char *argv[], char *envp[])
Вызов
setenv
или функции семейства
putenv
изменяет среду, на которую указывает
*envp
.
Риск
Когда вы изменяете среду через вызов setenv
или функции семейства putenv
, память среды может потенциально быть перераспределена. Размещенный указатель среды не обновляется и может указать на неправильное местоположение. Вызов этого указателя может возвратить неожиданные результаты или вызвать аварийное завершение программы.
Фиксация
Не используйте размещенный указатель среды. Вместо этого используйте глобальную внешнюю переменную environ
в Linux®, _environ
или _wenviron
в Windows® или их эквиваленте. Когда вы изменяете среду, эти переменные обновляются.
Пример - доступ к среде через указатель envp
#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();
}
}