ISO/IEC TS 17961 [addrescape]

Выход из адреса автоматического объекта

Описание

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

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

Реализация Polyspace

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

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

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

Примеры

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

Проблема

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

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

  • Функция выполняет назначение 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- аргумент функции семейства возникает, когда аргумент putenvСемейство является локальной переменной с автоматической длительностью.

Риск

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

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

Использование 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 */
    }
}

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

Решимость: Undecidable
Введенный в R2019a

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