TMPA-2013 Vert Krikun: Finding Defects in C and C++ Pointers Using Static Analysis and Logical...

Preview:

DESCRIPTION

Vert, Т., Krikun, Т. и Glukhih, М., St. Petersburg State Polytechnic University, Clausthal Technical University Finding Defects in C and C++ Pointers Using Static Analysis and Logical Inference

Citation preview

Обнаружение дефектов работы с указателями в программах на языках C/C++ с использованием статического

анализа и логического вывода

Татьяна Верт, Татьяна Крикун (Санкт-Петербургскийгосударственный политехнический университет)

Михаил Глухих (Технический университет Клаусталя)

Программное обеспечение содержит ошибки

Функциональные ошибки

o Программа не соответствует спецификации

Нефункциональные ошибки (программные дефекты)

o Использование неинициализированных переменных

o Некорректное использование указателей

o Выходы за границы массивов

2

Полнота – доля истинных обнаруженных дефектовсреди всех дефектов, имеющихся в программе

Точность – доля истинных обнаруженных дефектовсреди всех обнаруженных дефектов

3

Два из Трех

Высокая полнота

Высокая точность

Низкая ресурсоемкость

4

Анализ всех путей программы

Раздельный анализ путей (высокая точность и высокая ресурсоёмкость)

Совместный анализ путей (приемлемая ресурсоёмкость и низкая точность)

5

Зависимость – произвольная связь междузначениями двух и более переменныхпрограммы

Математически, зависимость может бытьпредставлена в виде предиката

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

6

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

7

8

9

Предикаты

Точные значения (i=const, p=&obj+shift)

Предикаты общего вида(type(obj1, obj2, ...) is

true)

Анализ точных значений

Анализ зависимостей

Хранение состояния анализируемой программы ввиде множества предикатов логики первого порядка

10

Извлечение предикатов при интерпретации операторов

Типы предикатов:

– арифметические (A=B+C, A=B*C, A=B%C, и т. д.)

– логические (A=¬B, A=B∨D, A=B∧D, A→B)

– сравнения (A>B, A<B, A≥B, A≤B, A≠B)

– работа с указателями(A=&B+C, A=*B)

– обращение к составному объекту(A=B[C], A=B.C)

– размер объекта(A = sizeof B, A ≤ sizeof B)

– …

Представление: 𝑝(𝑣1, 𝑣2, … , 𝑣𝑛), где 𝑝 -функциональный символ, 𝑣𝑖 , 𝑖 = 1…𝑛 – предикатныепеременные 11

Переменными предикатов являются другие предикаты

Примеры:

– 𝑜𝑛𝑒𝑜𝑓 𝑝1, 𝑝2 – истинен хотя бы один из двух предикатов 𝑝1, 𝑝2

– 𝑜𝑝𝑝𝑜𝑠(𝑝) – предикат 𝑝 ложен

– 𝑒𝑞𝑢𝑖𝑣 𝑝1, 𝑝2 – предикаты 𝑝1 и 𝑝2 одновременно истинны или одновременно ложны

Сложные предикаты также могут быть описаны в

терминах логики первого порядка

12

Представление переменных на основе статическогооднократного присваивания (SSA):

– Каждой переменной значение присваиваетсятолько один раз;

– В случае присвоения нескольких значенийиспользуется версионирование переменных.

x = a + b; x.1 = a.1 + b.1;

y = x * x; y.1 = x.1 * x.1;

x = c + d; x.2 = c.1 + d.1;

𝑠𝑢𝑚 𝑥1, 𝑎1, 𝑏1mult 𝑦1, 𝑥1, 𝑥1s𝑢𝑚 𝑥2, 𝑐1, 𝑑1

13

Выявление зависимостей при интерпретации:

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

– операторов прямого присваивания lvar=…

• Присваивания lvar=rvar

• Присваивания lvar=binary(arg1, arg2)

• Присваивания lvar=unary(rvar)

• Присваивания адреса lvar=&rvar

• Присваивания через косвенную адресациюlvar=*rvar

– операторов косвенного присваивания *lvar=rvalue

– операторов ветвления if (cond)

– операторов выделения/освобождения памяти

14

Объединение состояний программы в точках слиянияпутей

Любое условие сохраняется на выходе фи-функциитолько в том случае, если оно имелось на всех еёвходах

Если некоторой переменной программы𝑣 соответствуют разные предикатные переменные𝑣1 и 𝑣2 во входных состояниях, то для неё создаетсяновая предикатная переменная 𝑣3, при этом ввыходное состояние добавляется предикат𝑜𝑛𝑒𝑜𝑓(𝑒𝑞𝑢𝑎𝑙𝑠(𝑣3, 𝑣1), 𝑒𝑞𝑢𝑎𝑙𝑠(𝑣3, 𝑣2))

15

Если объект имеет разные версии в разных ветвях условного оператора, предикат, описывающий его значение, следует привязать к условию оператора if

Пример: Предикатное состояние

if (size > 0)

q = malloc(size);

else

q = 0;

16

Истинная ветвь Ложная ветвь

𝑔𝑟𝑒𝑎𝑡𝑒𝑟 𝑠𝑖𝑧𝑒1, 0 𝑙𝑒𝑠𝑠_𝑒𝑞𝑢𝑎𝑙𝑠 𝑠𝑖𝑧𝑒1, 0

𝑠𝑖𝑧𝑒𝑜𝑓 𝑑𝑦𝑛, 𝑠𝑖𝑧𝑒1 𝑒𝑞𝑢𝑎𝑙𝑠 𝑞2, 0

𝑝𝑡𝑟 𝑑𝑦𝑛, 𝑞1, 0

Выходное состояние

𝑜𝑛𝑒𝑜𝑓(𝑒𝑞𝑢𝑎𝑙𝑠(𝑞3, 𝑞1), 𝑒𝑞𝑢𝑎𝑙𝑠(𝑞3, 𝑞2))

𝑒𝑞𝑢𝑖𝑣(𝑙𝑒𝑠𝑠_𝑒𝑞𝑢𝑎𝑙𝑠 𝑠𝑖𝑧𝑒1, 0 , 𝑒𝑞𝑢𝑎𝑙𝑠 𝑞3, 0 )

17

Обнаружение дефектов при анализе операцииразадресации *ptr и операции обращения по индексуptr[i]

• Некорректное использование указателей:int* ptr = 0;

if (array[0]>0)

ptr=array;

int val=*ptr; //разадресация нулевого указателя

• Выход за границу объектаint a, i;

int array[9];

i = 10;

a = array[i]; //выход за границу массива

Корректность указателя

p = (void*)(&t)+s; v = sizeof(t);

𝑝𝑡𝑟 𝑡, 𝑝, 𝑠 , 𝑠𝑖𝑧𝑒𝑜𝑓 𝑡, 𝑣 , 𝑔𝑟𝑒𝑎𝑡𝑒𝑟_𝑒𝑞𝑢𝑎𝑙𝑠(𝑠, 0), 𝑙𝑒𝑠𝑠(𝑠, 𝑣)

𝑐𝑜𝑟𝑟𝑒𝑐𝑡_𝑝𝑡𝑟(𝑝)

Разадресация указателя v = *p;

1) Указатель на простую переменную

p = (void*)(&t);𝑝𝑡𝑟 𝑡,𝑝,0 ,𝑑𝑒𝑟𝑒𝑓(𝑝,𝑣)

𝑒𝑞𝑢𝑎𝑙𝑠(𝑡,𝑣)

2) Указатель на элемент составного объекта

p = (void*)(&a)+s; t = *(&a +s);

𝑝𝑡𝑟 𝑎, 𝑝, 𝑠 , 𝑎𝑟𝑟 𝑎, 𝑡, 𝑠 , 𝑑𝑒𝑟𝑒𝑓(𝑝, 𝑣)

𝑒𝑞𝑢𝑎𝑙𝑠(𝑡, 𝑣)

18

Сложение указателя с целочисленной константойp = (void*)(&a)+s; t=s+b; q = p+b;

𝑝𝑡𝑟 𝑎, 𝑝, 𝑠 , 𝑠𝑢𝑚 𝑡, 𝑠, 𝑏 , 𝑠𝑢𝑚(𝑞, 𝑝, 𝑏)

𝑝𝑡𝑟(𝑎, 𝑞, 𝑡)

19

Присутствие дефекта – доказательство

разрешимости предикатов:

– нулевой указатель:𝑒𝑞𝑢𝑎𝑙𝑠(𝑝𝑡𝑟, 0)

– некорректный указатель: 𝑜𝑝𝑝𝑜𝑠(𝑐𝑜𝑟𝑟𝑒𝑐𝑡_𝑝𝑡𝑟(𝑝𝑡𝑟))

Отсутствие дефекта – неразрешимость предикатов

20

… Предикаты

int x,b; sizeof(arr, 20),

std::cin >> x; equals(arr[0]_0, 0),

int arr[5]={0,1,2,3,4}; equals(arr[1]_0, 1),

if (x>0){ equals(arr[2]_0, 2),

b = arr[x]; equals(arr[3]_0, 3),

} equals(arr[4]_0, 4),

… greater(x_0, 0),

ptr(arr, tmp1_0, 0)),

mult(tmp2_0, x_0, 4),

sum(tmp3_0, tmp1_0,tmp2_0)

ptr(arr, tmp3, tmp2), sizeof(arr, 20), or(less(tmp2, 0),

greater_equals(tmp2, 20)) = > oppos(correct_ptr(tmp3))

21

Доказатели теорем

– HOL Theorem Prover

Языки логического программирования

– Bprolog

SMT-решатели

– Z3

22

Средство-прототип

23

24

Пример Истинных

дефектов

Разработанная

система

Aegis

(Digitek Labs)

FlexeLint

(Gimpel Software)

дефектов

найдено

ложных

дефектов

найдено

дефектов

найдено

ложных

дефектов

найдено

дефектов

найдено

ложных

дефектов

найдено

1 1 1 0 1 0 1 0

2 2 2 0 0 0 0 0

3 1 1 0 1 0 0 0

4 2 2 0 3 1 3 1

5 0 0 0 1 1 1 1

6 2 2 0 3 1 1 1

7 0 0 0 2 2 1 1

8 2 1 0 1 0 1 0

Полнота 95% 75% 45%

Точность 95% 68% 60%

Среднее время 53 сек. 5 сек. 4 сек.

Применение алгоритмов сборки мусора

Применение алгоритмов упрощениясостояния программы

Разработка механизма выделенияинвариантов цикла

Обнаружение более широкого классапрограммных дефектов

25

Рассмотрен подход к статическому анализу сиспользованием средств логического вывода.

Приведены правила извлечения предикатов изразличных операторов анализируемой программы.

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

Приведённые алгоритмы анализа реализованы висследовательском прототипе на базе анализатораAegis и SMT-решателя Microsoft Z3.

Показано значительное повышение точности посравнению с базовым анализатором.

26

27

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

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

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

Абстрактная интерпретация – общая теория,которая задает способ аппроксимации семантикидинамических дискретных систем, в том числе -компьютерных программ.

28

Логика первого порядка (исчисление предикатов) –формальное исчисление, допускающее высказыванияотносительно переменных, фиксированных функций ипредикатов.

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

29