Введение 4
1. Постановка задачи 6
2. Обзор 7
2.1. Символьное исполнение 7
2.2. Система типов 8
2.3. Существующие подходы 9
3. Архитектура подсистемы интерпретации типов 10
4. Композициональное символьное исполнение с типами 12
4.1. Частично определенные типы 12
4.2. Подстановка типов 13
5. Формализация системы типов .NET 15
6. Алгоритм решения систем ограничений на типы 19
7. Тестирование 30
Заключение 31
Список литературы 32
В области верификации есть методы, которые используют технику символьного исполнения [2, 12, 13] для сведения кода к языку логики первого порядка и решатели дизъюнктов Хорна [8, 9, 14] для их разрешения. Одна из главных задач, решаемых символьным интерпретатором — исследование веток выполнения кода на неопределенных входных данных.
Во время символьного исполнения .NET-кода появляется проблема, порождаемая неопределенностью данных, а именно неопределенность динамических типов объектов. Один из самых простых примеров, демонстрирующих эту проблему — функция Object.Equals(Object). Вне контекста конкретного вызова невозможно понять, какой именно объект будет передан в качестве параметра этого метода, в частности, неизвестно какой у объекта будет тип. Ситуация осложняется наличием обобщений (generics) с ограничениями на типовые параметры, а также вариантностью для обобщенных интерфейсов. Не стоит забывать и о сложности системы типов .NET. В частности, решение должно естественным образом масштабироваться на массивы символьных размерностей, делегаты, unsafe-указатели и т. д.
Одна из главных проблем, от которой страдают символьные интерпретаторы — проблема взрыва путей исполнения: количество путей исполнения программы в общем случае зависит экспоненциально от ее размера[1]. Один из подходов, направленных на решение этой проблемы — это композиционное символьное исполнение [6], которое позволяет переиспользовать уже проинтерпретированные участки кода во время символьного исполнения. В случае с динамическими типами объектов композиционность заключается в возможности получить корректный результат интерпретации кода, при условии того, что типы объектов могут быть конкретизированы, без повторного исполнения.
V# — это проект, направленный на создание неограничиваемого верификатора для платформы .NET. Помимо огромной важности для самого проекта V#, эта задача может представлять интерес для академического сообщества. К примеру, существует довольно большое количество работ, посвященных статическому анализу языка Java (одна из последних обзорных статей на эту тему является [16]). Существуют и работы на тему символьного исполнения в условиях неопределенности типа объектов, например, [10]. Стоит отметить также, что в наиболее известных state-of-art-интерпретаторах (таких как Java PathFinder [7] и Pex [21]), символьное исполнение кода со сложными типами поддержано в весьма ограниченном виде. В частности, не один из этих инструментов не поддерживает исполнение кода с открытыми типами в полном объёме, хотя возможность получить корректный результат символьной интерпретации кода с открытыми типами в сочетании с композициональностью позволяет сильно повысить эффективность исполнения.
В данной работе были выполнены следующие задачи.
• Спроектирована архитектура подсистемы, отвечающей за интерпретацию типов.
• Реализовано символьное исполнение функций с учетом открытых типов и полиморфизма. Неопределенность динамических типов выражена в символьных типах, на которые накладываются ограничения в виде символьных булевых термов. Поддержка исполнения кода с неопределенными типами реализована с учетом композициональности исполнения.
• Предложен и реализован алгоритм, который решает ситемы ограничений на открытые .NET типы. В частности, разработан и реализован алгоритм, который сводит задачу определения выполнимости набора ограничений на открытые типы платформы .NET к разрешимому фрагменту логики первого порядка.
• Подана статья на конференцию SEIM 2018, c последующей публикацией в CEUR (индексируется в базе данных SCOPUS).
• Проведено тестирование функциональности реализованной подсистемы.
[1] Baldoni R. et al. A survey of symbolic execution techniques // arXiv preprint arXiv:1610.00502. — 2016.
[2] Boyer R. S. Elspas B. Levitt K. N. SELECT—a formal system for testing and debugging programs by symbolic execution // ACM SigPlan Notices. —1975.—Vol. 10, no. 6.—P. 234-245.
[3] Cseppento L. Micskei Z. Evaluating symbolic execution-based test tools // Software Testing, Verification and Validation (ICST), 2015 IEEE 8th International Conference on / IEEE. — 2015. — P. 1-10.
[4] Ecma TC39. TG3. Common Language Infrastructure (CLI). Standard ECMA-335, June 2005.
[5] Fraser G. Arcuri A. Evosuite: automatic test suite generation for object-oriented software // Proceedings of the 19th ACM SIGSOFT symposium and the 13th European conference on Foundations of software engineering / ACM. — 2011. — P. 416-419.
[6] Godefroid P. Compositional dynamic test generation // ACM Sigplan Notices / ACM.—Vol. 42. —2007. —P. 47-54.
[7] Havelund K. Pressburger T. Model checking java programs using java pathfinder // International Journal on Software Tools for Technology Transfer (STTT). — 2000.—Vol. 2, no. 4. — P. 366-381.
[8] Hoder K. Bjprner N. Generalized Property Directed Reachability // SAT. —2012.—Vol. 7317. —P. 157-171.
[9] Hojjat H. et al. A verification toolkit for numerical transition systems // International Symposium on Formal Methods / Springer. — 2012. —P. 247-251.
[10] Islam M. Csallner C. Generating test cases for programs that are coded against interfaces and annotations // ACM Transactions on Software Engineering and Methodology (TOSEM). — 2014. — Vol. 23, no. 3.— P. 21.
[11] Kennedy A. J. Pierce B. C. On decidability of nominal subtyping with variance. — 2006.
[12] King J. C. A new approach to program testing // ACM SIGPLAN Notices / ACM.—Vol. 10. —1975. —P. 228-233.
[13] King J. C. Symbolic execution and program testing // Communications of the ACM. —1976.—Vol. 19, no. 7. —P. 385-394.
[14] Komuravelli A. et al. Automatic abstraction in SMT-based unbounded software model checking // International Conference on Computer Aided Verification / Springer. — 2013.—P. 846-862.
[15] La Poutre J. A. van Leeuwen J. Maintenance of transitive closures and transitive reductions of graphs // International Workshop on Graph- Theoretic Concepts in Computer Science / Springer. — 1987. — P. 106-120.
...