CERT C: Rec. INT04-C

Осуществите пределы на целочисленных значениях, происходящих из испорченных источников

Описание

Управляйте определением

Осуществите пределы на целочисленных значениях, происходящих из испорченного sources.[1]

Реализация Polyspace

Это средство проверки проверяет на эти проблемы:

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

  • Цикл ограничен с испорченным значением.

  • Выделение памяти с испорченным размером.

  • Испорченный размер массива переменной длины.

Примеры

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

Проблема

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

Риск

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

  • Недостаточное наполнение буфера / подписывает — пишущий в память перед началом буфера.

  • Переполнение буфера — пишущий в память после конца буфера.

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

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

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

Фиксация

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

Пример - индекс использования, чтобы возвратить буферность
#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;
	}
}

Проблема

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

Риск

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

Фиксация

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

Пример - контур цикла от входного параметра
#include<stdio.h>
enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

int taintedloopboundary(void) {
    int count;
    scanf("%d", &count);
    int res = 0;
    for (int i=0 ; i < count; ++i) {
        res += i;
    }
    return res;
}

В этом примере функция использует входной параметр, чтобы циклично выполнить count \times. count мог быть любой номер, потому что значение не проверяется прежде, чем запустить for цикл.

Коррекция: зафиксируйте испорченное управление циклом

Одна возможная коррекция должна зафиксировать испорченное управление циклом. Подтверждать испорченную переменную цикла count, этот пример ограничивает count к минимальному значению и максимальному значению при помощи подставляемых функций min и max. Независимо от ввода данных пользователем, значения count остается в известной области значений.

#include<stdio.h>
#include<algorithm>
#define MIN 50
#define MAX 128
static  inline int max(int a, int b) { return a > b ? a : b;}
static inline int min(int a, int b) { return a < b ? a : b; }

int taintedloopboundary(void) {
	int count;
	scanf("%d", &count);
	int res = 0;
	count = max(MIN, min(count, MAX));
	for (int i=0 ; i<count ; ++i) { 
		res += i;
	} 
	return res;
}
Коррекция — проверка испорченное управление циклом

Другая возможная коррекция должна проверять нижнюю границу и верхнюю границу испорченной переменной контура цикла прежде, чем запустить for цикл. Этот пример проверяет нижние и верхние границы count и выполняет цикл только когда count между 0 и 127.

#include<stdio.h>

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};


int taintedloopboundary(void) {
    int count;
    scanf("%d", &count);
    int res = 0;

    if (count>=0 && count<SIZE128) {
        for (int i=0 ; i<count ; ++i) { 
            res += i;
        }
    }
    return res;
}
Проблема

Выделение памяти с испорченным размером проверяет функции выделения памяти, такие как calloc или malloc, для аргументов размера из необеспеченных источников.

Риск

Неконтролируемое выделение памяти может заставить вашу программу запрашивать слишком много системной памяти. Это последствие может привести к катастрофическому отказу из-за условия из памяти, или присваивающий слишком много ресурсов.

Фиксация

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

Пример - выделяет память Используя вход от пользователя
#include<stdio.h>
#include <stdlib.h>

int* bug_taintedmemoryallocsize(void) {
    size_t size;
    scanf("%zu", &size);
    int* p = (int*)malloc(size);
    return p;
}

В этом примере, malloc выделяет size байты памяти для указателя p. Переменная size прибывает от пользователя программы. Его значение не проверяется, и это могло быть больше, чем сумма доступной памяти. Если size больше, чем количество доступных байтов, ваша программа могла отказать.

Коррекция — Размер Проверки Памяти, которая будет Выделена

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

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

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

int* corrected_taintedmemoryallocsize(void) {
    size_t size;
    scanf("%zu", &size);
    int* p = NULL;
    if (size>0 && size<SIZE128) {          /* Fix: Check entry range before use */
        p = (int*)malloc((unsigned int)size);
    }
    return p;
}
Проблема

Испорченный размер массива переменной длины обнаруживает массивы переменной длины (VLA), размер которых из небезопасного источника.

Риск

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

Если размер неположителен, поведение VLA не определено. Ваша программа не выполняет как ожидалось.

Если размер неограничен, VLA может вызвать исчерпание памяти или переполнение стека.

Фиксация

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

Пример - входной параметр, используемый в качестве размера VLA
#include<stdio.h>
#inclule<stdlib.h>
#define LIM 40

long squaredSum(int size) {

	int tabvla[size];
	long res = 0;
	for (int i=0 ; i<LIM-1 ; ++i) {
		tabvla[i] = i*i;
		res += tabvla[i];
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}

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

Коррекция — проверяет размер VLA

Одна возможная коррекция должна проверять переменную размера прежде, чем создать массив переменной длины. Этот пример проверяет, больше ли размер, чем 0 и меньше чем 40, прежде, чем создать VLA

#include <stdio.h>
#include <stdlib.h>
#define LIM 40

long squaredSum(int size) {
	long res = 0;
	if (size>0 && size<LIM){
		int tabvla[size];
		for (int i=0 ; i<size || i<LIM-1 ; ++i) {
			tabvla[i] = i*i;
			res += tabvla[i];
		}
	}else{
		res = -1;
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}

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

Группа: Rec. 04. Целые числа (INT)
Введенный в R2019a

[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

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

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