С момента начала разработки программного обеспечения стоит проблема тестирования и выявления дефектов и неисправностей. С ростом сложности программ и увеличением размера кодовой базы важность проблемы только растёт.
Почти всегда необходимо не только установить факт того, что программа выдаёт неправильный результат, не завершает исполнение или завершается аварийно, но так же и определить набор входных данных, на которых это произошло. Для этого часто используют фаззинг.
Фаззинг - метод тестирования программного обеспечения, который основан на генерации входных данных для тестируемого программного обеспечения. Фаззеры стараются генерировать такие данные, которые скорее всего выявят проблемы в программе: заведомо некорректные данные, данные неверного формата, краевые случаи данных.
Для генерации новых данных часто используется уже готовый корпус тестовых случаев. Его загружают перед стартом фаззинга и в дальнейшем к нему применяют различные мутации, комбинируют тестовые данные друг с другом, чтобы получить новые входные данные. Для мутаций часто используют случайные величины, эвристики, но нередко и машинное обучение.
После генерации данные передаются на вход тестируемой программе. Поведение программы анализируется: собирается информация о том, по какому пути пошло исполнение программы, завершилась ли программа аварийно, каков результат выполнения программы. Эти данные передаются фаззеру и на их основе принимается решение о том, как продолжать фаззинг и генерировать новые тестовые случаи.
Таким образом, фаззер состоит из двух независимых частей. В первой части происходит генерация и обработка данных об исполнении программы. Во второй части происходит непосредственно запуск программы на переданных входных данных.
Часто обе части разрабатываются вместе для фаззинга программ на одном из языков программирования:
1. LibFuzzer [1] — фаззер для C/C++.
2. Jsfuzz [3] — фаззер для JavaScript.
Разработка общей фаззинг платформы позволила бы не реализовывать алгоритм фаззинга для каждого языка. Чтобы применить платформу к новому языку программирования, достаточно было бы реализовать вторую часть фаззера для этого языка, которая запускает программу и собирает информацию об исполнении.
В данной работе были выполнены следующие задачи:
1. Проведён обзор уже существующих решений для фаззинга программ на C/C++. Были изучены аналоги, позволяющие проводить фаззинг программ на нескольких языках программирования.
2. Разработан исполнитель C++ — программный аппарат для запуска программ, написанных на C/C++. Реализована возможность собирать данные об исполнении программы.
3. Разработан протокол для обмена данными между исполнителем Java и исполнителем C++.
4. Разработан исполнитель Java — программный аппарат для запуска универсальной фаззинг платформы и передачи ей данных об исполнении программы.
5. Разработанный фаззер был сравнён с аналогами.