Введение 5
1. Постановка задачи 7
2. Обзор предметной области 8
2.1. Символьное исполнение 8
2.2. SMT-решатели 11
2.3. Архитектура проекта V# 12
2.4. Модель символьной памяти в V# 13
3. Независимое управление ограничениями 15
3.1. Существующие реализации 16
3.2. Подход к реализации в V# 17
4. Кэширование моделей SMT-решателя 19
4.1. Существующие реализации 19
4.2. Подход к реализации в V# 21
5. Инкрементальное использование SMT-решателя 22
5.1. Инкрементальность на основе стека 23
5.2. Инкрементальность на основе предпосылок 24
5.3. Существующие реализации 26
5.4. Подход к реализации в V# 26
6. Особенности реализации 28
6.1. Независимое управление ограничениями 28
6.2. Кэширование моделей SMT-решателя 30
6.3. Инкрементальное использование SMT-решателя 31
7. Эксперименты 32
7.1. Тестовые данные 32
7.2. Исследовательские вопросы 32
7.3. Результаты 33
Заключение
Список литературы
Качественное тестирование достаточно сложной, чтобы быть полезной не только для ее создателя, программы — это, как правило, трудоёмкая задача. Тестирование требует значительного количества времени, которое не всегда удаётся выделить в реальном процессе разработки. При этом даже после тестирования и отладки в программном коде могут оставаться незамеченные специалистами уязвимости, при-водящие к ошибкам или нежелательному поведению только при исполнении на специфичных комбинациях входных данных. Для решения данных проблем часто применяются инструменты автоматической генерации тестов, в том числе инструменты тестирования «белого ящика» (которым доступен исходный код программы, в отличие от тестирования «черного ящика»). В основе таких инструментов лежат различные механизмы статического анализа кода, один из которых — механизм символьного исполнения.
Техники символьного исполнения кода заключаются в исполнении программы не на конкретных значениях входных данных, а на так называемых символьных переменных. Это даёт возможность для каждого пути исполнения получить логические ограничения на значения входных параметров, при выполнении которых этот путь достигается. После этого при помощи БМТх-решателя такие значения могут быть найдены и сгенерирован тест, реализующий данный путь.
Механизм символьного исполнения обладает таким достоинством, как теоретически полное покрытие кода, что даёт возможность гарантировать выполнение некоторых условий программой (например, что она никогда не выбрасывает Null Pointer Exception). В то же время необходимость анализировать все возможные пути исполнения, число которых растет экспоненциально, влечёт его главный недостаток — высокую вычислительную сложность. К этому также следует добавить NP-трудность задачи выполнимости формулы в теориях, к которой, как правило, сводится задача поиска значений входных данных.
■Satisfiability Modulo Theory, задача выполнимости формулы в теориях
В качестве примера, иллюстрирующего эффективность и сложность символьного исполнения, можно привести использование компанией Microsoft символьной машины SAGE для воспроизведения ошибки переполнения стека в ОС Windows [15]. Ошибка в коде, отвечающем за чтение файлов анимированных курсоров, приводила к возможности удаленного исполнения произвольного кода злоумышленником . В отличие от других инструментов статического анализа, SAGE удалось сгенерировать файл, чтение которого приводило к ошибке, но на это понадобилось семь с половиной часов на машине с производительностью среднего ПК.
Таким образом, создание практически полезного инструмента, основанного на механизме символьного исполнения, невозможно без использования различных оптимизаций и эвристик. Существует большое количество подходов к управлению ограничениями в символьных маши-нах, позволяющих минимизировать число запросов к SMT-решателю, увеличить переиспользование уже полученных в процессе исполнения результатов и исключить определённые пути исполнения.
V# — это символьная машина для программ на платформе .NET с открытым исходным кодом, которая разрабатывается с целью удовлетворить текущую потребность в системе автоматической генерации тестов для наиболее современных фреймворков .NET и .NET Core, используя при этом наиболее современные подходы к оптимизации процесса символьного исполнения.
В ходе данной работы были получены следующие результаты.
• Проведён обзор оптимизаций управления символьными ограничениями: техник независимого управления ограничениями и кэширования моделей SMT-решателя, подходов к инкрементальному использованию SMT-решателя на основе стека и предпосылок.
• Независимое управление ограничениями реализовано в символьной виртуальной машине V#.
• Кэширование моделей SMT-решателя реализовано в символьной виртуальной машине V#.
• Подход к инкрементальному использованию SMT-решателя на основе предпосылок реализован в символьной виртуальной машине V#.
• Проведены эксперименты на синтетических тестовых данных.
Исходный код проекта V# является открытым и содержится в репозитории GitHub (имя аккаунта — mxprshn).
[1] The SMT-LIB Standard: Version 2.6 : Rep. / Department of Com¬puter Science, The University of Iowa ; Executor: Clark Barrett, Pas¬cal Fontaine, Cesare Tinelli : 2017.
[2] Barrett Clark W., Dill David L., Levitt Jeremy R.A Decision Procedure for Bit-Vector Arithmetic. - DAC ’98. - New York, NY, USA : Association for Computing Machinery, 1998. — P. 522-527.
[3] Benchmarking the Capability of Symbolic Execution Tools with Logic Bombs / Hui Xu, Zirui Zhao, Yangfan Zhou, Michael R. Lyu //IEEETransactions on Dependable and Secure Computing. — 2020. — Vol. 17, no. 6. — P. 1243-1256.
[4] Bjprner Nikolaj. How incremental solving works in Z3? // Stack Over-flow.— 2016.— URL: https://stackoverflow.eom/a/40427658/11933076 (online; accessed: 02.05.2022).
[5] Cadar Cristian, Dunbar Daniel, Engler Dawson. KLEE: Unassisted and Automatic Generation of High-Coverage Tests for Complex Sys¬tems Programs // Proceedings of the 8th USENIX Conference on Op¬erating Systems Design and Implementation.— OSDI’08.— USA : USENIX Association, 2008. — P. 209-224.
[6] Liu Tianhai, Araujo Mateus, d’Amorim Marcelo, Taghdiri Mana. A Comparative Study of Incremental Constraint Solving Approaches in Symbolic Execution. — 2014.
[7] Cook Stephen A.The Complexity of Theorem-Proving Procedures // Proceedings of the Third Annual ACM Symposium on Theory of Com-puting. — STOC ’71.— New York, NY, USA : Association for Com¬puting Machinery, 1971. — P. 151-158.
[8] DPLL(T): Fast Decision Procedures / Harald Ganzinger, George Ha¬gen, Robert Nieuwenhuis et al. — 2004. — 06.
[9] Davis Martin, Logemann George, Loveland Donald. A Machine Pro¬gram for Theorem-Proving //Commun. ACM. — 1962. —jul. — Vol. 5, no. 7. — P. 394-397.
[10] ECMA International. Standard ECMA-335 - Common Lan¬guage Infrastructure (CLI).— 2012.— URL: https://www.
ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf (online; accessed: 01.05.2022).
[11] EXE: Automatically Generating Inputs of Death / Cristian Cadar, Vijay Ganesh, Peter M. Pawlowski et al. //ACM Trans. Inf. Syst.Secur. — 2008. — dec. — Vol. 12, no. 2. — 38 p. — URL: https://doi.org/10.1145/1455518.1455522.
[12] English Lyn, Sriraman Bharath. Problem Solving for the 21st Cen¬tury. - 2010.-01.
[13] Ganesh Vijay.SAT and SMT Solvers: A Foundational Perspective// Engineering Secure and Dependable Software Systems. — NATO Sci-ence for Peace and Security Series - D: Information and Communication Security. — 2018. — P. 29 - 60.
[14] Ganesh Vijay, Dill David.A Decision Procedure for Bit-Vectors andArrays. — Vol. 4590. — 2007. — 01. - P. 519-531.
[15] Godefroid Patrice, Levin Michael, Molnar David. SAGE: Whitebox Fuzzing for Security Testing //ACM Queue. — 2012. — 03. — Vol. 10. — P. 20.
[16] Introduction to Algorithms / Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein. — 2nd edition. — The MIT Press, 2001. — ISBN:0262032937.
[17] Lin Yude, Miller Tim, Spndergaard Harald.Compositional SymbolicExecution: Incremental Solving Revisited// 2016 23rd Asia-Pacific Software Engineering Conference (APSEC). — 2016. — P. 273-280.
[18] Marques Silva J.P., Sakallah K.A.GRASP-A new search algorithm forsatisfiability // Proceedings of International Conference on Computer Aided Design. — 1996. — P. 220-227.
[19] Marques-Silva J.P., Sakallah K.A. GRASP: a search algorithm for propositional satisfiability //IEEE Transactions on Computers. — 1999. — Vol. 48, no. 5. — P. 506-521.
[20] Mordvinov Dmitry. Property Directed Symbolic Execution. — 2021. — Spring/Summer Young Researchers’ Colloquium on Software Engi-neering. URL: https://youtu.be/pX5qS4SbsJI (online; accessed: 03.05.2022).
[21] SCSE: Boosting Symbolic Execution via State Concretization / Huibin WANG, Chunqiang LI, Jianyi MENG, Xiaoyan XIANG //IE-ICE Transactions on Information and Systems. — 2019. — Vol. E102.D, no. 8. — P. 1506-1516.
[22] Stump Aaron, Barrett Clark, Dill David. A Decision Procedure for an Extensional Theory of Arrays. — 2002. — 01.
[23] A Survey of Symbolic Execution Techniques / Roberto Baldoni, Emilio Coppa, Daniele Cono D’elia et al. //ACM Comput. Surv.— 2018. — may. — Vol. 51, no. 3. — 39 p. — URL: https://doi.org/10.1145/3182657.
[24] Sydr: Cutting Edge Dynamic Symbolic Execution / Alexey Vish¬nyakov, Andrey Fedotov, Daniil Kuts et al. //2020 Ivannikov IsprasOpen Conference (ISPRAS). — 2020. — Dec.
[25] Tillmann Nikolai, de Halleux Peli. Pex - White Box Test Generation for .NET // Proc. of Tests and Proofs (TAP’08). - Vol. 4966 of LNCS. - 2008. — April. — P. 134-153.
[26] de Moura Leonardo, Bjprner Nikolaj. Satisfiability modulo Theories: Introduction and Applications //Commun. ACM.— 2011.—sep.— Vol. 54, no. 9. - P. 69-77.
[27] de Moura Leonardo, Bj0rner Nikolaj.Z3: an efficient SMT solver.— Vol. 4963. — 2008.-04. — P. 337-340.
[28] Костицын Михаил Павлович. Модель символьной памяти .NET с поддержкой реинтерпретаций. Бакалаврская работа // Санкт- Петербургский государственный университет. — 2019.