exponenta event banner

ISO/IEC TS 17961 [taintsink]

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

Описание

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

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

Внедрение Polyspace

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

  • Запятнанный размер массива переменной длины.

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

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

Примеры

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

Проблема

Запятнанный размер массива переменной длины определяет массивы переменной длины (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

Одной из возможных корректировок является проверка переменной размера перед созданием массива переменной длины. В этом примере перед созданием VLA проверяется, превышает ли размер 0 и меньше 40.

#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;
}
Проблема

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

Эта проверка фокусируется на динамически назначаемых буферах. Для получения информации о смещениях статического буфера см. раздел 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 может находиться вне диапазона указателей, что приводит к ошибке вне диапазона.

Коррекция - проверка индекса перед исключением

Одной из возможных корректировок является проверка значения индекса. Если индекс находится в допустимом диапазоне, продолжите с деэреференцией указателя.

#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;
}
Проблема

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

Риск

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

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

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

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

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

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

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

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

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

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

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

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