CERT C++: STR53-CPP

Доступ к элементу проверки области значений

Описание

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

Доступ к элементу проверки области значений.[1]

Реализация Polyspace

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

  • Доступ к массиву вне границ.

  • Доступ к массиву с испорченным индексом.

  • Разыменование указателя с испорченным смещением.

Примеры

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

Проблема

Доступ к массиву вне границ происходит, когда индекс массива падает за пределы области значений [0...array_size-1] во время доступа к массиву.

Риск

Доступ к массиву за его пределами является неопределенным поведением. Можно считать непредсказуемое значение или попытаться получить доступ к расположению, которое не разрешено, и столкнуться с отказом сегментации.

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

Исправление зависит от первопричины дефекта. Например, вы получили доступ к массиву внутри цикла, и произошла одна из следующих ситуаций:

  • Верхняя граница цикла слишком велика.

  • Вы использовали индекс массива, который совпадает с индексом цикла, а не на один меньше, чем индекс цикла.

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

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

Часто детали результата показывают последовательность событий, которые привели к дефекту. Вы можете реализовать исправление на любом событии в последовательности. Если сведения о результате не отображают историю событий, можно отследить их с помощью опций правого щелчка в исходном коде и просмотреть предыдущие связанные события. Смотрите также Результаты интерпретации Bug Finder в интерфейсе пользователя Polyspace Desktop.

См. примеры исправлений ниже.

Если вы не хотите устранять проблему, добавьте комментарии к своему результату или коду, чтобы избежать другой проверки. Смотрите Адрес Результаты Polyspace через исправления ошибок или обоснования.

Пример - ошибка доступа к массиву вне границ
#include <stdio.h>

void fibonacci(void)
{
    int i;
    int fib[10];
 
    for (i = 0; i < 10; i++) 
       {
        if (i < 2) 
            fib[i] = 1;
         else 
            fib[i] = fib[i-1] + fib[i-2];
       }

    printf("The 10-th Fibonacci number is %i .\n", fib[i]);   
    /* Defect: Value of i is greater than allowed value of 9 */
}

Область массива fib присваивается размер 10. Индекс массива для fib имеет допустимые значения [0,1,2,...,9]. Переменная i имеет значение 10, когда оно выходит из for-цикл. Поэтому printf оператор пытается получить доступ к fib[10] через i.

Коррекция - Сохраните индекс массива в пределах границ массива

Одной из возможных коррекций является печать fib[i-1] вместо fib[i] после for-цикл.

#include <stdio.h>

void fibonacci(void)
{
   int i;
   int fib[10];

   for (i = 0; i < 10; i++) 
    {
        if (i < 2) 
            fib[i] = 1;
        else 
            fib[i] = fib[i-1] + fib[i-2];
    }

    /* Fix: Print fib[9] instead of fib[10] */
    printf("The 10-th Fibonacci number is %i .\n", fib[i-1]); 
}

The printf доступ к оператору fib[9] вместо fib[10].

Проблема

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

Риск

Возможно, индекс находится вне допустимой области значений массивов. Если испорченный индекс находится вне области значений массивов, это может вызвать:

  • Buffer underflow/underwrite - запись в память перед началом буфера.

  • Переполнение буфера - запись в память после окончания буфера.

  • Перечитывание буфера - доступ к памяти после окончания целевого буфера.

  • Недостаточное чтение буфера или доступ к памяти перед началом целевого буфера.

Атакующий может использовать недопустимую операцию чтения или записи, созданную для проблем в вашей программе.

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

Прежде чем использовать индекс для доступа к массиву, проверьте значение индекса, чтобы убедиться, что он находится внутри области значений массива.

Пример - Используйте индекс для возврата значения буфера
#include <stdlib.h>
#include <stdio.h>
#define SIZE100 100
extern int tab[SIZE100];
static int tainted_int_source(void) {
  return strtol(getenv("INDEX"),NULL,10);
}
int taintedarrayindex(void) {
	int num = tainted_int_source();
    return tab[num];  
}

В этом примере индекс num обращается к массиву tab. Область индекса num получается из небезопасного источника и функции taintedarrayindex не проверяет, чтобы увидеть num находится внутри области значений tab.

Коррекция - Проверяйте область значений перед использованием

Одной из возможных коррекций является проверка того num находится в области значений перед использованием.

#include <stdlib.h>
#include <stdio.h>
#define SIZE100 100
extern int tab[SIZE100];
static int tainted_int_source(void) {
	return strtol(getenv("INDEX"),NULL,10);
}
int taintedarrayindex(void) {
	int num = tainted_int_source();
	if (num >= 0 && num < SIZE100) {
		return tab[num]; 
	} else {
		return -1;
	}
}

Проблема

Разыменование указателя с испорченным смещением обнаруживает разыгрывание указателя, чтение или запись, с помощью переменной смещения от неизвестного или небезопасного источника.

Эта проверка фокусируется на динамически выделенных буферах. Для статических смещений буфера смотрите Array access with tainted index.

Риск

Возможно, индекс находится вне допустимой области значений массивов. Если испорченный индекс находится вне области значений массивов, это может вызвать:

  • Подземный поток буфера/андеррайт или запись в память перед началом буфера.

  • Переполнение буфера или запись в память после окончания буфера.

  • Над чтением буфера или доступом к памяти после окончания целевого буфера.

  • Недостаточное чтение буфера или доступ к памяти перед началом целевого буфера.

Атакующий может использовать недопустимое чтение или запись, чтобы скомпрометировать вашу программу.

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

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

Пример - Массив указателей на размежевание
#include <stdio.h>
#include <stdlib.h>
enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};
extern void read_pint(int*);

int taintedptroffset(void) {
    int offset;
    scanf("%d",&offset);
    int* pint = (int*)calloc(SIZE10, sizeof(int));
    int c = 0;
    if(pint) {
        /* Filling array */
        read_pint(pint);
        c = pint[offset];
        free(pint);
    }
    return c;
}

В этом примере функция инициализирует целочисленный указатель pint. Удаление указателя осуществляется с помощью индекса входа offset. Значение offset может находиться вне области значений указателя, вызывая ошибку вне области допустимого значения.

Коррекция - Проверяйте индекс перед дереференцией

Одной из возможных коррекций является подтверждение значения offset. Продолжите разметку указателя только в том случае, если offset находится внутри допустимой области значений.

#include <stdlib.h>
#include <stdio.h>
enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};
extern void read_pint(int*);

int taintedptroffset(void) {
    int offset;
    scanf("%d",&offset);
    int* pint = (int*)calloc(SIZE10, sizeof(int));
    int c = 0;
    if (pint) {
        /* Filling array */
        read_pint(pint);
        if (offset>0 && offset<SIZE10) {
            c = pint[offset];
        }
        free(pint);
    }
    return c;
}

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

Группа: 05. Символы и строки (STR)
Введенный в R2019a

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

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

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