1.80M
Category: programmingprogramming

Инструментальные средства. Защитное программирование

1.

Тема 4.2: Инструментальные средства.
Защитное программирование
1

2.

План лекции
1.Обработка ошибок. Механизмы
• Исключения;
• Раскрутка стека (при возникновении исключений);
• Рекомендации.
2.Регулярные выражения:
• Регулярные выражения в различных языках и библиотеках.
• Полезные, но труднопонимаемые конструкции.
• Где можно использовать?
3.Проектирование по контракту (CdD):
• Понятие корректности (+ мини-задание);
• Контракты в .NET;
• Реализация контрактов;
• Контракты в .NET (с инвариантом);
• Контракты в Python (PyContracts);
• Контракты в Java (Guava.Preconditions);
• Контракты в Java 5 (аннотации и не только);
• Контракты и модульные тесты;
2

3.

1 Обработка ошибок. Стоимость. Проблемы
книга Карпова Model Checking.
Исследования кода с PVS-Studio.
3

4.

1 Механизмы обработки ошибок
1. За счет чего достигается надежность ПО?
2. Рассуждаем о надежности программ на Java, C++, Python:
- Типизация;
- Указатели;
- Спецификация.
3. Механизмы обработки ошибок:
- exit(-564);
- cerr/clog;
- возврат заведомо некорректного значения: malloc (Си), str.find (Python), std::find (C++);
- возврат кода ошибки: QString::toUInt(bool *ok = nullptr), работа с процессами ОС;
- выставление флага ошибки:
* внутри объекта: fstream::good(), fstream::bad();
* глобально — errno (Си), std::error_code(C++).
- альтернативные варианты:
* setjmp/longjmp;
* поток ошибок и callback для их получения (OpenGL);
- вырабатывание исключения.
4

5.

1 Обработка ошибок. Проблема донесения
ошибки до обработчика
Как бы вы реализовали (де)сериализацию объектов в этой игре? Так, чтобы избежа
Main. Игровое поле. Объекты.
Никто кроме объектов не должен заниматься их вводом/выводом.
Пока класс неизвестен — объект не создан.
=> Main. Игровое поле. Фабрика. Объекты.
Пакман разрабатывали 9 человек. Целый год. Призрак «Спиди
5

6.

1 Обработка ошибок. Проблемы. Итоги
80% кода — обработка ошибок. В Unix точно.
Цена возникновения ошибок обычно выше чем цена исправления.
=> Существуют тестирование, верифиация и санитайзеры.
=> Нужны более совершенные подходы обработки ошибок. Решающие проблемы:
|
+----- типизации ошибок;
|
+----- донесение ошибки до обработчика;
|
+----- дополнения типа ошибки текстовой информацией;
|
+----- выстраивания типов ошибок в иерархию, их полиморфной обработки;
|
+----- «проброса» ошибки «дальше» после ее обработки.
6

7.

1.1 Обработка исключений (синтаксис)
try {
socket = connect_to_server(host); // throw BadHostException or ServerNotAvailableException
send_message(socket, message); // throw ServerNotAvailableException or BadMsgException
}
catch(BadHostException exception) {
// BadHostException hadler
// can charge other host from user
}
catch(ServerNotAvailableException exception) {
// ServerNotAvailableException handler
// can reconnect for example
}
catch(BadMsgException exception) {
// BadMsgException hadler
// can notify user by window
}
catch(...) {
// other types of exceptions hadler
}
7

8.

1.2 Выделение памяти на стеке. Пример 1
Стек - область памяти, уникальная для каждого потока (thread);
Выделяется:
●Ядром ОС (для главного потока);
●Внутри процесса при создании
●потока (pthread).
Вершина стека - регистр SP.
Размер элемента - машинное слово.
https://godbolt.org/z/G7bs3zeqn
Как реализуется стек? (операции push, pop, выделение памяти).
8

9.

1.2 Выделение памяти на стеке. Пример 2
9

10.

1.2 Выделение памяти на стеке. Стековый кадр
Адреса возврата
●Сохранённые регистры
●Локальные переменные
●Аргументы функции
10

11.

1.2 Выделение памяти на стеке.
Соглашение о вызовах
Как передаются аргументы?
•Регистры?
•Стек?
•В каком порядке?
Кто очищает стек от аргументов?
•Вызывающая функция? (caller)
•Вызываемая функция? (callee)
Как возвращается результат?
•Регистры?
•Стек?
Какие регистры необходимо сохранить в стек?
11

12.

1.2 Выделение памяти на стеке.
Соглашение о вызовах
https://godbolt.org/z/To5MvTcKf
12

13.

1.2 Выделение памяти на стеке. Раскрутка стека
Проход по содержимому стека
●Перебор стековых кадров в порядке, обратном вызову функций;
●Логика над полученными данными.
Сложности:
●Разный формат стековых кадров для разных функций:
●Различное количество аргументов, передаваемых по-разному
●Различное число локальных переменных
●Разные регистры сохраняются в стек
●Зависимость от архитектуры
●Оптимизации компилятора
13

14.

1.2 Выделение памяти на стеке. Регистры
Stack pointer ( SP, ESP, RSP)
•Вершина стека
•Может меняться во время исполнения функции
●Frame pointer , Base pointer (FP, EBP, RBP):
•Используется для адресации локальных переменных
•Указывает на начало стекового кадра текущей функции
•Не меняется во время исполнения функции
•Может не использоваться ( -fomit-frame-pointer)
●Instruction pointer, program counter (PC, IP, EIP, RIP)
•Указывает на исполняемую инструкцию.
●Другие регистры в зависимости от архитектуры
•Link Register (LR) — адрес возврата ( ARM 32-bit)
14

15.

1.2 Выделение памяти на стеке.
Виртуальная раскрутка
Виртуальные регистры ( VRs):
●Копия (snapshot) значений регистров в памяти
●Все манипуляции происходят с копией
●Значения извлекаются из стека
●Доступ к памяти из стека:
●Стековые регистры (SP, FP) содержат адреса элементов стека
●Чтение — разыменование указателей
●Стек «заморожен» , пока выполняется раскрутка
●Не можем выйти из функции, пока продолжается раскрутка ( текущий по
●Выполнение потока приостановлено (другой поток/ процесс)
15

16.

1.2 Выделение памяти на стеке.
Алгоритм раскрутки
1) Получаем исходные данные - значения регистров (ip, sp, fp)
2) Выполняем логику над значениями регистров
3) Считываем предыдущий стековый кадр и восстанавливаем значения р
4) Зацикливаем пункт 2
Есть разные реализации.
16

17.

1.3 Использование исключений
Выброшенное исключение приводит к раскрутке стека до подходящего о
Квест — найди ошибку:
Иерархия исключений — это очень удобно:
•Типизация ошибок - не exit(1);
•Структурирование ошибок — не exit(BadLogin);
•Механизм доставки ошибки до обработчика;
•Возможность использования полиморфизма (обработка исключений базо
•В любом языке есть базовые классы исключений => читаем документаци
В ОО-языках исключения могут вылетать откуда угодно (почти).
17

18.

1.3 Использование исключений
В ряде языков кроме try-catch-throw есть что-то типа finally. Мартин рекомен
Квест — найди ошибку
https://godbolt.org/z/7dxh3vfWz
18

19.

1.3 Использование исключений
В ряде языков можно задавать спецификацию исключений. В С++ была, но
В ряде языков есть спецификатор, показывающий, что функция не может вы
19

20.

1.3 Использование исключений
Оператор noexcept может использоваться внутри функций. Он принимает в
https://godbolt.org/z/KbrTxvj6a
20

21.

1.3 Использование исключений
Почему полезно отмечать функции, как не выбрасывающие исключен
Функции, которые являются noexcept, могут позволить компилятору выполнять
21

22.

1.3 Использование исключений.
Транзакционное поведение
Фрагмент кода безопасен с точки зрения исключений если он, отвечает след
Все ресурсы, выделенные внутри блока try до генерации исключения, до
Все объекты, созданные внутри блока try до генерации исключения, долж
Должен произойти полный откат всех изменений в системе, внесенных к
Блоками try следует охватывать участки кода, которые должны представлят
22

23.

1.4 Литература
1. Мартин Р. Чистый код. Создание, анализ и рефакторинг. Библиотека програм
2. Мейерс С. Эффективное использование С++. 35 новых рекомендаций по улу
3. Исключения C++ через призму компиляторных оптимизаций. Роман Русяев. U
4. Обработка исключений (40% лекции): https://pro-prof.com/forums/topic/exceptio
5. С++ exception handling под капотом (цикл статей о деталях реализации). URL
6. Константин Крамлих Аскетичная разработка браузера (Яндекс браузер НЕ ис
7. Разбор соглашения о кодировании Google в части исключений: http://eao197.
23

24.

2 Регулярные выражения
Функции типа scanf, sscanf, sprinf поддерживают описание формата:
%[*][width][length]specifier
1.Это удобно, но нетипобезопасно:
2.scanf("%d", &b); // что, если b — не целого типа?
3. Можно обработать ошибки (реально все гораздо сложнее):
4.errno = 0;
5.scanf("%d", &b);
if (errno != 0) {
perror("scanf");
} else {
//…
}
1. В качестве спецификатора может передаваться Scanset или Negative sca
scanf("%255[^\n]", str);
24

25.

2.1 Регулярные выражения Java
https://onlinegdb.com/5KxHfETzDZ
Умеют заменять группы на другой текст и многое другое.
25

26.

2.1 Регулярные выражения php
https://onlinegdb.com/pii_J8rlln
26

27.

2.1 Регулярные выражения js
https://js.do/vsvasilev/jscode
27

28.

2.1 Регулярные выражения Qt
28

29.

2.2 Некоторые интересные команды
(pattern) - Соответствует строке pattern и запоминает найденное соответствие.
(?:pattern) - Соответствует строке pattern, но не запоминает найденное соответстви
(?=pattern) - Соответствие с "заглядыванием вперед", происходит при соответствии
(?!pattern) - Соответствие с "заглядыванием вперед", происходит при несоответств
29

30.

2.3 Применение для валидации полей (C++, Qt)
30

31.

2.3 Примение для валидация JSON
31

32.

2.4 Что почитать?
Мини-задание: составить регулярное выражение для валидации даты в формат
1. Учебник: Регулярные выражения (regular expressions): https://pro-prof.com/archive
2. Поиск с помощью регулярных выражений может быть простым и быстрым: https:
3. Подборка материалов по регулярным выражениям: https://vk.com/wall-105242702
32

33.

2.4 Фридл Дж. «Регулярные выражения.
Сборник рецептов»
33

34.

3.1 Понятие корректности
int DoSomething(int y) {
int x = y/2;
return x;
}
Корректность – это согласованность программных элементов с
заданной спецификацией.
Термин «корректность» не применим к программному элементу, он
имеет смысл лишь для пары – «программный элемент и его
спецификация»
{require} A {ensure}
{x = 5} x = x ^ 2 {x > 0}
34

35.

3.2 Контракты в .NET
public class Math {
public static double Sqrt(double x) {
Contract.Requires(x >= 0, “Positive x"); // Реализация метода }
}
public class Stack<T> {
public void Push(T t) {
Contract.Requires(t != null, "t not null");
Contract.Ensures(Count == Contract.OldValue(Count) + 1, "One more item"); //
Реализация метода }
public T Pop() {
Contract.Requires(Count != 0, "Not empty");
Contract.Ensures(Contract.Result<T>() != null, "Result
not null");
Contract.Ensures(Count ==Contract.OldValue(Count) - 1,
"One fewer item"); // Реализация метода }
public int Count {get;}
}
https://godbolt.org/z/PPKGEcYcY
https://godbolt.org/z/GWq6Yf1v3
35

36.

3.3 Реализация контрактов
• Во время исполнения – останов (или генерация исключения) при
нарушении. Возможность отключения.
• Статические проверки на этапе компиляции.
• Часть документации.
• Основа для тестирования.
• Контракты могут являться частью объектной модели.
• Понятие инварианта класса.
• Предусловия у наследников могут быть ослаблены, а постусловия и
инварианты - усилены.
https://godbolt.org/z/5Gfd5o83q
36

37.

3.4 Контракты в .NET (с инвариантом)
https://godbolt.org/z/9Treqqsr6
37

38.

3.5 Контракты в Python (PyContracts)
https://godbolt.org/z/Efhh1Ka16
38

39.

3.6 Контракты в Java (Guava.Preconditions)
39

40.

3.7 Контракты в Java 5 (аннотации и не только)
Contract4J, но есть и другие. Есть без аннотаций (C4J)
40

41.

3.8 Контракты и модульные тесты
Контракты – декларативны
Юнит тесты – императивны
[ContractClassFor(typeof(IList<>))]
internal abstract class IListContract<T> : IList<T>
{
void IList<T>.Add(T item)
{
Contract.Ensures(this.Count == (Contract.OldValue<int>(this.Count) + 1),
"Count == Contract.OldValue(Count) + 1");
}
}
На языке D:
41

42.

3.9 Что еще почитать?
1.Проектирование по контракту. Корректность ПО
http://sergeyteplyakov.blogspot.com/2010/05/design-by-contract.html
2.Проектирование по контракту. Утверждения
http://sergeyteplyakov.blogspot.com/2010/05/blog-post.html
3.Утверждения и защитное программирование
http://sergeyteplyakov.blogspot.com/2010/05/blog-post_14.html
4.Проектирование по контракту. Наследование
http://sergeyteplyakov.blogspot.com/2010/05/blog-post_17.html
5.Мониторинг утверждений в период выполнения
http://sergeyteplyakov.blogspot.com/2010/05/blog-post_20.html
6.Альтернативная проверка предусловий в Code Contracts
http://sergeyteplyakov.blogspot.com/2012/03/blog-post_12.html
7.Контракты vs Юнит тесты http://sergeyteplyakov.blogspot.com/2012/06/vs.html
8.Предусловия в конструкторах наследников
http://sergeyteplyakov.blogspot.com/2015/03/preconditions-in-derivedclass.html
42

43.

3.9 Что еще почитать?
1.Code Contracts library http://lunarfrog.com/blog/code-contracts
2.Контрактное программирование под Android
http://derevyanko.blogspot.com/2014/01/android.html
3.Контрактное программирование в D
https://tour.dlang.org/tour/ru/gems/contract-programming
4.Документация по вашему любимому ЯП или его библиотекам.
43
English     Русский Rules