Фильтрованный контент о тестировании и качестве ПО.
ADD r1, r2 → SUB r1, r2). Любое отклонение от начального состояния в конце выполнения должно быть ошибкой. Реверсивный подход хорош, но он усложняет создание тестовых сценариев для архитектуры CISC, такой как x86.
В случае с Zenbleed использовался другой тестовый оракул, который назвали "сериализованный оракул". Во время фаззинга отслеживается макроархитектурное состояние, как например значения регистров. Существует также микроархитектурное состояние, которое в основном невидимо для нас, например, предсказатель ветвлений, состояние спекулятивного выполнения инструкций и конвейер инструкций. Сериализация позволяет иметь некоторый контроль над этим, указывая CPU отключить параллельное выполнение инструкций. Основная идея сериализованного оракуласостоит в том, чтобы сгенерировать случайную программу, а затем автоматически преобразовывать её в сериализованную форму. Случайно сгенерированная последовательность инструкций и та же последовательность, но с добавлением рандомизированного выравнивания (см. пример инструкций), сериализации и спекулятивных ограждений. Эти две программы могут иметь разные характеристики производительности, но они должны выдавать одинаковый результат. Если конечные состояния не совпадают, то, должно быть, была какая-то ошибка в том, как они были выполнены на уровне микроархитектуры, что может указывать на ошибку. Так Zenbleed и обнаружили - вывод сериализованного оракула не совпал.
viaprint <<EOT
Test Mail::Sendmail $Mail::Sendmail::VERSION
Trying to send a message to the author (and/or whoever if you edited test.pl)
(The test is designed so it can be run by Test::Harness from CPAN.pm.
Edit it to send the mail to yourself for more concrete feedback. If you
do this, you also need to specify a different mail server, and possibly
a different From: address.)
Current recipient(s): '$mail{To}'
EOT
;
github.com/neilb/M…iginal.tstd::sort, std::binary_search, std::set, std::map и в C qsort или bsearch. Компараторы должны удовлетворять некоторым требованиям, а нарушение требований приводит к Undefined Behavior. Такие требования (или аксиомы) неинтуитивны и в них легко ошибиться, о чём свидетельствует большое количество соответствующих багов в open-source проектах.
Аксиомы, которым должны подчиняться компараторы, изложены в стандарте языка, их можно посмотреть в Cppref.
Популярные ошибки при написании компараторов:
1) Использование <= вместо <.
2) Сравнение особых объектов отдельным алгоритмом и нарушение условия транзитивности.
3) Неправильная реализация лексикографического порядка, когда не сравнивается первый элемент структуры на равенство при сравнение второго.
4) Массивы содержащие NaN.
5) Некорректная обработка специального случая.
6) Отрицание строгого порядка не является строгим порядком.
Для поиска таких проблем Юра предлагает два варианта: использование опций в тулчейне и использование динамического анализа.
В первом случае макрос -D_GLIBCXX_DEBUG в libstdc++ включает дополнительную проверку иррефлексивности, а в Libc++ c помощью -D_LIBCPP_ENABLE_DEBUG_MODE включаются проверки согласованности компараторов. Обе опции имеют существенный (2x) оверхед, поэтому их рекомендуется использовать только для тестирования.
Во втором случае динамические чекеры позволяют выполнять проверки компараторов в рантайме: SortChecker позволяет перехватывать компараторы для функций qsort и bsearch в C c помощью динамической инструментации (LD_PRELOAD), SortChecker++ позволяет проверять компараторы типа std::sort в программах на C++ и использует source-to-source инструментацию (Clang-based).