exponenta event banner

CERT C: ENV31-C правил

Не полагаться на указатель среды после операции, которая может сделать его недействительным

Описание

Определение правила

Не полагайтесь на указатель среды после операции, которая может сделать его недействительным. [1 ]

Внедрение Polyspace

Эта проверка проверяет наличие указателя среды, недействительного в предыдущей операции.

Примеры

развернуть все

Проблема

Указатель среды, недействительный предыдущей операцией, возникает при использовании третьего аргумента main () в размещенной среде для доступа к среде после того, как операция изменит среду. В размещенной среде многие реализации 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();
    }
} 

Проверить информацию

Группа: Правило 10. Окружающая среда (ENV)
Представлен в R2019a

[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОНА И/ИЛИ ЕГО ПРОГРАММНОГО ИНЖЕНЕРНОГО ИНСТИТУТА, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ КАК ЕСТЬ. УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБЫХ ВОПРОСОВ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИИ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ ТОВАРНОЙ ПРИГОДНОСТИ, ИСКЛЮЧИТЕЛЬНОСТИ ИЛИ РЕЗУЛЬТАТОВ, ПОЛУЧЕННЫХ ОТ ИСПОЛЬЗОВАНИЯ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Данное программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллона или его Институтом разработки программного обеспечения.