exponenta event banner

ISO/IEC TS 17961 [адрес]

Удаление адреса автоматического объекта

Описание

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

Утечка адреса автоматического объекта. [1 ]

Внедрение Polyspace

Эта проверка проверяет наличие следующих проблем:

  • Указатель или ссылка на переменную стека, покидающую область.

  • Использование автоматической переменной в качестве аргумента функции putenv-family.

Примеры

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

Проблема

Указатель или ссылка на переменную стека, покидающую область, возникает, когда указатель или ссылка на локальную переменную выходит из области действия переменной. Например:

  • Функция возвращает указатель на локальную переменную.

  • Назначение выполняется функцией globPtr = &locVar. globPtr является глобальной переменной указателя и locVar является локальной переменной.

  • Назначение выполняется функцией *paramPtr = &locVar. paramPtr является параметром функции, который является, например, int** указатель и locVar является локальным int переменная.

  • Метод C++ выполняет назначение memPtr = &locVar. memPtr является элементом данных указателя класса, которому принадлежит метод. locVar является переменной, локальной для метода.

Дефект также относится к памяти, выделенной с помощью alloca функция. Дефект не относится к статическим локальным переменным.

Риск

Локальным переменным назначается адрес в стеке. После окончания области действия локальной переменной этот адрес становится доступным для повторного использования. Использование этого адреса для доступа к значению локальной переменной вне области действия переменной может привести к непредвиденному поведению.

Если указатель на локальную переменную выходит из области действия переменной, Polyspace ® Bug Finder™ выделяет дефект. Дефект появляется, даже если адрес, сохраненный в указателе, не используется. Для поддерживаемого кода рекомендуется не разрешать указателю выходить из области действия переменной. Даже если вы сейчас не используете адрес в указателе, кто-то другой, использующий вашу функцию, может использовать адрес, вызывая неопределенное поведение.

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

Не допускайте выхода указателя или ссылки на локальную переменную из области действия переменной.

Пример - Указатель на локальную переменную, возвращаемую функцией
void func2(int *ptr) {
    *ptr = 0;
}

int* func1(void) {
    int ret = 0;
    return &ret ;
}
void main(void) {
    int* ptr = func1() ;
    func2(ptr) ;
}

В этом примере: func1 возвращает указатель на локальную переменную ret.

В main, ptr указывает на адрес локальной переменной. Когда ptr доступен в func2, доступ запрещен, поскольку область действия ret ограничивается func1,

Проблема

Использование автоматической переменной в качестве putenv- аргумент функции family возникает, когда аргумент putenvФункция -family является локальной переменной с автоматической длительностью.

Риск

Функция putenv(char *string) вставляет указатель на предоставленный аргумент в массив среды вместо создания копии аргумента. Если аргумент является автоматической переменной, его память может быть перезаписана после функции, содержащей putenv() возврат вызова. Последующий вызов getenv() из другой функции возвращает адрес переменной вне области действия, которая не может быть дереферифицирована юридически. Эта переменная вне области действия может привести к тому, что переменные среды приобретут непредвиденные значения, перестанут отвечать программе или допустят уязвимости при выполнении произвольного кода.

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

Использовать setenv()/unsetenv() для установки и отмены настройки переменных среды. В качестве альтернативы можно использовать putenv-семейные аргументы функции с динамически выделенной памятью или, если приложение не требует повторного входа, аргументы со статической длительностью. Например, выполнение одного потока без рекурсии или прерываний не требует повторного входа. Его невозможно вызвать (повторно ввести) во время выполнения.

Пример - Автоматическая переменная в качестве аргумента putenv()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE1024 1024

void func(int var)
{
    char env[SIZE1024];
    int retval = sprintf(env, "TEST=%s", var ? "1" : "0");
    if (retval <= 0) {
        /* Handle error */
    }
	/* Environment variable TEST is set using putenv().
	The argument passed to putenv is an automatic variable. */
    retval = putenv(env);   
    if (retval != 0) {
        /* Handle error */
    }
}
              

В этом примере: sprintf() сохраняет символьную строку TEST=var в env. Значение переменной среды TEST затем устанавливается в значение var с помощью putenv(). Поскольку env - автоматическая переменная, значение TEST может измениться один раз func() возвращает.

Коррекция - использование static Переменная для аргумента putenv()

Объявить env как переменная статической длительности. Расположение памяти env не перезаписывается в течение программы, даже после func() возвращает.

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

#define SIZE1024 1024 
void func(int var)
{
	/* static duration variable */
    static char env[SIZE1024]; 
    int retval = sprintf(env,"TEST=%s", var ? "1" : "0");
    if (retval <= 0) {
        /* Handle error */
    }
	
	/* Environment variable TEST is set using putenv() */
    retval=putenv(env);   
	if (retval != 0) {
        /* Handle error */
    }
}
Коррекция - использование setenv() Установка значения переменной среды

Установка значения TEST кому var, использовать setenv().

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

#define SIZE1024 1024 

void func(int var)
{
	/* Environment variable TEST is set using setenv() */
    int retval = setenv("TEST", var ? "1" : "0", 1); 
	
    if (retval != 0) {
        /* Handle error */
    }
}

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

Разрешимость: неразрешимая
Представлен в R2019a

[1] Выдержки из стандарта «ISO/IEC TS 17961 Technical Specification - 2013-11-15» воспроизводятся с согласия AFNOR. Нормативную ценность имеет только оригинальный и полный текст стандарта, опубликованный изданиями AFNOR - доступный через веб-сайт www.boutique.afnor.org.