Categorias: Todos - символы - тестирование - грамматика

por Andrew Petukhov 1 ano atrás

146

MindMap fuzz-тестирования шаблонизаторов

В процессе выбора наиболее успешных тестов для фаззинга, важно учитывать частоту переходов в тестах и оптимизацию множества символов. Это позволяет направлять фаззер более эффективно, делая выбор символов осмысленным с точки зрения программирования.

MindMap fuzz-тестирования шаблонизаторов

Генерация тестов/деревьев

Перебираем все короткие поддеревья нетерминала и пытаемся заменить текущее

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

Обработка успешных

Исходя из контекста выбранной метрики. Например, если метрика - покрытие функций - и тест запустил новую функцию - то его оставляем.

Как понять нужен ли этот тест?

Провести "турнир" в случайном подмножестве и взять нескольких победителей.

Выбрать несколько случайным образом

Оставить какой-то процент тех, у кого максимальна функция качества

Как выбрать наиболее успешные?

Если в вершине потенциально много поддеревьев, будем ходить туда чаще. Плюсы: позволит наиболее полно покрыть грамматику. Минусы: требуется предпосчёт количества деревьев для каждого нетерминала.

Чем чаще встречается переход в тестах, тем чаще мы его будем использовать. Плюсы: просто пишется. Позволяет направлять фаззер, путём изменения множества. Выбор символа становится более осмысленным с точки зрения программирования. Минусы: нужно начальное множество

При генерации с равной вероятностью выбираем символ грамматики из текущей вершинки Плюсы: просто Минусы: работает хуже остальных. Например: будет часто вставлять терминальный символ вместо расширения дерева.

Чем длиннее тест - тем он дольше будет выполняться, и тем сложнее будет разбираться в случае обнаружении бага

Из истории - чем код сложнее и рекурсивнее, тем вероятнее в нём есть баг.

Какие свойства хотим получить у сгенерированных?

Информацию о покрытии

Более детальный способ описывать покрытие. Метрика интересена только в контексте наличия других тестов. Плюсы: получаем более информативную оценку. Минусы: сложно реализовывать.

Подсчёт количества строк/функций, которые покрыл тест. Плюсы: просто (относительно) Минусы: метрика сама по себе не очень информативна. В контесте множества тестов можно выялять те, которые попадают в новые строки/функции.

Покрытие веток(путей)

Короткие

Сложные рекурсивные тесты

Функция(какая-то) от метрик, полученных при запуске, построении(сложность теста, покрытие, наличие эксепшона, длина)

Как понять, что тест успешный?

Убрать из тестов семантические ошибки. Например, использование необъявленных переменных

Если используется вероятностная грамматика, то в ней можно изменять случайно вероятности

Рекурсивное дублирование поддерева

AFL мутации - бит флип, замена "интересных значений"

Для каждой вершинки в дереве считаем какую-то дополнительную информация и меняем, только на дерево с такой же инфомарцией. Например, тип нетерминала, количество переменных.

Замена поддерева на случайно сгенерированное

Скрещивание с другими тестами, путём замены поддеревьев

Мутации

Контролировать размер во время построение теста, если такое используется

Можно просто выкидывать поддеревья

Рекурсивное замещение поддерева

Уменьшение поддерева

Запускать только один пример из очереди

Минимизация размера

Менять СРАЗУ всё поколение: Запускать все тесты и считать для каждого функцию качества

Как прогонять множество во время фаззинга?

Можно брать обратные вероятности Это позволит "мыслить" фаззеру в противоположном направлении. Плюсы: чаще будем покрывать неожиданные пути в грамматике. Минусы: чаще будем попадать в неинтересные символы(например в js часто будет вызываться return)

По количеству поддеревьев в нетерминале.

Если есть какое-то множество примеров, можно по частоте встречаемости нетерминалов в них.

Откуда брать вероятности?

По грамматике с вероятностями

Равновероятно по грамматике

Как генерировать?

Сгенерировать самим

Взять изначальное множество из интернета(либо из исходников, либо с гитхаба)

Откуда брать начальное множество?

Множество тестов

Покрытие функций(function coverage)

Покрытие кода(line coverage)

Патчим бинарь, чтобы получать метрики от тестов

Какие метрики хотим получать от бинаря?

Как патчить?

Можно как в АФЛ

Fuzzer

whitebox

greybox