CERT C: Rule ENV31-C

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

Описание

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

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

Реализация Polyspace

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

Примеры

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

Проблема

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

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

Риск

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

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

Не используйте размещенный указатель окружения. Вместо этого используйте глобальную внешнюю переменную 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 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

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

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