From dd3f4f9b9200547458f7fb8740fe5c5e9e602d3f Mon Sep 17 00:00:00 2001 From: Bosswestfalen <bosswestfalen@users.noreply.github.com> Date: Mon, 12 Dec 2016 19:26:45 +0100 Subject: [PATCH 01/71] Replaced class iterator and class const_iterator with aliases of template <typename U> iter_impl. iter_impl has operator const_iterator to create an const_iterator from an iterator. --- src/json.hpp | 245 ++++++++++++--------------------------------------- 1 file changed, 55 insertions(+), 190 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 04ea79a2..e95acd95 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -261,10 +261,12 @@ class basic_json /// the type of an element const pointer using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; + // forward declaration for iterators + template <typename U> class iter_impl; /// an iterator for a basic_json container - class iterator; + using iterator = iter_impl<basic_json>; /// a const iterator for a basic_json container - class const_iterator; + using const_iterator = iter_impl<const basic_json>; /// a reverse iterator for a basic_json container using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; /// a const reverse iterator for a basic_json container @@ -8204,10 +8206,10 @@ class basic_json public: /*! - @brief a const random access iterator for the @ref basic_json class + @brief a template for a random access iterator for the @ref basic_json class - This class implements a const iterator for the @ref basic_json class. From - this class, the @ref iterator class is derived. + This class implements a both iterators (iterator and const_iterator) + for the @ref basic_json class. @note An iterator is called *initialized* when a pointer to a JSON value has been set (e.g., by a constructor or a copy assignment). If the @@ -8222,25 +8224,35 @@ class basic_json @since version 1.0.0 */ - class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json> + template <typename U> + class iter_impl : public std::iterator<std::random_access_iterator_tag, U> { /// allow basic_json to access private members friend class basic_json; + // make sure U is basic_json or const basic_json + static_assert(std::is_same<U, basic_json>::value + or std::is_same<U, const basic_json>::value, + "iter_impl only accepts (const) basic_json"); + public: /// the type of the values when the iterator is dereferenced using value_type = typename basic_json::value_type; /// a type to represent differences between iterators using difference_type = typename basic_json::difference_type; /// defines a pointer to the type iterated over (value_type) - using pointer = typename basic_json::const_pointer; + using pointer = typename std::conditional<std::is_const<U>::value, + typename basic_json::const_pointer, + typename basic_json::pointer>::type; /// defines a reference to the type iterated over (value_type) - using reference = typename basic_json::const_reference; + using reference = typename std::conditional<std::is_const<U>::value, + typename basic_json::const_reference, + typename basic_json::reference>::type; /// the category of the iterator using iterator_category = std::bidirectional_iterator_tag; /// default constructor - const_iterator() = default; + iter_impl() = default; /*! @brief constructor for a given JSON instance @@ -8248,7 +8260,7 @@ class basic_json @pre object != nullptr @post The iterator is initialized; i.e. `m_object != nullptr`. */ - explicit const_iterator(pointer object) noexcept + explicit iter_impl(pointer object) noexcept : m_object(object) { assert(m_object != nullptr); @@ -8275,37 +8287,25 @@ class basic_json } } - /*! - @brief copy constructor given a non-const iterator - @param[in] other iterator to copy from - @note It is not checked whether @a other is initialized. + /* + Use operator const_iterator instead of + const_iterator(const iterator& other) noexcept + to avoid two class definitions for iterator and const_iterator. + + This function is only called if this class is an iterator. + If this class is a const_iterator this function is not called. */ - explicit const_iterator(const iterator& other) noexcept - : m_object(other.m_object) - { - if (m_object != nullptr) - { - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - m_it.object_iterator = other.m_it.object_iterator; - break; - } + operator const_iterator() const + { + const_iterator ret; - case basic_json::value_t::array: - { - m_it.array_iterator = other.m_it.array_iterator; - break; - } - - default: - { - m_it.primitive_iterator = other.m_it.primitive_iterator; - break; - } - } + if (m_object) + { + ret.m_object = m_object; + ret.m_it = m_it; } + + return ret; } /*! @@ -8313,7 +8313,7 @@ class basic_json @param[in] other iterator to copy from @note It is not checked whether @a other is initialized. */ - const_iterator(const const_iterator& other) noexcept + iter_impl(const iter_impl& other) noexcept : m_object(other.m_object), m_it(other.m_it) {} @@ -8322,7 +8322,7 @@ class basic_json @param[in,out] other iterator to copy from @note It is not checked whether @a other is initialized. */ - const_iterator& operator=(const_iterator other) noexcept( + iter_impl& operator=(iter_impl other) noexcept( std::is_nothrow_move_constructible<pointer>::value and std::is_nothrow_move_assignable<pointer>::value and std::is_nothrow_move_constructible<internal_iterator>::value and @@ -8484,7 +8484,7 @@ class basic_json @brief post-increment (it++) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator operator++(int) + iter_impl operator++(int) { auto result = *this; ++(*this); @@ -8495,7 +8495,7 @@ class basic_json @brief pre-increment (++it) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator& operator++() + iter_impl& operator++() { assert(m_object != nullptr); @@ -8527,7 +8527,7 @@ class basic_json @brief post-decrement (it--) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator operator--(int) + iter_impl operator--(int) { auto result = *this; --(*this); @@ -8538,7 +8538,7 @@ class basic_json @brief pre-decrement (--it) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator& operator--() + iter_impl& operator--() { assert(m_object != nullptr); @@ -8570,7 +8570,7 @@ class basic_json @brief comparison: equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator==(const const_iterator& other) const + bool operator==(const iter_impl& other) const { // if objects are not the same, the comparison is undefined if (m_object != other.m_object) @@ -8603,7 +8603,7 @@ class basic_json @brief comparison: not equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator!=(const const_iterator& other) const + bool operator!=(const iter_impl& other) const { return not operator==(other); } @@ -8612,7 +8612,7 @@ class basic_json @brief comparison: smaller @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator<(const const_iterator& other) const + bool operator<(const iter_impl& other) const { // if objects are not the same, the comparison is undefined if (m_object != other.m_object) @@ -8645,7 +8645,7 @@ class basic_json @brief comparison: less than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator<=(const const_iterator& other) const + bool operator<=(const iter_impl& other) const { return not other.operator < (*this); } @@ -8654,7 +8654,7 @@ class basic_json @brief comparison: greater than @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator>(const const_iterator& other) const + bool operator>(const iter_impl& other) const { return not operator<=(other); } @@ -8663,7 +8663,7 @@ class basic_json @brief comparison: greater than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator>=(const const_iterator& other) const + bool operator>=(const iter_impl& other) const { return not operator<(other); } @@ -8672,7 +8672,7 @@ class basic_json @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator& operator+=(difference_type i) + iter_impl& operator+=(difference_type i) { assert(m_object != nullptr); @@ -8703,7 +8703,7 @@ class basic_json @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator& operator-=(difference_type i) + iter_impl& operator-=(difference_type i) { return operator+=(-i); } @@ -8712,7 +8712,7 @@ class basic_json @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator operator+(difference_type i) + iter_impl operator+(difference_type i) { auto result = *this; result += i; @@ -8723,7 +8723,7 @@ class basic_json @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator operator-(difference_type i) + iter_impl operator-(difference_type i) { auto result = *this; result -= i; @@ -8734,7 +8734,7 @@ class basic_json @brief return difference @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - difference_type operator-(const const_iterator& other) const + difference_type operator-(const iter_impl& other) const { assert(m_object != nullptr); @@ -8830,141 +8830,6 @@ class basic_json internal_iterator m_it = internal_iterator(); }; - /*! - @brief a mutable random access iterator for the @ref basic_json class - - @requirement The class satisfies the following concept requirements: - - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): - The iterator that can be moved to point (forward and backward) to any - element in constant time. - - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator): - It is possible to write to the pointed-to element. - - @since version 1.0.0 - */ - class iterator : public const_iterator - { - public: - using base_iterator = const_iterator; - using pointer = typename basic_json::pointer; - using reference = typename basic_json::reference; - - /// default constructor - iterator() = default; - - /// constructor for a given JSON instance - explicit iterator(pointer object) noexcept - : base_iterator(object) - {} - - /// copy constructor - iterator(const iterator& other) noexcept - : base_iterator(other) - {} - - /// copy assignment - iterator& operator=(iterator other) noexcept( - std::is_nothrow_move_constructible<pointer>::value and - std::is_nothrow_move_assignable<pointer>::value and - std::is_nothrow_move_constructible<internal_iterator>::value and - std::is_nothrow_move_assignable<internal_iterator>::value - ) - { - base_iterator::operator=(other); - return *this; - } - - /// return a reference to the value pointed to by the iterator - reference operator*() const - { - return const_cast<reference>(base_iterator::operator*()); - } - - /// dereference the iterator - pointer operator->() const - { - return const_cast<pointer>(base_iterator::operator->()); - } - - /// post-increment (it++) - iterator operator++(int) - { - iterator result = *this; - base_iterator::operator++(); - return result; - } - - /// pre-increment (++it) - iterator& operator++() - { - base_iterator::operator++(); - return *this; - } - - /// post-decrement (it--) - iterator operator--(int) - { - iterator result = *this; - base_iterator::operator--(); - return result; - } - - /// pre-decrement (--it) - iterator& operator--() - { - base_iterator::operator--(); - return *this; - } - - /// add to iterator - iterator& operator+=(difference_type i) - { - base_iterator::operator+=(i); - return *this; - } - - /// subtract from iterator - iterator& operator-=(difference_type i) - { - base_iterator::operator-=(i); - return *this; - } - - /// add to iterator - iterator operator+(difference_type i) - { - auto result = *this; - result += i; - return result; - } - - /// subtract from iterator - iterator operator-(difference_type i) - { - auto result = *this; - result -= i; - return result; - } - - /// return difference - difference_type operator-(const iterator& other) const - { - return base_iterator::operator-(other); - } - - /// access to successor - reference operator[](difference_type n) const - { - return const_cast<reference>(base_iterator::operator[](n)); - } - - /// return the value of an iterator - reference value() const - { - return const_cast<reference>(base_iterator::value()); - } - }; - /*! @brief a template for a reverse iterator class From 1e981115c962b9fa3e750967bd994020f0610664 Mon Sep 17 00:00:00 2001 From: Yixin Zhang <m.yixin.zhang@gmail.com> Date: Fri, 9 Dec 2016 21:31:57 -0500 Subject: [PATCH 02/71] Fix issue #380: Signed integer overflow check Instead of checking something like `x * y + z > max` where `x * y` can overflow, check for `x > (max - z) / y` instead. --- src/json.hpp | 1350 +++++++++++++++------------------------------ src/json.hpp.re2c | 12 +- 2 files changed, 442 insertions(+), 920 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 0dfc11fd..2eaf9eb8 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9311,915 +9311,437 @@ class basic_json m_start = m_cursor; assert(m_start != nullptr); - - { - lexer_char_t yych; - unsigned int yyaccept = 0; - static const unsigned char yybm[] = - { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 32, 0, 0, 32, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 160, 128, 0, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 0, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }; - if ((m_limit - m_cursor) < 5) - { - fill_line_buffer(5); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yybm[0 + yych] & 32) - { - goto basic_json_parser_6; - } - if (yych <= '[') - { - if (yych <= '-') - { - if (yych <= '"') - { - if (yych <= 0x00) - { - goto basic_json_parser_2; - } - if (yych <= '!') - { - goto basic_json_parser_4; - } - goto basic_json_parser_9; - } - else - { - if (yych <= '+') - { - goto basic_json_parser_4; - } - if (yych <= ',') - { - goto basic_json_parser_10; - } - goto basic_json_parser_12; - } - } - else - { - if (yych <= '9') - { - if (yych <= '/') - { - goto basic_json_parser_4; - } - if (yych <= '0') - { - goto basic_json_parser_13; - } - goto basic_json_parser_15; - } - else - { - if (yych <= ':') - { - goto basic_json_parser_17; - } - if (yych <= 'Z') - { - goto basic_json_parser_4; - } - goto basic_json_parser_19; - } - } - } - else - { - if (yych <= 'n') - { - if (yych <= 'e') - { - if (yych == ']') - { - goto basic_json_parser_21; - } - goto basic_json_parser_4; - } - else - { - if (yych <= 'f') - { - goto basic_json_parser_23; - } - if (yych <= 'm') - { - goto basic_json_parser_4; - } - goto basic_json_parser_24; - } - } - else - { - if (yych <= 'z') - { - if (yych == 't') - { - goto basic_json_parser_25; - } - goto basic_json_parser_4; - } - else - { - if (yych <= '{') - { - goto basic_json_parser_26; - } - if (yych == '}') - { - goto basic_json_parser_28; - } - goto basic_json_parser_4; - } - } - } -basic_json_parser_2: - ++m_cursor; - { - last_token_type = token_type::end_of_input; - break; - } -basic_json_parser_4: - ++m_cursor; -basic_json_parser_5: - { - last_token_type = token_type::parse_error; - break; - } -basic_json_parser_6: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yybm[0 + yych] & 32) - { - goto basic_json_parser_6; - } - { - continue; - } -basic_json_parser_9: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych <= 0x1F) - { - goto basic_json_parser_5; - } - if (yych <= 0x7F) - { - goto basic_json_parser_31; - } - if (yych <= 0xC1) - { - goto basic_json_parser_5; - } - if (yych <= 0xF4) - { - goto basic_json_parser_31; - } - goto basic_json_parser_5; -basic_json_parser_10: - ++m_cursor; - { - last_token_type = token_type::value_separator; - break; - } -basic_json_parser_12: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_5; - } - if (yych <= '0') - { - goto basic_json_parser_13; - } - if (yych <= '9') - { - goto basic_json_parser_15; - } - goto basic_json_parser_5; -basic_json_parser_13: - yyaccept = 1; - yych = *(m_marker = ++m_cursor); - if (yych <= 'D') - { - if (yych == '.') - { - goto basic_json_parser_43; - } - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_44; - } - if (yych == 'e') - { - goto basic_json_parser_44; - } - } -basic_json_parser_14: - { - last_token_type = token_type::value_number; - break; - } -basic_json_parser_15: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - fill_line_buffer(3); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yybm[0 + yych] & 64) - { - goto basic_json_parser_15; - } - if (yych <= 'D') - { - if (yych == '.') - { - goto basic_json_parser_43; - } - goto basic_json_parser_14; - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_44; - } - if (yych == 'e') - { - goto basic_json_parser_44; - } - goto basic_json_parser_14; - } -basic_json_parser_17: - ++m_cursor; - { - last_token_type = token_type::name_separator; - break; - } -basic_json_parser_19: - ++m_cursor; - { - last_token_type = token_type::begin_array; - break; - } -basic_json_parser_21: - ++m_cursor; - { - last_token_type = token_type::end_array; - break; - } -basic_json_parser_23: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'a') - { - goto basic_json_parser_45; - } - goto basic_json_parser_5; -basic_json_parser_24: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'u') - { - goto basic_json_parser_46; - } - goto basic_json_parser_5; -basic_json_parser_25: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'r') - { - goto basic_json_parser_47; - } - goto basic_json_parser_5; -basic_json_parser_26: - ++m_cursor; - { - last_token_type = token_type::begin_object; - break; - } -basic_json_parser_28: - ++m_cursor; - { - last_token_type = token_type::end_object; - break; - } -basic_json_parser_30: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; -basic_json_parser_31: - if (yybm[0 + yych] & 128) - { - goto basic_json_parser_30; - } - if (yych <= 0xE0) - { - if (yych <= '\\') - { - if (yych <= 0x1F) - { - goto basic_json_parser_32; - } - if (yych <= '"') - { - goto basic_json_parser_33; - } - goto basic_json_parser_35; - } - else - { - if (yych <= 0xC1) - { - goto basic_json_parser_32; - } - if (yych <= 0xDF) - { - goto basic_json_parser_36; - } - goto basic_json_parser_37; - } - } - else - { - if (yych <= 0xEF) - { - if (yych == 0xED) - { - goto basic_json_parser_39; - } - goto basic_json_parser_38; - } - else - { - if (yych <= 0xF0) - { - goto basic_json_parser_40; - } - if (yych <= 0xF3) - { - goto basic_json_parser_41; - } - if (yych <= 0xF4) - { - goto basic_json_parser_42; - } - } - } -basic_json_parser_32: - m_cursor = m_marker; - if (yyaccept == 0) - { - goto basic_json_parser_5; - } - else - { - goto basic_json_parser_14; - } -basic_json_parser_33: - ++m_cursor; - { - last_token_type = token_type::value_string; - break; - } -basic_json_parser_35: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 'e') - { - if (yych <= '/') - { - if (yych == '"') - { - goto basic_json_parser_30; - } - if (yych <= '.') - { - goto basic_json_parser_32; - } - goto basic_json_parser_30; - } - else - { - if (yych <= '\\') - { - if (yych <= '[') - { - goto basic_json_parser_32; - } - goto basic_json_parser_30; - } - else - { - if (yych == 'b') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - } - } - else - { - if (yych <= 'q') - { - if (yych <= 'f') - { - goto basic_json_parser_30; - } - if (yych == 'n') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 's') - { - if (yych <= 'r') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 't') - { - goto basic_json_parser_30; - } - if (yych <= 'u') - { - goto basic_json_parser_48; - } - goto basic_json_parser_32; - } - } - } -basic_json_parser_36: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; -basic_json_parser_37: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x9F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_36; - } - goto basic_json_parser_32; -basic_json_parser_38: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_36; - } - goto basic_json_parser_32; -basic_json_parser_39: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0x9F) - { - goto basic_json_parser_36; - } - goto basic_json_parser_32; -basic_json_parser_40: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x8F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_38; - } - goto basic_json_parser_32; -basic_json_parser_41: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0xBF) - { - goto basic_json_parser_38; - } - goto basic_json_parser_32; -basic_json_parser_42: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 0x7F) - { - goto basic_json_parser_32; - } - if (yych <= 0x8F) - { - goto basic_json_parser_38; - } - goto basic_json_parser_32; -basic_json_parser_43: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_49; - } - goto basic_json_parser_32; -basic_json_parser_44: - yych = *++m_cursor; - if (yych <= ',') - { - if (yych == '+') - { - goto basic_json_parser_51; - } - goto basic_json_parser_32; - } - else - { - if (yych <= '-') - { - goto basic_json_parser_51; - } - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_52; - } - goto basic_json_parser_32; - } -basic_json_parser_45: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_54; - } - goto basic_json_parser_32; -basic_json_parser_46: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_55; - } - goto basic_json_parser_32; -basic_json_parser_47: - yych = *++m_cursor; - if (yych == 'u') - { - goto basic_json_parser_56; - } - goto basic_json_parser_32; -basic_json_parser_48: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_57; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_57; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_57; - } - goto basic_json_parser_32; - } -basic_json_parser_49: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) - { - fill_line_buffer(3); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= 'D') - { - if (yych <= '/') - { - goto basic_json_parser_14; - } - if (yych <= '9') - { - goto basic_json_parser_49; - } - goto basic_json_parser_14; - } - else - { - if (yych <= 'E') - { - goto basic_json_parser_44; - } - if (yych == 'e') - { - goto basic_json_parser_44; - } - goto basic_json_parser_14; - } -basic_json_parser_51: - yych = *++m_cursor; - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych >= ':') - { - goto basic_json_parser_32; - } -basic_json_parser_52: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '/') - { - goto basic_json_parser_14; - } - if (yych <= '9') - { - goto basic_json_parser_52; - } - goto basic_json_parser_14; -basic_json_parser_54: - yych = *++m_cursor; - if (yych == 's') - { - goto basic_json_parser_58; - } - goto basic_json_parser_32; -basic_json_parser_55: - yych = *++m_cursor; - if (yych == 'l') - { - goto basic_json_parser_59; - } - goto basic_json_parser_32; -basic_json_parser_56: - yych = *++m_cursor; - if (yych == 'e') - { - goto basic_json_parser_61; - } - goto basic_json_parser_32; -basic_json_parser_57: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_63; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_63; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_63; - } - goto basic_json_parser_32; - } -basic_json_parser_58: - yych = *++m_cursor; - if (yych == 'e') - { - goto basic_json_parser_64; - } - goto basic_json_parser_32; -basic_json_parser_59: - ++m_cursor; - { - last_token_type = token_type::literal_null; - break; - } -basic_json_parser_61: - ++m_cursor; - { - last_token_type = token_type::literal_true; - break; - } -basic_json_parser_63: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_66; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_66; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_66; - } - goto basic_json_parser_32; - } -basic_json_parser_64: - ++m_cursor; - { - last_token_type = token_type::literal_false; - break; - } -basic_json_parser_66: - ++m_cursor; - if (m_limit <= m_cursor) - { - fill_line_buffer(1); // LCOV_EXCL_LINE - } - yych = *m_cursor; - if (yych <= '@') - { - if (yych <= '/') - { - goto basic_json_parser_32; - } - if (yych <= '9') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } - else - { - if (yych <= 'F') - { - goto basic_json_parser_30; - } - if (yych <= '`') - { - goto basic_json_parser_32; - } - if (yych <= 'f') - { - goto basic_json_parser_30; - } - goto basic_json_parser_32; - } + + { + lexer_char_t yych; + unsigned int yyaccept = 0; + static const unsigned char yybm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32, 32, 0, 0, 32, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 160, 128, 0, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + if ((m_limit - m_cursor) < 5) fill_line_buffer(5); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yybm[0+yych] & 32) { + goto basic_json_parser_6; + } + if (yych <= '[') { + if (yych <= '-') { + if (yych <= '"') { + if (yych <= 0x00) goto basic_json_parser_2; + if (yych <= '!') goto basic_json_parser_4; + goto basic_json_parser_9; + } else { + if (yych <= '+') goto basic_json_parser_4; + if (yych <= ',') goto basic_json_parser_10; + goto basic_json_parser_12; } + } else { + if (yych <= '9') { + if (yych <= '/') goto basic_json_parser_4; + if (yych <= '0') goto basic_json_parser_13; + goto basic_json_parser_15; + } else { + if (yych <= ':') goto basic_json_parser_17; + if (yych <= 'Z') goto basic_json_parser_4; + goto basic_json_parser_19; + } + } + } else { + if (yych <= 'n') { + if (yych <= 'e') { + if (yych == ']') goto basic_json_parser_21; + goto basic_json_parser_4; + } else { + if (yych <= 'f') goto basic_json_parser_23; + if (yych <= 'm') goto basic_json_parser_4; + goto basic_json_parser_24; + } + } else { + if (yych <= 'z') { + if (yych == 't') goto basic_json_parser_25; + goto basic_json_parser_4; + } else { + if (yych <= '{') goto basic_json_parser_26; + if (yych == '}') goto basic_json_parser_28; + goto basic_json_parser_4; + } + } + } +basic_json_parser_2: + ++m_cursor; + { last_token_type = token_type::end_of_input; break; } +basic_json_parser_4: + ++m_cursor; +basic_json_parser_5: + { last_token_type = token_type::parse_error; break; } +basic_json_parser_6: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yybm[0+yych] & 32) { + goto basic_json_parser_6; + } + { continue; } +basic_json_parser_9: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych <= 0x1F) goto basic_json_parser_5; + if (yych <= 0x7F) goto basic_json_parser_31; + if (yych <= 0xC1) goto basic_json_parser_5; + if (yych <= 0xF4) goto basic_json_parser_31; + goto basic_json_parser_5; +basic_json_parser_10: + ++m_cursor; + { last_token_type = token_type::value_separator; break; } +basic_json_parser_12: + yych = *++m_cursor; + if (yych <= '/') goto basic_json_parser_5; + if (yych <= '0') goto basic_json_parser_13; + if (yych <= '9') goto basic_json_parser_15; + goto basic_json_parser_5; +basic_json_parser_13: + yyaccept = 1; + yych = *(m_marker = ++m_cursor); + if (yych <= 'D') { + if (yych == '.') goto basic_json_parser_43; + } else { + if (yych <= 'E') goto basic_json_parser_44; + if (yych == 'e') goto basic_json_parser_44; + } +basic_json_parser_14: + { last_token_type = token_type::value_number; break; } +basic_json_parser_15: + yyaccept = 1; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yybm[0+yych] & 64) { + goto basic_json_parser_15; + } + if (yych <= 'D') { + if (yych == '.') goto basic_json_parser_43; + goto basic_json_parser_14; + } else { + if (yych <= 'E') goto basic_json_parser_44; + if (yych == 'e') goto basic_json_parser_44; + goto basic_json_parser_14; + } +basic_json_parser_17: + ++m_cursor; + { last_token_type = token_type::name_separator; break; } +basic_json_parser_19: + ++m_cursor; + { last_token_type = token_type::begin_array; break; } +basic_json_parser_21: + ++m_cursor; + { last_token_type = token_type::end_array; break; } +basic_json_parser_23: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'a') goto basic_json_parser_45; + goto basic_json_parser_5; +basic_json_parser_24: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'u') goto basic_json_parser_46; + goto basic_json_parser_5; +basic_json_parser_25: + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'r') goto basic_json_parser_47; + goto basic_json_parser_5; +basic_json_parser_26: + ++m_cursor; + { last_token_type = token_type::begin_object; break; } +basic_json_parser_28: + ++m_cursor; + { last_token_type = token_type::end_object; break; } +basic_json_parser_30: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; +basic_json_parser_31: + if (yybm[0+yych] & 128) { + goto basic_json_parser_30; + } + if (yych <= 0xE0) { + if (yych <= '\\') { + if (yych <= 0x1F) goto basic_json_parser_32; + if (yych <= '"') goto basic_json_parser_33; + goto basic_json_parser_35; + } else { + if (yych <= 0xC1) goto basic_json_parser_32; + if (yych <= 0xDF) goto basic_json_parser_36; + goto basic_json_parser_37; + } + } else { + if (yych <= 0xEF) { + if (yych == 0xED) goto basic_json_parser_39; + goto basic_json_parser_38; + } else { + if (yych <= 0xF0) goto basic_json_parser_40; + if (yych <= 0xF3) goto basic_json_parser_41; + if (yych <= 0xF4) goto basic_json_parser_42; + } + } +basic_json_parser_32: + m_cursor = m_marker; + if (yyaccept == 0) { + goto basic_json_parser_5; + } else { + goto basic_json_parser_14; + } +basic_json_parser_33: + ++m_cursor; + { last_token_type = token_type::value_string; break; } +basic_json_parser_35: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 'e') { + if (yych <= '/') { + if (yych == '"') goto basic_json_parser_30; + if (yych <= '.') goto basic_json_parser_32; + goto basic_json_parser_30; + } else { + if (yych <= '\\') { + if (yych <= '[') goto basic_json_parser_32; + goto basic_json_parser_30; + } else { + if (yych == 'b') goto basic_json_parser_30; + goto basic_json_parser_32; + } + } + } else { + if (yych <= 'q') { + if (yych <= 'f') goto basic_json_parser_30; + if (yych == 'n') goto basic_json_parser_30; + goto basic_json_parser_32; + } else { + if (yych <= 's') { + if (yych <= 'r') goto basic_json_parser_30; + goto basic_json_parser_32; + } else { + if (yych <= 't') goto basic_json_parser_30; + if (yych <= 'u') goto basic_json_parser_48; + goto basic_json_parser_32; + } + } + } +basic_json_parser_36: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x7F) goto basic_json_parser_32; + if (yych <= 0xBF) goto basic_json_parser_30; + goto basic_json_parser_32; +basic_json_parser_37: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x9F) goto basic_json_parser_32; + if (yych <= 0xBF) goto basic_json_parser_36; + goto basic_json_parser_32; +basic_json_parser_38: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x7F) goto basic_json_parser_32; + if (yych <= 0xBF) goto basic_json_parser_36; + goto basic_json_parser_32; +basic_json_parser_39: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x7F) goto basic_json_parser_32; + if (yych <= 0x9F) goto basic_json_parser_36; + goto basic_json_parser_32; +basic_json_parser_40: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x8F) goto basic_json_parser_32; + if (yych <= 0xBF) goto basic_json_parser_38; + goto basic_json_parser_32; +basic_json_parser_41: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x7F) goto basic_json_parser_32; + if (yych <= 0xBF) goto basic_json_parser_38; + goto basic_json_parser_32; +basic_json_parser_42: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 0x7F) goto basic_json_parser_32; + if (yych <= 0x8F) goto basic_json_parser_38; + goto basic_json_parser_32; +basic_json_parser_43: + yych = *++m_cursor; + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_49; + goto basic_json_parser_32; +basic_json_parser_44: + yych = *++m_cursor; + if (yych <= ',') { + if (yych == '+') goto basic_json_parser_51; + goto basic_json_parser_32; + } else { + if (yych <= '-') goto basic_json_parser_51; + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_52; + goto basic_json_parser_32; + } +basic_json_parser_45: + yych = *++m_cursor; + if (yych == 'l') goto basic_json_parser_54; + goto basic_json_parser_32; +basic_json_parser_46: + yych = *++m_cursor; + if (yych == 'l') goto basic_json_parser_55; + goto basic_json_parser_32; +basic_json_parser_47: + yych = *++m_cursor; + if (yych == 'u') goto basic_json_parser_56; + goto basic_json_parser_32; +basic_json_parser_48: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= '@') { + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_57; + goto basic_json_parser_32; + } else { + if (yych <= 'F') goto basic_json_parser_57; + if (yych <= '`') goto basic_json_parser_32; + if (yych <= 'f') goto basic_json_parser_57; + goto basic_json_parser_32; + } +basic_json_parser_49: + yyaccept = 1; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= 'D') { + if (yych <= '/') goto basic_json_parser_14; + if (yych <= '9') goto basic_json_parser_49; + goto basic_json_parser_14; + } else { + if (yych <= 'E') goto basic_json_parser_44; + if (yych == 'e') goto basic_json_parser_44; + goto basic_json_parser_14; + } +basic_json_parser_51: + yych = *++m_cursor; + if (yych <= '/') goto basic_json_parser_32; + if (yych >= ':') goto basic_json_parser_32; +basic_json_parser_52: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= '/') goto basic_json_parser_14; + if (yych <= '9') goto basic_json_parser_52; + goto basic_json_parser_14; +basic_json_parser_54: + yych = *++m_cursor; + if (yych == 's') goto basic_json_parser_58; + goto basic_json_parser_32; +basic_json_parser_55: + yych = *++m_cursor; + if (yych == 'l') goto basic_json_parser_59; + goto basic_json_parser_32; +basic_json_parser_56: + yych = *++m_cursor; + if (yych == 'e') goto basic_json_parser_61; + goto basic_json_parser_32; +basic_json_parser_57: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= '@') { + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_63; + goto basic_json_parser_32; + } else { + if (yych <= 'F') goto basic_json_parser_63; + if (yych <= '`') goto basic_json_parser_32; + if (yych <= 'f') goto basic_json_parser_63; + goto basic_json_parser_32; + } +basic_json_parser_58: + yych = *++m_cursor; + if (yych == 'e') goto basic_json_parser_64; + goto basic_json_parser_32; +basic_json_parser_59: + ++m_cursor; + { last_token_type = token_type::literal_null; break; } +basic_json_parser_61: + ++m_cursor; + { last_token_type = token_type::literal_true; break; } +basic_json_parser_63: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= '@') { + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_66; + goto basic_json_parser_32; + } else { + if (yych <= 'F') goto basic_json_parser_66; + if (yych <= '`') goto basic_json_parser_32; + if (yych <= 'f') goto basic_json_parser_66; + goto basic_json_parser_32; + } +basic_json_parser_64: + ++m_cursor; + { last_token_type = token_type::literal_false; break; } +basic_json_parser_66: + ++m_cursor; + if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE + yych = *m_cursor; + if (yych <= '@') { + if (yych <= '/') goto basic_json_parser_32; + if (yych <= '9') goto basic_json_parser_30; + goto basic_json_parser_32; + } else { + if (yych <= 'F') goto basic_json_parser_30; + if (yych <= '`') goto basic_json_parser_32; + if (yych <= 'f') goto basic_json_parser_30; + goto basic_json_parser_32; + } + } } @@ -10619,19 +10141,19 @@ basic_json_parser_66: // skip if definitely not an integer if (type != value_t::number_float) { - // multiply last value by ten and add the new digit - auto temp = value * 10 + *curptr - '0'; + auto digit = *curptr - '0'; - // test for overflow - if (temp < value || temp > max) + // overflow if value * 10 + digit > max, move terms around + // to avoid overflow in intermediate values + if (value > (max - digit) / 10) { // overflow type = value_t::number_float; } else { - // no overflow - save it - value = temp; + // no overflow + value = value * 10 + digit; } } } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 72fd0474..57c502d3 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -9769,19 +9769,19 @@ class basic_json // skip if definitely not an integer if (type != value_t::number_float) { - // multiply last value by ten and add the new digit - auto temp = value * 10 + *curptr - '0'; + auto digit = *curptr - '0'; - // test for overflow - if (temp < value || temp > max) + // overflow if value * 10 + digit > max, move terms around + // to avoid overflow in intermediate values + if (value > (max - digit) / 10) { // overflow type = value_t::number_float; } else { - // no overflow - save it - value = temp; + // no overflow + value = value * 10 + digit; } } } From bd6422f5835beca46e0a3652fb6b5d93312fa442 Mon Sep 17 00:00:00 2001 From: Yixin Zhang <m.yixin.zhang@gmail.com> Date: Sat, 10 Dec 2016 14:21:13 -0500 Subject: [PATCH 03/71] Ran `make pretty` --- src/json.hpp | 1242 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 860 insertions(+), 382 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 2eaf9eb8..e64484e3 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9311,437 +9311,915 @@ class basic_json m_start = m_cursor; assert(m_start != nullptr); - - { - lexer_char_t yych; - unsigned int yyaccept = 0; - static const unsigned char yybm[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32, 32, 0, 0, 32, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 160, 128, 0, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 0, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }; - if ((m_limit - m_cursor) < 5) fill_line_buffer(5); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yybm[0+yych] & 32) { - goto basic_json_parser_6; - } - if (yych <= '[') { - if (yych <= '-') { - if (yych <= '"') { - if (yych <= 0x00) goto basic_json_parser_2; - if (yych <= '!') goto basic_json_parser_4; - goto basic_json_parser_9; - } else { - if (yych <= '+') goto basic_json_parser_4; - if (yych <= ',') goto basic_json_parser_10; - goto basic_json_parser_12; - } - } else { - if (yych <= '9') { - if (yych <= '/') goto basic_json_parser_4; - if (yych <= '0') goto basic_json_parser_13; - goto basic_json_parser_15; - } else { - if (yych <= ':') goto basic_json_parser_17; - if (yych <= 'Z') goto basic_json_parser_4; - goto basic_json_parser_19; - } - } - } else { - if (yych <= 'n') { - if (yych <= 'e') { - if (yych == ']') goto basic_json_parser_21; - goto basic_json_parser_4; - } else { - if (yych <= 'f') goto basic_json_parser_23; - if (yych <= 'm') goto basic_json_parser_4; - goto basic_json_parser_24; - } - } else { - if (yych <= 'z') { - if (yych == 't') goto basic_json_parser_25; - goto basic_json_parser_4; - } else { - if (yych <= '{') goto basic_json_parser_26; - if (yych == '}') goto basic_json_parser_28; - goto basic_json_parser_4; - } - } - } + + { + lexer_char_t yych; + unsigned int yyaccept = 0; + static const unsigned char yybm[] = + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32, 32, 0, 0, 32, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 160, 128, 0, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + if ((m_limit - m_cursor) < 5) + { + fill_line_buffer(5); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yybm[0 + yych] & 32) + { + goto basic_json_parser_6; + } + if (yych <= '[') + { + if (yych <= '-') + { + if (yych <= '"') + { + if (yych <= 0x00) + { + goto basic_json_parser_2; + } + if (yych <= '!') + { + goto basic_json_parser_4; + } + goto basic_json_parser_9; + } + else + { + if (yych <= '+') + { + goto basic_json_parser_4; + } + if (yych <= ',') + { + goto basic_json_parser_10; + } + goto basic_json_parser_12; + } + } + else + { + if (yych <= '9') + { + if (yych <= '/') + { + goto basic_json_parser_4; + } + if (yych <= '0') + { + goto basic_json_parser_13; + } + goto basic_json_parser_15; + } + else + { + if (yych <= ':') + { + goto basic_json_parser_17; + } + if (yych <= 'Z') + { + goto basic_json_parser_4; + } + goto basic_json_parser_19; + } + } + } + else + { + if (yych <= 'n') + { + if (yych <= 'e') + { + if (yych == ']') + { + goto basic_json_parser_21; + } + goto basic_json_parser_4; + } + else + { + if (yych <= 'f') + { + goto basic_json_parser_23; + } + if (yych <= 'm') + { + goto basic_json_parser_4; + } + goto basic_json_parser_24; + } + } + else + { + if (yych <= 'z') + { + if (yych == 't') + { + goto basic_json_parser_25; + } + goto basic_json_parser_4; + } + else + { + if (yych <= '{') + { + goto basic_json_parser_26; + } + if (yych == '}') + { + goto basic_json_parser_28; + } + goto basic_json_parser_4; + } + } + } basic_json_parser_2: - ++m_cursor; - { last_token_type = token_type::end_of_input; break; } + ++m_cursor; + { + last_token_type = token_type::end_of_input; + break; + } basic_json_parser_4: - ++m_cursor; + ++m_cursor; basic_json_parser_5: - { last_token_type = token_type::parse_error; break; } + { + last_token_type = token_type::parse_error; + break; + } basic_json_parser_6: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yybm[0+yych] & 32) { - goto basic_json_parser_6; - } - { continue; } + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yybm[0 + yych] & 32) + { + goto basic_json_parser_6; + } + { + continue; + } basic_json_parser_9: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych <= 0x1F) goto basic_json_parser_5; - if (yych <= 0x7F) goto basic_json_parser_31; - if (yych <= 0xC1) goto basic_json_parser_5; - if (yych <= 0xF4) goto basic_json_parser_31; - goto basic_json_parser_5; + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych <= 0x1F) + { + goto basic_json_parser_5; + } + if (yych <= 0x7F) + { + goto basic_json_parser_31; + } + if (yych <= 0xC1) + { + goto basic_json_parser_5; + } + if (yych <= 0xF4) + { + goto basic_json_parser_31; + } + goto basic_json_parser_5; basic_json_parser_10: - ++m_cursor; - { last_token_type = token_type::value_separator; break; } + ++m_cursor; + { + last_token_type = token_type::value_separator; + break; + } basic_json_parser_12: - yych = *++m_cursor; - if (yych <= '/') goto basic_json_parser_5; - if (yych <= '0') goto basic_json_parser_13; - if (yych <= '9') goto basic_json_parser_15; - goto basic_json_parser_5; + yych = *++m_cursor; + if (yych <= '/') + { + goto basic_json_parser_5; + } + if (yych <= '0') + { + goto basic_json_parser_13; + } + if (yych <= '9') + { + goto basic_json_parser_15; + } + goto basic_json_parser_5; basic_json_parser_13: - yyaccept = 1; - yych = *(m_marker = ++m_cursor); - if (yych <= 'D') { - if (yych == '.') goto basic_json_parser_43; - } else { - if (yych <= 'E') goto basic_json_parser_44; - if (yych == 'e') goto basic_json_parser_44; - } + yyaccept = 1; + yych = *(m_marker = ++m_cursor); + if (yych <= 'D') + { + if (yych == '.') + { + goto basic_json_parser_43; + } + } + else + { + if (yych <= 'E') + { + goto basic_json_parser_44; + } + if (yych == 'e') + { + goto basic_json_parser_44; + } + } basic_json_parser_14: - { last_token_type = token_type::value_number; break; } + { + last_token_type = token_type::value_number; + break; + } basic_json_parser_15: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yybm[0+yych] & 64) { - goto basic_json_parser_15; - } - if (yych <= 'D') { - if (yych == '.') goto basic_json_parser_43; - goto basic_json_parser_14; - } else { - if (yych <= 'E') goto basic_json_parser_44; - if (yych == 'e') goto basic_json_parser_44; - goto basic_json_parser_14; - } + yyaccept = 1; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) + { + fill_line_buffer(3); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yybm[0 + yych] & 64) + { + goto basic_json_parser_15; + } + if (yych <= 'D') + { + if (yych == '.') + { + goto basic_json_parser_43; + } + goto basic_json_parser_14; + } + else + { + if (yych <= 'E') + { + goto basic_json_parser_44; + } + if (yych == 'e') + { + goto basic_json_parser_44; + } + goto basic_json_parser_14; + } basic_json_parser_17: - ++m_cursor; - { last_token_type = token_type::name_separator; break; } + ++m_cursor; + { + last_token_type = token_type::name_separator; + break; + } basic_json_parser_19: - ++m_cursor; - { last_token_type = token_type::begin_array; break; } + ++m_cursor; + { + last_token_type = token_type::begin_array; + break; + } basic_json_parser_21: - ++m_cursor; - { last_token_type = token_type::end_array; break; } + ++m_cursor; + { + last_token_type = token_type::end_array; + break; + } basic_json_parser_23: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'a') goto basic_json_parser_45; - goto basic_json_parser_5; + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'a') + { + goto basic_json_parser_45; + } + goto basic_json_parser_5; basic_json_parser_24: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'u') goto basic_json_parser_46; - goto basic_json_parser_5; + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'u') + { + goto basic_json_parser_46; + } + goto basic_json_parser_5; basic_json_parser_25: - yyaccept = 0; - yych = *(m_marker = ++m_cursor); - if (yych == 'r') goto basic_json_parser_47; - goto basic_json_parser_5; + yyaccept = 0; + yych = *(m_marker = ++m_cursor); + if (yych == 'r') + { + goto basic_json_parser_47; + } + goto basic_json_parser_5; basic_json_parser_26: - ++m_cursor; - { last_token_type = token_type::begin_object; break; } + ++m_cursor; + { + last_token_type = token_type::begin_object; + break; + } basic_json_parser_28: - ++m_cursor; - { last_token_type = token_type::end_object; break; } + ++m_cursor; + { + last_token_type = token_type::end_object; + break; + } basic_json_parser_30: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; basic_json_parser_31: - if (yybm[0+yych] & 128) { - goto basic_json_parser_30; - } - if (yych <= 0xE0) { - if (yych <= '\\') { - if (yych <= 0x1F) goto basic_json_parser_32; - if (yych <= '"') goto basic_json_parser_33; - goto basic_json_parser_35; - } else { - if (yych <= 0xC1) goto basic_json_parser_32; - if (yych <= 0xDF) goto basic_json_parser_36; - goto basic_json_parser_37; - } - } else { - if (yych <= 0xEF) { - if (yych == 0xED) goto basic_json_parser_39; - goto basic_json_parser_38; - } else { - if (yych <= 0xF0) goto basic_json_parser_40; - if (yych <= 0xF3) goto basic_json_parser_41; - if (yych <= 0xF4) goto basic_json_parser_42; - } - } + if (yybm[0 + yych] & 128) + { + goto basic_json_parser_30; + } + if (yych <= 0xE0) + { + if (yych <= '\\') + { + if (yych <= 0x1F) + { + goto basic_json_parser_32; + } + if (yych <= '"') + { + goto basic_json_parser_33; + } + goto basic_json_parser_35; + } + else + { + if (yych <= 0xC1) + { + goto basic_json_parser_32; + } + if (yych <= 0xDF) + { + goto basic_json_parser_36; + } + goto basic_json_parser_37; + } + } + else + { + if (yych <= 0xEF) + { + if (yych == 0xED) + { + goto basic_json_parser_39; + } + goto basic_json_parser_38; + } + else + { + if (yych <= 0xF0) + { + goto basic_json_parser_40; + } + if (yych <= 0xF3) + { + goto basic_json_parser_41; + } + if (yych <= 0xF4) + { + goto basic_json_parser_42; + } + } + } basic_json_parser_32: - m_cursor = m_marker; - if (yyaccept == 0) { - goto basic_json_parser_5; - } else { - goto basic_json_parser_14; - } + m_cursor = m_marker; + if (yyaccept == 0) + { + goto basic_json_parser_5; + } + else + { + goto basic_json_parser_14; + } basic_json_parser_33: - ++m_cursor; - { last_token_type = token_type::value_string; break; } + ++m_cursor; + { + last_token_type = token_type::value_string; + break; + } basic_json_parser_35: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= 'e') { - if (yych <= '/') { - if (yych == '"') goto basic_json_parser_30; - if (yych <= '.') goto basic_json_parser_32; - goto basic_json_parser_30; - } else { - if (yych <= '\\') { - if (yych <= '[') goto basic_json_parser_32; - goto basic_json_parser_30; - } else { - if (yych == 'b') goto basic_json_parser_30; - goto basic_json_parser_32; - } - } - } else { - if (yych <= 'q') { - if (yych <= 'f') goto basic_json_parser_30; - if (yych == 'n') goto basic_json_parser_30; - goto basic_json_parser_32; - } else { - if (yych <= 's') { - if (yych <= 'r') goto basic_json_parser_30; - goto basic_json_parser_32; - } else { - if (yych <= 't') goto basic_json_parser_30; - if (yych <= 'u') goto basic_json_parser_48; - goto basic_json_parser_32; - } - } - } + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 'e') + { + if (yych <= '/') + { + if (yych == '"') + { + goto basic_json_parser_30; + } + if (yych <= '.') + { + goto basic_json_parser_32; + } + goto basic_json_parser_30; + } + else + { + if (yych <= '\\') + { + if (yych <= '[') + { + goto basic_json_parser_32; + } + goto basic_json_parser_30; + } + else + { + if (yych == 'b') + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; + } + } + } + else + { + if (yych <= 'q') + { + if (yych <= 'f') + { + goto basic_json_parser_30; + } + if (yych == 'n') + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 's') + { + if (yych <= 'r') + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 't') + { + goto basic_json_parser_30; + } + if (yych <= 'u') + { + goto basic_json_parser_48; + } + goto basic_json_parser_32; + } + } + } basic_json_parser_36: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= 0x7F) goto basic_json_parser_32; - if (yych <= 0xBF) goto basic_json_parser_30; - goto basic_json_parser_32; + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0xBF) + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; basic_json_parser_37: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= 0x9F) goto basic_json_parser_32; - if (yych <= 0xBF) goto basic_json_parser_36; - goto basic_json_parser_32; + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x9F) + { + goto basic_json_parser_32; + } + if (yych <= 0xBF) + { + goto basic_json_parser_36; + } + goto basic_json_parser_32; basic_json_parser_38: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= 0x7F) goto basic_json_parser_32; - if (yych <= 0xBF) goto basic_json_parser_36; - goto basic_json_parser_32; + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0xBF) + { + goto basic_json_parser_36; + } + goto basic_json_parser_32; basic_json_parser_39: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= 0x7F) goto basic_json_parser_32; - if (yych <= 0x9F) goto basic_json_parser_36; - goto basic_json_parser_32; + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0x9F) + { + goto basic_json_parser_36; + } + goto basic_json_parser_32; basic_json_parser_40: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= 0x8F) goto basic_json_parser_32; - if (yych <= 0xBF) goto basic_json_parser_38; - goto basic_json_parser_32; + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x8F) + { + goto basic_json_parser_32; + } + if (yych <= 0xBF) + { + goto basic_json_parser_38; + } + goto basic_json_parser_32; basic_json_parser_41: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= 0x7F) goto basic_json_parser_32; - if (yych <= 0xBF) goto basic_json_parser_38; - goto basic_json_parser_32; + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0xBF) + { + goto basic_json_parser_38; + } + goto basic_json_parser_32; basic_json_parser_42: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= 0x7F) goto basic_json_parser_32; - if (yych <= 0x8F) goto basic_json_parser_38; - goto basic_json_parser_32; + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 0x7F) + { + goto basic_json_parser_32; + } + if (yych <= 0x8F) + { + goto basic_json_parser_38; + } + goto basic_json_parser_32; basic_json_parser_43: - yych = *++m_cursor; - if (yych <= '/') goto basic_json_parser_32; - if (yych <= '9') goto basic_json_parser_49; - goto basic_json_parser_32; + yych = *++m_cursor; + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_49; + } + goto basic_json_parser_32; basic_json_parser_44: - yych = *++m_cursor; - if (yych <= ',') { - if (yych == '+') goto basic_json_parser_51; - goto basic_json_parser_32; - } else { - if (yych <= '-') goto basic_json_parser_51; - if (yych <= '/') goto basic_json_parser_32; - if (yych <= '9') goto basic_json_parser_52; - goto basic_json_parser_32; - } + yych = *++m_cursor; + if (yych <= ',') + { + if (yych == '+') + { + goto basic_json_parser_51; + } + goto basic_json_parser_32; + } + else + { + if (yych <= '-') + { + goto basic_json_parser_51; + } + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_52; + } + goto basic_json_parser_32; + } basic_json_parser_45: - yych = *++m_cursor; - if (yych == 'l') goto basic_json_parser_54; - goto basic_json_parser_32; + yych = *++m_cursor; + if (yych == 'l') + { + goto basic_json_parser_54; + } + goto basic_json_parser_32; basic_json_parser_46: - yych = *++m_cursor; - if (yych == 'l') goto basic_json_parser_55; - goto basic_json_parser_32; + yych = *++m_cursor; + if (yych == 'l') + { + goto basic_json_parser_55; + } + goto basic_json_parser_32; basic_json_parser_47: - yych = *++m_cursor; - if (yych == 'u') goto basic_json_parser_56; - goto basic_json_parser_32; + yych = *++m_cursor; + if (yych == 'u') + { + goto basic_json_parser_56; + } + goto basic_json_parser_32; basic_json_parser_48: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= '@') { - if (yych <= '/') goto basic_json_parser_32; - if (yych <= '9') goto basic_json_parser_57; - goto basic_json_parser_32; - } else { - if (yych <= 'F') goto basic_json_parser_57; - if (yych <= '`') goto basic_json_parser_32; - if (yych <= 'f') goto basic_json_parser_57; - goto basic_json_parser_32; - } + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_57; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 'F') + { + goto basic_json_parser_57; + } + if (yych <= '`') + { + goto basic_json_parser_32; + } + if (yych <= 'f') + { + goto basic_json_parser_57; + } + goto basic_json_parser_32; + } basic_json_parser_49: - yyaccept = 1; - m_marker = ++m_cursor; - if ((m_limit - m_cursor) < 3) fill_line_buffer(3); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= 'D') { - if (yych <= '/') goto basic_json_parser_14; - if (yych <= '9') goto basic_json_parser_49; - goto basic_json_parser_14; - } else { - if (yych <= 'E') goto basic_json_parser_44; - if (yych == 'e') goto basic_json_parser_44; - goto basic_json_parser_14; - } + yyaccept = 1; + m_marker = ++m_cursor; + if ((m_limit - m_cursor) < 3) + { + fill_line_buffer(3); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= 'D') + { + if (yych <= '/') + { + goto basic_json_parser_14; + } + if (yych <= '9') + { + goto basic_json_parser_49; + } + goto basic_json_parser_14; + } + else + { + if (yych <= 'E') + { + goto basic_json_parser_44; + } + if (yych == 'e') + { + goto basic_json_parser_44; + } + goto basic_json_parser_14; + } basic_json_parser_51: - yych = *++m_cursor; - if (yych <= '/') goto basic_json_parser_32; - if (yych >= ':') goto basic_json_parser_32; + yych = *++m_cursor; + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych >= ':') + { + goto basic_json_parser_32; + } basic_json_parser_52: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= '/') goto basic_json_parser_14; - if (yych <= '9') goto basic_json_parser_52; - goto basic_json_parser_14; + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '/') + { + goto basic_json_parser_14; + } + if (yych <= '9') + { + goto basic_json_parser_52; + } + goto basic_json_parser_14; basic_json_parser_54: - yych = *++m_cursor; - if (yych == 's') goto basic_json_parser_58; - goto basic_json_parser_32; + yych = *++m_cursor; + if (yych == 's') + { + goto basic_json_parser_58; + } + goto basic_json_parser_32; basic_json_parser_55: - yych = *++m_cursor; - if (yych == 'l') goto basic_json_parser_59; - goto basic_json_parser_32; + yych = *++m_cursor; + if (yych == 'l') + { + goto basic_json_parser_59; + } + goto basic_json_parser_32; basic_json_parser_56: - yych = *++m_cursor; - if (yych == 'e') goto basic_json_parser_61; - goto basic_json_parser_32; + yych = *++m_cursor; + if (yych == 'e') + { + goto basic_json_parser_61; + } + goto basic_json_parser_32; basic_json_parser_57: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= '@') { - if (yych <= '/') goto basic_json_parser_32; - if (yych <= '9') goto basic_json_parser_63; - goto basic_json_parser_32; - } else { - if (yych <= 'F') goto basic_json_parser_63; - if (yych <= '`') goto basic_json_parser_32; - if (yych <= 'f') goto basic_json_parser_63; - goto basic_json_parser_32; - } + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_63; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 'F') + { + goto basic_json_parser_63; + } + if (yych <= '`') + { + goto basic_json_parser_32; + } + if (yych <= 'f') + { + goto basic_json_parser_63; + } + goto basic_json_parser_32; + } basic_json_parser_58: - yych = *++m_cursor; - if (yych == 'e') goto basic_json_parser_64; - goto basic_json_parser_32; + yych = *++m_cursor; + if (yych == 'e') + { + goto basic_json_parser_64; + } + goto basic_json_parser_32; basic_json_parser_59: - ++m_cursor; - { last_token_type = token_type::literal_null; break; } + ++m_cursor; + { + last_token_type = token_type::literal_null; + break; + } basic_json_parser_61: - ++m_cursor; - { last_token_type = token_type::literal_true; break; } + ++m_cursor; + { + last_token_type = token_type::literal_true; + break; + } basic_json_parser_63: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= '@') { - if (yych <= '/') goto basic_json_parser_32; - if (yych <= '9') goto basic_json_parser_66; - goto basic_json_parser_32; - } else { - if (yych <= 'F') goto basic_json_parser_66; - if (yych <= '`') goto basic_json_parser_32; - if (yych <= 'f') goto basic_json_parser_66; - goto basic_json_parser_32; - } + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_66; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 'F') + { + goto basic_json_parser_66; + } + if (yych <= '`') + { + goto basic_json_parser_32; + } + if (yych <= 'f') + { + goto basic_json_parser_66; + } + goto basic_json_parser_32; + } basic_json_parser_64: - ++m_cursor; - { last_token_type = token_type::literal_false; break; } + ++m_cursor; + { + last_token_type = token_type::literal_false; + break; + } basic_json_parser_66: - ++m_cursor; - if (m_limit <= m_cursor) fill_line_buffer(1); // LCOV_EXCL_LINE - yych = *m_cursor; - if (yych <= '@') { - if (yych <= '/') goto basic_json_parser_32; - if (yych <= '9') goto basic_json_parser_30; - goto basic_json_parser_32; - } else { - if (yych <= 'F') goto basic_json_parser_30; - if (yych <= '`') goto basic_json_parser_32; - if (yych <= 'f') goto basic_json_parser_30; - goto basic_json_parser_32; - } - } + ++m_cursor; + if (m_limit <= m_cursor) + { + fill_line_buffer(1); // LCOV_EXCL_LINE + } + yych = *m_cursor; + if (yych <= '@') + { + if (yych <= '/') + { + goto basic_json_parser_32; + } + if (yych <= '9') + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; + } + else + { + if (yych <= 'F') + { + goto basic_json_parser_30; + } + if (yych <= '`') + { + goto basic_json_parser_32; + } + if (yych <= 'f') + { + goto basic_json_parser_30; + } + goto basic_json_parser_32; + } + } } From 703d4baf8b7589a033b36eb4d394533eebc62552 Mon Sep 17 00:00:00 2001 From: Yixin Zhang <m.yixin.zhang@gmail.com> Date: Mon, 12 Dec 2016 20:59:43 -0500 Subject: [PATCH 04/71] Fixed conversion warnings Use static_cast on digit. --- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index e64484e3..ff409559 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -10619,7 +10619,7 @@ basic_json_parser_66: // skip if definitely not an integer if (type != value_t::number_float) { - auto digit = *curptr - '0'; + auto digit = static_cast<number_unsigned_t>(*curptr - '0'); // overflow if value * 10 + digit > max, move terms around // to avoid overflow in intermediate values diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 57c502d3..4366fe6d 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -9769,7 +9769,7 @@ class basic_json // skip if definitely not an integer if (type != value_t::number_float) { - auto digit = *curptr - '0'; + auto digit = static_cast<number_unsigned_t>(*curptr - '0'); // overflow if value * 10 + digit > max, move terms around // to avoid overflow in intermediate values From f5d4a9c4eb5ded73dfe3307342592337f3c8dde0 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 13 Dec 2016 17:51:46 +0100 Subject: [PATCH 05/71] :construction_worker: added Clang 3.9.0 and sanitizer build #394 --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index bb0e504d..fb8f44bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,6 +41,15 @@ matrix: after_success: - make check TEST_PREFIX="valgrind --error-exitcode=1 --leak-check=full " TEST_PATTERN="" + # CLang sanitizers + + - os: linux + env: LLVM_VERSION=3.9.0 + compiler: clang + after_success: + - make clean + - CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" make check + # cppcheck - os: linux @@ -190,6 +199,7 @@ cache: - ${TRAVIS_BUILD_DIR}/deps/llvm-3.7.1 - ${TRAVIS_BUILD_DIR}/deps/llvm-3.8.0 - ${TRAVIS_BUILD_DIR}/deps/llvm-3.8.1 + - ${TRAVIS_BUILD_DIR}/deps/llvm-3.9.0 install: From 9b5411db57b13ac8900d57905fc9b52b3be0e71c Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 13 Dec 2016 17:55:41 +0100 Subject: [PATCH 06/71] :construction_worker: clang 3.9.0 is not working #394 --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fb8f44bd..b87008a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,9 @@ matrix: # CLang sanitizers - os: linux - env: LLVM_VERSION=3.9.0 + env: + - LLVM_VERSION=3.8.1 + - SPECIAL=sanitizers compiler: clang after_success: - make clean @@ -199,7 +201,6 @@ cache: - ${TRAVIS_BUILD_DIR}/deps/llvm-3.7.1 - ${TRAVIS_BUILD_DIR}/deps/llvm-3.8.0 - ${TRAVIS_BUILD_DIR}/deps/llvm-3.8.1 - - ${TRAVIS_BUILD_DIR}/deps/llvm-3.9.0 install: From 3f089cab2bf21b2cca172f2662ce25e8c8ba2535 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 13 Dec 2016 18:24:16 +0100 Subject: [PATCH 07/71] :construction_worker: moved instructed build to "before_script" #394 --- .travis.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index b87008a4..c07b610a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,16 +41,15 @@ matrix: after_success: - make check TEST_PREFIX="valgrind --error-exitcode=1 --leak-check=full " TEST_PATTERN="" - # CLang sanitizers + # cLang sanitizer - os: linux env: - LLVM_VERSION=3.8.1 - - SPECIAL=sanitizers + - SPECIAL=sanitizer compiler: clang - after_success: - - make clean - - CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" make check + before_script: + - CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" make # cppcheck From c3fac19692fa4946da8b79931d43914c6075f766 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 13 Dec 2016 19:41:36 +0100 Subject: [PATCH 08/71] :construction_worker: another try for sanitizers #394 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c07b610a..c7edd7e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,7 @@ matrix: - SPECIAL=sanitizer compiler: clang before_script: - - CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" make + - make clang_sanitize # cppcheck From 92e28c31530a2a2411fe6711691aa8e2757c79b0 Mon Sep 17 00:00:00 2001 From: Bosswestfalen <bosswestfalen@users.noreply.github.com> Date: Tue, 13 Dec 2016 20:30:56 +0100 Subject: [PATCH 09/71] added missing changes in json.hpp.re2c --- src/json.hpp.re2c | 239 ++++++++++------------------------------------ 1 file changed, 51 insertions(+), 188 deletions(-) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 76084140..520d2204 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8204,10 +8204,10 @@ class basic_json public: /*! - @brief a const random access iterator for the @ref basic_json class + @brief a template for a random access iterator for the @ref basic_json class - This class implements a const iterator for the @ref basic_json class. From - this class, the @ref iterator class is derived. + This class implements a both iterators (iterator and const_iterator) + for the @ref basic_json class. @note An iterator is called *initialized* when a pointer to a JSON value has been set (e.g., by a constructor or a copy assignment). If the @@ -8222,25 +8222,35 @@ class basic_json @since version 1.0.0 */ - class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json> + template <typename U> + class iter_impl : public std::iterator<std::random_access_iterator_tag, U> { /// allow basic_json to access private members friend class basic_json; + // make sure U is basic_json or const basic_json + static_assert(std::is_same<U, basic_json>::value + or std::is_same<U, const basic_json>::value, + "iter_impl only accepts (const) basic_json"); + public: /// the type of the values when the iterator is dereferenced using value_type = typename basic_json::value_type; /// a type to represent differences between iterators using difference_type = typename basic_json::difference_type; /// defines a pointer to the type iterated over (value_type) - using pointer = typename basic_json::const_pointer; + using pointer = typename std::conditional<std::is_const<U>::value, + typename basic_json::const_pointer, + typename basic_json::pointer>::type; /// defines a reference to the type iterated over (value_type) - using reference = typename basic_json::const_reference; + using reference = typename std::conditional<std::is_const<U>::value, + typename basic_json::const_reference, + typename basic_json::reference>::type; /// the category of the iterator using iterator_category = std::bidirectional_iterator_tag; /// default constructor - const_iterator() = default; + iter_impl() = default; /*! @brief constructor for a given JSON instance @@ -8248,7 +8258,7 @@ class basic_json @pre object != nullptr @post The iterator is initialized; i.e. `m_object != nullptr`. */ - explicit const_iterator(pointer object) noexcept + explicit iter_impl(pointer object) noexcept : m_object(object) { assert(m_object != nullptr); @@ -8275,37 +8285,25 @@ class basic_json } } - /*! - @brief copy constructor given a non-const iterator - @param[in] other iterator to copy from - @note It is not checked whether @a other is initialized. + /* + Use operator const_iterator instead of + const_iterator(const iterator& other) noexcept + to avoid two class definitions for iterator and const_iterator. + + This function is only called if this class is an iterator. + If this class is a const_iterator this function is not called. */ - explicit const_iterator(const iterator& other) noexcept - : m_object(other.m_object) - { - if (m_object != nullptr) - { - switch (m_object->m_type) - { - case basic_json::value_t::object: - { - m_it.object_iterator = other.m_it.object_iterator; - break; - } + operator const_iterator() const + { + const_iterator ret; - case basic_json::value_t::array: - { - m_it.array_iterator = other.m_it.array_iterator; - break; - } - - default: - { - m_it.primitive_iterator = other.m_it.primitive_iterator; - break; - } - } + if (m_object) + { + ret.m_object = m_object; + ret.m_it = m_it; } + + return ret; } /*! @@ -8313,7 +8311,7 @@ class basic_json @param[in] other iterator to copy from @note It is not checked whether @a other is initialized. */ - const_iterator(const const_iterator& other) noexcept + iter_impl(const iter_impl& other) noexcept : m_object(other.m_object), m_it(other.m_it) {} @@ -8322,7 +8320,7 @@ class basic_json @param[in,out] other iterator to copy from @note It is not checked whether @a other is initialized. */ - const_iterator& operator=(const_iterator other) noexcept( + iter_impl& operator=(iter_impl other) noexcept( std::is_nothrow_move_constructible<pointer>::value and std::is_nothrow_move_assignable<pointer>::value and std::is_nothrow_move_constructible<internal_iterator>::value and @@ -8484,7 +8482,7 @@ class basic_json @brief post-increment (it++) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator operator++(int) + iter_impl operator++(int) { auto result = *this; ++(*this); @@ -8495,7 +8493,7 @@ class basic_json @brief pre-increment (++it) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator& operator++() + iter_impl& operator++() { assert(m_object != nullptr); @@ -8527,7 +8525,7 @@ class basic_json @brief post-decrement (it--) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator operator--(int) + iter_impl operator--(int) { auto result = *this; --(*this); @@ -8538,7 +8536,7 @@ class basic_json @brief pre-decrement (--it) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator& operator--() + iter_impl& operator--() { assert(m_object != nullptr); @@ -8570,7 +8568,7 @@ class basic_json @brief comparison: equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator==(const const_iterator& other) const + bool operator==(const iter_impl& other) const { // if objects are not the same, the comparison is undefined if (m_object != other.m_object) @@ -8603,7 +8601,7 @@ class basic_json @brief comparison: not equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator!=(const const_iterator& other) const + bool operator!=(const iter_impl& other) const { return not operator==(other); } @@ -8612,7 +8610,7 @@ class basic_json @brief comparison: smaller @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator<(const const_iterator& other) const + bool operator<(const iter_impl& other) const { // if objects are not the same, the comparison is undefined if (m_object != other.m_object) @@ -8645,7 +8643,7 @@ class basic_json @brief comparison: less than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator<=(const const_iterator& other) const + bool operator<=(const iter_impl& other) const { return not other.operator < (*this); } @@ -8654,7 +8652,7 @@ class basic_json @brief comparison: greater than @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator>(const const_iterator& other) const + bool operator>(const iter_impl& other) const { return not operator<=(other); } @@ -8663,7 +8661,7 @@ class basic_json @brief comparison: greater than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator>=(const const_iterator& other) const + bool operator>=(const iter_impl& other) const { return not operator<(other); } @@ -8672,7 +8670,7 @@ class basic_json @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator& operator+=(difference_type i) + iter_impl& operator+=(difference_type i) { assert(m_object != nullptr); @@ -8703,7 +8701,7 @@ class basic_json @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator& operator-=(difference_type i) + iter_impl& operator-=(difference_type i) { return operator+=(-i); } @@ -8712,7 +8710,7 @@ class basic_json @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator operator+(difference_type i) + iter_impl operator+(difference_type i) { auto result = *this; result += i; @@ -8723,7 +8721,7 @@ class basic_json @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const_iterator operator-(difference_type i) + iter_impl operator-(difference_type i) { auto result = *this; result -= i; @@ -8734,7 +8732,7 @@ class basic_json @brief return difference @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - difference_type operator-(const const_iterator& other) const + difference_type operator-(const iter_impl& other) const { assert(m_object != nullptr); @@ -8830,141 +8828,6 @@ class basic_json internal_iterator m_it = internal_iterator(); }; - /*! - @brief a mutable random access iterator for the @ref basic_json class - - @requirement The class satisfies the following concept requirements: - - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator): - The iterator that can be moved to point (forward and backward) to any - element in constant time. - - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator): - It is possible to write to the pointed-to element. - - @since version 1.0.0 - */ - class iterator : public const_iterator - { - public: - using base_iterator = const_iterator; - using pointer = typename basic_json::pointer; - using reference = typename basic_json::reference; - - /// default constructor - iterator() = default; - - /// constructor for a given JSON instance - explicit iterator(pointer object) noexcept - : base_iterator(object) - {} - - /// copy constructor - iterator(const iterator& other) noexcept - : base_iterator(other) - {} - - /// copy assignment - iterator& operator=(iterator other) noexcept( - std::is_nothrow_move_constructible<pointer>::value and - std::is_nothrow_move_assignable<pointer>::value and - std::is_nothrow_move_constructible<internal_iterator>::value and - std::is_nothrow_move_assignable<internal_iterator>::value - ) - { - base_iterator::operator=(other); - return *this; - } - - /// return a reference to the value pointed to by the iterator - reference operator*() const - { - return const_cast<reference>(base_iterator::operator*()); - } - - /// dereference the iterator - pointer operator->() const - { - return const_cast<pointer>(base_iterator::operator->()); - } - - /// post-increment (it++) - iterator operator++(int) - { - iterator result = *this; - base_iterator::operator++(); - return result; - } - - /// pre-increment (++it) - iterator& operator++() - { - base_iterator::operator++(); - return *this; - } - - /// post-decrement (it--) - iterator operator--(int) - { - iterator result = *this; - base_iterator::operator--(); - return result; - } - - /// pre-decrement (--it) - iterator& operator--() - { - base_iterator::operator--(); - return *this; - } - - /// add to iterator - iterator& operator+=(difference_type i) - { - base_iterator::operator+=(i); - return *this; - } - - /// subtract from iterator - iterator& operator-=(difference_type i) - { - base_iterator::operator-=(i); - return *this; - } - - /// add to iterator - iterator operator+(difference_type i) - { - auto result = *this; - result += i; - return result; - } - - /// subtract from iterator - iterator operator-(difference_type i) - { - auto result = *this; - result -= i; - return result; - } - - /// return difference - difference_type operator-(const iterator& other) const - { - return base_iterator::operator-(other); - } - - /// access to successor - reference operator[](difference_type n) const - { - return const_cast<reference>(base_iterator::operator[](n)); - } - - /// return the value of an iterator - reference value() const - { - return const_cast<reference>(base_iterator::value()); - } - }; - /*! @brief a template for a reverse iterator class From dfafd2c259ae65ac135b12f03c4fd5bb32670456 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 13 Dec 2016 21:23:59 +0100 Subject: [PATCH 10/71] :construction_worker: can't get clang sanitizer to work #394 See https://travis-ci.org/nlohmann/json/jobs/183684093 for a failing build. --- .travis.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index c7edd7e0..0f9010b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,13 +43,13 @@ matrix: # cLang sanitizer - - os: linux - env: - - LLVM_VERSION=3.8.1 - - SPECIAL=sanitizer - compiler: clang - before_script: - - make clang_sanitize + #- os: linux + # env: + # - LLVM_VERSION=3.8.1 + # - SPECIAL=sanitizer + # compiler: clang + # before_script: + # - make clang_sanitize # cppcheck From 2f94c30baddaa6267961b3d61a86c438c3e9ac2c Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 13 Dec 2016 21:46:07 +0100 Subject: [PATCH 11/71] :white_check_mark: added a regression test for #380 / #390 --- README.md | 1 + test/src/unit-regression.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/README.md b/README.md index 04bdf192..fa045f7f 100644 --- a/README.md +++ b/README.md @@ -583,6 +583,7 @@ I deeply appreciate the help of the following people. - [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser and improved the benchmarking code. - [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan. - [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning. +- [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check. Thanks a lot for helping out! diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index f6d05eff..3125c44e 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -533,4 +533,11 @@ TEST_CASE("regression tests") json j3 = json::parse("-9223372036854775809"); CHECK(j3.is_number_float()); } + + SECTION("issue #380 - bug in overflow detection when parsing integers") + { + json j = json::parse("166020696663385964490"); + CHECK(j.is_number_float()); + CHECK(j.dump() == "1.66020696663386e+20"); + } } From f24e4f680ebeff7fdc7a824fa83fff2c504d6638 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 14 Dec 2016 22:30:09 +0100 Subject: [PATCH 12/71] :art: cleanup after PR #395 --- README.md | 1 + src/json.hpp | 35 +++++++++++++++++------------------ src/json.hpp.re2c | 37 +++++++++++++++++++------------------ 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index fa045f7f..644b37f2 100644 --- a/README.md +++ b/README.md @@ -584,6 +584,7 @@ I deeply appreciate the help of the following people. - [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan. - [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning. - [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check. +- [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one. Thanks a lot for helping out! diff --git a/src/json.hpp b/src/json.hpp index aed03fa3..d066bd2c 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -228,6 +228,7 @@ class basic_json public: // forward declarations + template<typename U> class iter_impl; template<typename Base> class json_reverse_iterator; class json_pointer; @@ -261,8 +262,6 @@ class basic_json /// the type of an element const pointer using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; - // forward declaration for iterators - template <typename U> class iter_impl; /// an iterator for a basic_json container using iterator = iter_impl<basic_json>; /// a const iterator for a basic_json container @@ -8208,8 +8207,8 @@ class basic_json /*! @brief a template for a random access iterator for the @ref basic_json class - This class implements a both iterators (iterator and const_iterator) - for the @ref basic_json class. + This class implements a both iterators (iterator and const_iterator) for the + @ref basic_json class. @note An iterator is called *initialized* when a pointer to a JSON value has been set (e.g., by a constructor or a copy assignment). If the @@ -8222,9 +8221,9 @@ class basic_json The iterator that can be moved to point (forward and backward) to any element in constant time. - @since version 1.0.0 + @since version 1.0.0, simplified in version 2.0.9 */ - template <typename U> + template<typename U> class iter_impl : public std::iterator<std::random_access_iterator_tag, U> { /// allow basic_json to access private members @@ -8242,12 +8241,12 @@ class basic_json using difference_type = typename basic_json::difference_type; /// defines a pointer to the type iterated over (value_type) using pointer = typename std::conditional<std::is_const<U>::value, - typename basic_json::const_pointer, - typename basic_json::pointer>::type; + typename basic_json::const_pointer, + typename basic_json::pointer>::type; /// defines a reference to the type iterated over (value_type) using reference = typename std::conditional<std::is_const<U>::value, - typename basic_json::const_reference, - typename basic_json::reference>::type; + typename basic_json::const_reference, + typename basic_json::reference>::type; /// the category of the iterator using iterator_category = std::bidirectional_iterator_tag; @@ -8288,19 +8287,19 @@ class basic_json } /* - Use operator const_iterator instead of - const_iterator(const iterator& other) noexcept - to avoid two class definitions for iterator and const_iterator. + Use operator `const_iterator` instead of `const_iterator(const iterator& + other) noexcept` to avoid two class definitions for @ref iterator and + @ref const_iterator. - This function is only called if this class is an iterator. - If this class is a const_iterator this function is not called. + This function is only called if this class is an @ref iterator. If this + class is a @ref const_iterator this function is not called. */ operator const_iterator() const - { - const_iterator ret; + { + const_iterator ret; if (m_object) - { + { ret.m_object = m_object; ret.m_it = m_it; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 17813c79..ded56b9f 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -228,6 +228,7 @@ class basic_json public: // forward declarations + template<typename U> class iter_impl; template<typename Base> class json_reverse_iterator; class json_pointer; @@ -262,9 +263,9 @@ class basic_json using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; /// an iterator for a basic_json container - class iterator; + using iterator = iter_impl<basic_json>; /// a const iterator for a basic_json container - class const_iterator; + using const_iterator = iter_impl<const basic_json>; /// a reverse iterator for a basic_json container using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; /// a const reverse iterator for a basic_json container @@ -8206,8 +8207,8 @@ class basic_json /*! @brief a template for a random access iterator for the @ref basic_json class - This class implements a both iterators (iterator and const_iterator) - for the @ref basic_json class. + This class implements a both iterators (iterator and const_iterator) for the + @ref basic_json class. @note An iterator is called *initialized* when a pointer to a JSON value has been set (e.g., by a constructor or a copy assignment). If the @@ -8220,9 +8221,9 @@ class basic_json The iterator that can be moved to point (forward and backward) to any element in constant time. - @since version 1.0.0 + @since version 1.0.0, simplified in version 2.0.9 */ - template <typename U> + template<typename U> class iter_impl : public std::iterator<std::random_access_iterator_tag, U> { /// allow basic_json to access private members @@ -8240,12 +8241,12 @@ class basic_json using difference_type = typename basic_json::difference_type; /// defines a pointer to the type iterated over (value_type) using pointer = typename std::conditional<std::is_const<U>::value, - typename basic_json::const_pointer, - typename basic_json::pointer>::type; + typename basic_json::const_pointer, + typename basic_json::pointer>::type; /// defines a reference to the type iterated over (value_type) using reference = typename std::conditional<std::is_const<U>::value, - typename basic_json::const_reference, - typename basic_json::reference>::type; + typename basic_json::const_reference, + typename basic_json::reference>::type; /// the category of the iterator using iterator_category = std::bidirectional_iterator_tag; @@ -8286,19 +8287,19 @@ class basic_json } /* - Use operator const_iterator instead of - const_iterator(const iterator& other) noexcept - to avoid two class definitions for iterator and const_iterator. + Use operator `const_iterator` instead of `const_iterator(const iterator& + other) noexcept` to avoid two class definitions for @ref iterator and + @ref const_iterator. - This function is only called if this class is an iterator. - If this class is a const_iterator this function is not called. + This function is only called if this class is an @ref iterator. If this + class is a @ref const_iterator this function is not called. */ operator const_iterator() const - { - const_iterator ret; + { + const_iterator ret; if (m_object) - { + { ret.m_object = m_object; ret.m_it = m_it; } From f6f7fed99a89d99b43ec20e65e08f706a00fa69a Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Fri, 16 Dec 2016 18:57:19 +0100 Subject: [PATCH 13/71] :rotating_light: removed some warnings --- src/json.hpp | 50 +++++++++++++++++++++++------------------------ src/json.hpp.re2c | 50 +++++++++++++++++++++++------------------------ 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index d066bd2c..d9760cfc 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6982,7 +6982,7 @@ class basic_json case 0xd9: // str 8 { - const auto len = get_from_vector<uint8_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -6990,7 +6990,7 @@ class basic_json case 0xda: // str 16 { - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -6998,7 +6998,7 @@ class basic_json case 0xdb: // str 32 { - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7007,7 +7007,7 @@ class basic_json case 0xdc: // array 16 { basic_json result = value_t::array; - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { @@ -7019,7 +7019,7 @@ class basic_json case 0xdd: // array 32 { basic_json result = value_t::array; - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { @@ -7031,7 +7031,7 @@ class basic_json case 0xde: // map 16 { basic_json result = value_t::object; - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { @@ -7044,7 +7044,7 @@ class basic_json case 0xdf: // map 32 { basic_json result = value_t::object; - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { @@ -7056,7 +7056,7 @@ class basic_json default: { - throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx)); + throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))); } } } @@ -7216,7 +7216,7 @@ class basic_json case 0x76: case 0x77: { - const size_t len = v[current_idx] - 0x60; + const auto len = static_cast<size_t>(v[current_idx] - 0x60); const size_t offset = current_idx + 1; idx += len; // skip content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7224,7 +7224,7 @@ class basic_json case 0x78: // UTF-8 string (one-byte uint8_t for n follows) { - const auto len = get_from_vector<uint8_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7232,7 +7232,7 @@ class basic_json case 0x79: // UTF-8 string (two-byte uint16_t for n follow) { - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7240,7 +7240,7 @@ class basic_json case 0x7a: // UTF-8 string (four-byte uint32_t for n follow) { - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7248,7 +7248,7 @@ class basic_json case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow) { - const auto len = get_from_vector<uint64_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx)); const size_t offset = current_idx + 9; idx += len + 8; // skip 8 size bytes + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7294,7 +7294,7 @@ class basic_json case 0x97: { basic_json result = value_t::array; - const size_t len = v[current_idx] - 0x80; + const auto len = static_cast<size_t>(v[current_idx] - 0x80); for (size_t i = 0; i < len; ++i) { result.push_back(from_cbor_internal(v, idx)); @@ -7305,7 +7305,7 @@ class basic_json case 0x98: // array (one-byte uint8_t for n follows) { basic_json result = value_t::array; - const auto len = get_from_vector<uint8_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); idx += 1; // skip 1 size byte for (size_t i = 0; i < len; ++i) { @@ -7317,7 +7317,7 @@ class basic_json case 0x99: // array (two-byte uint16_t for n follow) { basic_json result = value_t::array; - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); idx += 2; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { @@ -7329,7 +7329,7 @@ class basic_json case 0x9a: // array (four-byte uint32_t for n follow) { basic_json result = value_t::array; - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { @@ -7341,7 +7341,7 @@ class basic_json case 0x9b: // array (eight-byte uint64_t for n follow) { basic_json result = value_t::array; - const auto len = get_from_vector<uint64_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx)); idx += 8; // skip 8 size bytes for (size_t i = 0; i < len; ++i) { @@ -7389,7 +7389,7 @@ class basic_json case 0xb7: { basic_json result = value_t::object; - const size_t len = v[current_idx] - 0xa0; + const auto len = static_cast<size_t>(v[current_idx] - 0xa0); for (size_t i = 0; i < len; ++i) { std::string key = from_cbor_internal(v, idx); @@ -7401,7 +7401,7 @@ class basic_json case 0xb8: // map (one-byte uint8_t for n follows) { basic_json result = value_t::object; - const auto len = get_from_vector<uint8_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); idx += 1; // skip 1 size byte for (size_t i = 0; i < len; ++i) { @@ -7414,7 +7414,7 @@ class basic_json case 0xb9: // map (two-byte uint16_t for n follow) { basic_json result = value_t::object; - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { @@ -7427,7 +7427,7 @@ class basic_json case 0xba: // map (four-byte uint32_t for n follow) { basic_json result = value_t::object; - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { @@ -7440,7 +7440,7 @@ class basic_json case 0xbb: // map (eight-byte uint64_t for n follow) { basic_json result = value_t::object; - const auto len = get_from_vector<uint64_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx)); idx += 8; // skip 8 size bytes for (size_t i = 0; i < len; ++i) { @@ -7534,7 +7534,7 @@ class basic_json default: // anything else (0xFF is handled inside the other types) { - throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(v[current_idx])); + throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))); } } } @@ -10516,7 +10516,7 @@ basic_json_parser_66: { // we cannot simply negate value (== max == -INT64_MIN), // see https://github.com/nlohmann/json/issues/389 - result.m_value.number_integer = INT64_MIN; + result.m_value.number_integer = static_cast<number_integer_t>(INT64_MIN); } else { diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index ded56b9f..f2e5d991 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6982,7 +6982,7 @@ class basic_json case 0xd9: // str 8 { - const auto len = get_from_vector<uint8_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -6990,7 +6990,7 @@ class basic_json case 0xda: // str 16 { - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -6998,7 +6998,7 @@ class basic_json case 0xdb: // str 32 { - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7007,7 +7007,7 @@ class basic_json case 0xdc: // array 16 { basic_json result = value_t::array; - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { @@ -7019,7 +7019,7 @@ class basic_json case 0xdd: // array 32 { basic_json result = value_t::array; - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { @@ -7031,7 +7031,7 @@ class basic_json case 0xde: // map 16 { basic_json result = value_t::object; - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { @@ -7044,7 +7044,7 @@ class basic_json case 0xdf: // map 32 { basic_json result = value_t::object; - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { @@ -7056,7 +7056,7 @@ class basic_json default: { - throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx)); + throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))); } } } @@ -7216,7 +7216,7 @@ class basic_json case 0x76: case 0x77: { - const size_t len = v[current_idx] - 0x60; + const auto len = static_cast<size_t>(v[current_idx] - 0x60); const size_t offset = current_idx + 1; idx += len; // skip content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7224,7 +7224,7 @@ class basic_json case 0x78: // UTF-8 string (one-byte uint8_t for n follows) { - const auto len = get_from_vector<uint8_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7232,7 +7232,7 @@ class basic_json case 0x79: // UTF-8 string (two-byte uint16_t for n follow) { - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7240,7 +7240,7 @@ class basic_json case 0x7a: // UTF-8 string (four-byte uint32_t for n follow) { - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7248,7 +7248,7 @@ class basic_json case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow) { - const auto len = get_from_vector<uint64_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx)); const size_t offset = current_idx + 9; idx += len + 8; // skip 8 size bytes + content bytes return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); @@ -7294,7 +7294,7 @@ class basic_json case 0x97: { basic_json result = value_t::array; - const size_t len = v[current_idx] - 0x80; + const auto len = static_cast<size_t>(v[current_idx] - 0x80); for (size_t i = 0; i < len; ++i) { result.push_back(from_cbor_internal(v, idx)); @@ -7305,7 +7305,7 @@ class basic_json case 0x98: // array (one-byte uint8_t for n follows) { basic_json result = value_t::array; - const auto len = get_from_vector<uint8_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); idx += 1; // skip 1 size byte for (size_t i = 0; i < len; ++i) { @@ -7317,7 +7317,7 @@ class basic_json case 0x99: // array (two-byte uint16_t for n follow) { basic_json result = value_t::array; - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); idx += 2; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { @@ -7329,7 +7329,7 @@ class basic_json case 0x9a: // array (four-byte uint32_t for n follow) { basic_json result = value_t::array; - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { @@ -7341,7 +7341,7 @@ class basic_json case 0x9b: // array (eight-byte uint64_t for n follow) { basic_json result = value_t::array; - const auto len = get_from_vector<uint64_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx)); idx += 8; // skip 8 size bytes for (size_t i = 0; i < len; ++i) { @@ -7389,7 +7389,7 @@ class basic_json case 0xb7: { basic_json result = value_t::object; - const size_t len = v[current_idx] - 0xa0; + const auto len = static_cast<size_t>(v[current_idx] - 0xa0); for (size_t i = 0; i < len; ++i) { std::string key = from_cbor_internal(v, idx); @@ -7401,7 +7401,7 @@ class basic_json case 0xb8: // map (one-byte uint8_t for n follows) { basic_json result = value_t::object; - const auto len = get_from_vector<uint8_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); idx += 1; // skip 1 size byte for (size_t i = 0; i < len; ++i) { @@ -7414,7 +7414,7 @@ class basic_json case 0xb9: // map (two-byte uint16_t for n follow) { basic_json result = value_t::object; - const auto len = get_from_vector<uint16_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); idx += 2; // skip 2 size bytes for (size_t i = 0; i < len; ++i) { @@ -7427,7 +7427,7 @@ class basic_json case 0xba: // map (four-byte uint32_t for n follow) { basic_json result = value_t::object; - const auto len = get_from_vector<uint32_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); idx += 4; // skip 4 size bytes for (size_t i = 0; i < len; ++i) { @@ -7440,7 +7440,7 @@ class basic_json case 0xbb: // map (eight-byte uint64_t for n follow) { basic_json result = value_t::object; - const auto len = get_from_vector<uint64_t>(v, current_idx); + const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx)); idx += 8; // skip 8 size bytes for (size_t i = 0; i < len; ++i) { @@ -7534,7 +7534,7 @@ class basic_json default: // anything else (0xFF is handled inside the other types) { - throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(v[current_idx])); + throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))); } } } @@ -9666,7 +9666,7 @@ class basic_json { // we cannot simply negate value (== max == -INT64_MIN), // see https://github.com/nlohmann/json/issues/389 - result.m_value.number_integer = INT64_MIN; + result.m_value.number_integer = static_cast<number_integer_t>(INT64_MIN); } else { From 303e873ae8c4b3a5324eb37558e94644455cc9d3 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Fri, 16 Dec 2016 20:45:46 +0100 Subject: [PATCH 14/71] :bookmark: bumped version to 2.0.9 --- CMakeLists.txt | 2 +- doc/Doxyfile | 2 +- doc/index.md | 2 +- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- test/src/fuzz.cpp | 2 +- test/src/unit-algorithms.cpp | 2 +- test/src/unit-allocator.cpp | 2 +- test/src/unit-capacity.cpp | 2 +- test/src/unit-cbor.cpp | 2 +- test/src/unit-class_const_iterator.cpp | 2 +- test/src/unit-class_iterator.cpp | 2 +- test/src/unit-class_lexer.cpp | 2 +- test/src/unit-class_parser.cpp | 2 +- test/src/unit-comparison.cpp | 2 +- test/src/unit-concepts.cpp | 2 +- test/src/unit-constructor1.cpp | 2 +- test/src/unit-constructor2.cpp | 2 +- test/src/unit-convenience.cpp | 2 +- test/src/unit-conversions.cpp | 2 +- test/src/unit-deserialization.cpp | 2 +- test/src/unit-element_access1.cpp | 2 +- test/src/unit-element_access2.cpp | 2 +- test/src/unit-inspection.cpp | 2 +- test/src/unit-iterator_wrapper.cpp | 2 +- test/src/unit-iterators1.cpp | 2 +- test/src/unit-iterators2.cpp | 2 +- test/src/unit-json_patch.cpp | 2 +- test/src/unit-json_pointer.cpp | 2 +- test/src/unit-modifiers.cpp | 2 +- test/src/unit-msgpack.cpp | 2 +- test/src/unit-pointer_access.cpp | 2 +- test/src/unit-readme.cpp | 2 +- test/src/unit-reference_access.cpp | 2 +- test/src/unit-regression.cpp | 2 +- test/src/unit-serialization.cpp | 2 +- test/src/unit-testsuites.cpp | 2 +- test/src/unit-unicode.cpp | 2 +- test/src/unit.cpp | 2 +- 39 files changed, 39 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index efda6e92..80770367 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.0) # define the project -project(nlohmann_json VERSION 2.0.8 LANGUAGES CXX) +project(nlohmann_json VERSION 2.0.9 LANGUAGES CXX) enable_testing() diff --git a/doc/Doxyfile b/doc/Doxyfile index 625f9c11..17c81d8b 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "JSON for Modern C++" -PROJECT_NUMBER = 2.0.8 +PROJECT_NUMBER = 2.0.9 PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = . diff --git a/doc/index.md b/doc/index.md index 0b608eb5..8292fe65 100644 --- a/doc/index.md +++ b/doc/index.md @@ -277,4 +277,4 @@ The container functions known from STL have been extended to support the differe @author [Niels Lohmann](http://nlohmann.me) @see https://github.com/nlohmann/json to download the source code -@version 2.0.8 +@version 2.0.9 diff --git a/src/json.hpp b/src/json.hpp index d9760cfc..23058bee 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index f2e5d991..ac9a3315 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/fuzz.cpp b/test/src/fuzz.cpp index 880dc1ca..ef403ea8 100644 --- a/test/src/fuzz.cpp +++ b/test/src/fuzz.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Run "make fuzz_testing" and follow the instructions. diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp index 5197f803..31be6556 100644 --- a/test/src/unit-algorithms.cpp +++ b/test/src/unit-algorithms.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index f6cecc87..25fd3349 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-capacity.cpp b/test/src/unit-capacity.cpp index 97c19cf2..7fc3d49c 100644 --- a/test/src/unit-capacity.cpp +++ b/test/src/unit-capacity.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 604d7437..14944cff 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.7 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp index 2ef62441..2970b865 100644 --- a/test/src/unit-class_const_iterator.cpp +++ b/test/src/unit-class_const_iterator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-class_iterator.cpp b/test/src/unit-class_iterator.cpp index 3d82fce4..14c6828b 100644 --- a/test/src/unit-class_iterator.cpp +++ b/test/src/unit-class_iterator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp index 22a04b05..6dec3f82 100644 --- a/test/src/unit-class_lexer.cpp +++ b/test/src/unit-class_lexer.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index dad6b1ed..7bf23d50 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-comparison.cpp b/test/src/unit-comparison.cpp index 582146a1..73c31abc 100644 --- a/test/src/unit-comparison.cpp +++ b/test/src/unit-comparison.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-concepts.cpp b/test/src/unit-concepts.cpp index 002ccdfb..dea6b510 100644 --- a/test/src/unit-concepts.cpp +++ b/test/src/unit-concepts.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp index 6804a3a9..23c0db38 100644 --- a/test/src/unit-constructor1.cpp +++ b/test/src/unit-constructor1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-constructor2.cpp b/test/src/unit-constructor2.cpp index 1edad6ae..0bbd13cf 100644 --- a/test/src/unit-constructor2.cpp +++ b/test/src/unit-constructor2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-convenience.cpp b/test/src/unit-convenience.cpp index 8791caf2..94341be1 100644 --- a/test/src/unit-convenience.cpp +++ b/test/src/unit-convenience.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 1c49a93b..72c3bf60 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index 969a7753..605c596b 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp index d3b9ed4e..0a1715e7 100644 --- a/test/src/unit-element_access1.cpp +++ b/test/src/unit-element_access1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index ed1348f8..29be17a1 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-inspection.cpp b/test/src/unit-inspection.cpp index d373c103..1660c719 100644 --- a/test/src/unit-inspection.cpp +++ b/test/src/unit-inspection.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-iterator_wrapper.cpp b/test/src/unit-iterator_wrapper.cpp index af1fa08e..96928eb4 100644 --- a/test/src/unit-iterator_wrapper.cpp +++ b/test/src/unit-iterator_wrapper.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-iterators1.cpp b/test/src/unit-iterators1.cpp index d51c4541..60f7c2fa 100644 --- a/test/src/unit-iterators1.cpp +++ b/test/src/unit-iterators1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp index f231c8ec..da0fc937 100644 --- a/test/src/unit-iterators2.cpp +++ b/test/src/unit-iterators2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp index 9a40ce79..880bc46d 100644 --- a/test/src/unit-json_patch.cpp +++ b/test/src/unit-json_patch.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index 35558d27..91d003ab 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp index 08a6dd34..02ffa6a5 100644 --- a/test/src/unit-modifiers.cpp +++ b/test/src/unit-modifiers.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index 7498940a..46997e27 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.7 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-pointer_access.cpp b/test/src/unit-pointer_access.cpp index 5d5eb163..e1c9caab 100644 --- a/test/src/unit-pointer_access.cpp +++ b/test/src/unit-pointer_access.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp index 07f36363..92b13222 100644 --- a/test/src/unit-readme.cpp +++ b/test/src/unit-readme.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-reference_access.cpp b/test/src/unit-reference_access.cpp index a036d2f8..4a8047f8 100644 --- a/test/src/unit-reference_access.cpp +++ b/test/src/unit-reference_access.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 3125c44e..1e720ddb 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp index 0c800382..8385a4a4 100644 --- a/test/src/unit-serialization.cpp +++ b/test/src/unit-serialization.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index c41c4788..92b6e5aa 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp index 0e49757b..4cb51e21 100644 --- a/test/src/unit-unicode.cpp +++ b/test/src/unit-unicode.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit.cpp b/test/src/unit.cpp index 7b93c387..1a278868 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.8 +| | |__ | | | | | | version 2.0.9 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. From 706be50596984e956f00f54655dcddc49d9acff4 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Fri, 16 Dec 2016 20:54:43 +0100 Subject: [PATCH 15/71] :memo: updated number of tests --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 644b37f2..97fb41da 100644 --- a/README.md +++ b/README.md @@ -608,7 +608,7 @@ To compile and run the tests, you need to execute $ make check =============================================================================== -All tests passed (11201886 assertions in 43 test cases) +All tests passed (11201893 assertions in 43 test cases) ``` Alternatively, you can use [CMake](https://cmake.org) and run From 36dc7861069842fd742882864eb4ff7a099bfc12 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Fri, 16 Dec 2016 21:09:14 +0100 Subject: [PATCH 16/71] :bookmark: updated Changelog --- ChangeLog.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 287420c6..92545768 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,29 @@ # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [v2.0.9](https://github.com/nlohmann/json/releases/tag/v2.0.9) (2016-12-16) +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.8...v2.0.9) + +- \#pragma GCC diagnostic ignored "-Wdocumentation" [\#393](https://github.com/nlohmann/json/issues/393) +- How to parse this json file and write separate sub object as json files? [\#392](https://github.com/nlohmann/json/issues/392) +- Integer-overflow \(OSS-Fuzz issue 267\) [\#389](https://github.com/nlohmann/json/issues/389) +- Implement indefinite-length types from RFC 7049 [\#387](https://github.com/nlohmann/json/issues/387) +- template parameter "T" is not used in declaring the parameter types of function template [\#386](https://github.com/nlohmann/json/issues/386) +- Serializing json instances containing already serialized string values without escaping [\#385](https://github.com/nlohmann/json/issues/385) +- Add test cases from RFC 7049 [\#384](https://github.com/nlohmann/json/issues/384) +- Add a table of contents to the README file [\#383](https://github.com/nlohmann/json/issues/383) +- Update FAQ section in the guidelines for contributing [\#382](https://github.com/nlohmann/json/issues/382) +- Allow for forward declaring nlohmann::json [\#381](https://github.com/nlohmann/json/issues/381) +- Bug in overflow detection when parsing integers [\#380](https://github.com/nlohmann/json/issues/380) +- A unique name to mention the library? [\#377](https://github.com/nlohmann/json/issues/377) +- Support for comments. [\#376](https://github.com/nlohmann/json/issues/376) +- Non-unique keys in objects. [\#375](https://github.com/nlohmann/json/issues/375) +- Request: binary serialization/deserialization [\#358](https://github.com/nlohmann/json/issues/358) + +- Replace class iterator and const\_iterator by using a single template class to reduce code. [\#395](https://github.com/nlohmann/json/pull/395) ([Bosswestfalen](https://github.com/Bosswestfalen)) +- Clang: quiet a warning [\#391](https://github.com/nlohmann/json/pull/391) ([jaredgrubb](https://github.com/jaredgrubb)) +- Fix issue \#380: Signed integer overflow check [\#390](https://github.com/nlohmann/json/pull/390) ([qwename](https://github.com/qwename)) + ## [v2.0.8](https://github.com/nlohmann/json/releases/tag/v2.0.8) (2016-12-02) [Full Changelog](https://github.com/nlohmann/json/compare/v2.0.7...v2.0.8) @@ -8,7 +31,6 @@ All notable changes to this project will be documented in this file. This projec - Compiler warnings? [\#372](https://github.com/nlohmann/json/issues/372) - docs: how to release a json object in memory? [\#371](https://github.com/nlohmann/json/issues/371) - crash in dump [\#370](https://github.com/nlohmann/json/issues/370) -- Conversion operators not considered [\#369](https://github.com/nlohmann/json/issues/369) - Coverity issue \(FORWARD\_NULL\) in lexer\(std::istream& s\) [\#368](https://github.com/nlohmann/json/issues/368) - json::parse on failed stream gets stuck [\#366](https://github.com/nlohmann/json/issues/366) - Performance improvements [\#365](https://github.com/nlohmann/json/issues/365) From a507b9b46a35542aeb693ad87d947e7426e0ab98 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Fri, 16 Dec 2016 21:25:20 +0100 Subject: [PATCH 17/71] :bookmark: updated documentation --- README.md | 2 +- doc/examples/README.link | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 97fb41da..97ae6854 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [](https://ci.appveyor.com/project/nlohmann/json) [](https://coveralls.io/r/nlohmann/json) [](https://scan.coverity.com/projects/nlohmann-json) -[](http://melpon.org/wandbox/permlink/fsf5FqYe6GoX68W6) +[](http://melpon.org/wandbox/permlink/8soFCqS532vOyZcK) [](http://nlohmann.github.io/json) [](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) [](https://github.com/nlohmann/json/releases) diff --git a/doc/examples/README.link b/doc/examples/README.link index 48a66aa0..128ab1dc 100644 --- a/doc/examples/README.link +++ b/doc/examples/README.link @@ -1 +1 @@ -<a target="_blank" href="http://melpon.org/wandbox/permlink/G6Pdtdxq01HJvvJz"><b>online</b></a> \ No newline at end of file +<a target="_blank" href="http://melpon.org/wandbox/permlink/8soFCqS532vOyZcK"><b>online</b></a> \ No newline at end of file From 57afd293aa9d26f5760415b45a6ed82b8bd60a2c Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Fri, 16 Dec 2016 21:34:37 +0100 Subject: [PATCH 18/71] :bookmark: updated documentation --- doc/json.gif | Bin 1218691 -> 1325973 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/json.gif b/doc/json.gif index a5f118785512478a3ae129f355e934dd2a6ab758..7d3bf81645496c9a72e4f187e21a3ce2ba9223ef 100644 GIT binary patch delta 269401 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⁢{Q;*1=f5>62BjIrXa9 zoDi{GM2?-~n7uBeMgOu&C0ZG}PSWKZ&d*{L;?>VV4^%|RM&_pGctr5cf^xckPP(>^ zURp119lLU}crU+CfMG;@V={67aXOb+Lj?GTu|3<g16n-ip1ZYI`p2xBx|{~e-6hj{ zOJtRse5M4O&yYBYQ=nCQ)`p8!N0K=QvM=Xr>(c%8l9$U5PnKS;M6Be(VT8Z+F7Ka? z-n>mxZ&V)#quyBOh@~H!35K7&^&`Oze;`#Xvyi#lkGl|kkD`!R>la2dO!P2wQli5) z-pfSQ`JsgBzmnJAUY{(#{{Egp_>aq3xbB<@<M{<b7{%<rO($K6<+V~~+4{n4JV5mJ z-wzpvS95x7$Z^Bg|89jc*tCAm*BoHaG0G9{iIJK8$}l{Gg1!?FeMA3!vhx1lKL#b@ zQP;2}_lf2NV!)6k(Pi@RsTP*A52{tZh&|h^$c31Ll<Tm<Nhs+25lQNWwFhH|5vO;f z9H^FXd)^vL6Fd76Z^>hm7@5+>Bl*XGsJSS@_HgHeFi4pa3`|fI*sKLqS*Ti=B@XZp z@Mff-38cHrO>&P)&b|Gkg(w9EzTI&`1{G4a5vh7Z;d(nMH^p4z2IT1TvC?&JM_vVR zzH$qon#h`R`h!JL;om#Pw52Mpd6~(_1NR7}`M1);!AG26BTVv@#+#8*yUBWiG>9jJ zf#=a7R?os4c-7jFH!$fFdlHDxowUJhIH&LB&s+;ufs4z;aezl!LAXE4`CW_RiVt^( zJp!S+25r4Gp=a1i=iZFN$LV-p-qJq>AyP5u^@svfG=G=@uP%C;KO5B0;70UbCOmx_ zxyQ-jwFBZz;Pv{WAPMwxQxMze{S=NMUBRuXmi}6ly!w0h+H+(G*8?1BVdz7_XKI#C znli)$i%t1}l+h}xb+2~PVE3Y;jm3cW_C~>#GjSE6cCApaWBSKrCk-;2u2cFkT7Qxh zVG;h^rqsx`My<ay0K^v&H$vYfOqGHz*60cD3CBa>HZ)Hr&YBfdD`&Le;5D_`-_zEP z)X(p<Snq*eIa$X|sOMRKktQpdnj0Zsc=Wc2p$4chzgcNcpWf6U3+IK3-iAD=xteHa zoFdBL^LvnbGg(m1^WL-wTRVm=qM7_+EUYijZ5uRoocuh2OmWVNBcTWsUF08RqBCTj z!A~r1N;8-A?V>pMf69*2nDN*yQv)7!u!YKSq$Q^VLQ(>cUi`*insX-zE!Auwd)H}p z9dqf`kekB27oj{J4Lzs`fIidb2U;ZSVP(G*K`Z+Wx^Qd;l{qTdKq`Vg``HU`ZiA4x zQnBW~Y6|K)^AP|OXG3UlITNY=!mxt%9<Uy#fYUf~w|({W`mHRn%n$tfWc9u*GV5#f zpq?njuOBb&taT#<G#nSj9-8^?83u@zCw>7j!d$80QV%067@c@HtnT=#$|^m#jq!BI z;B9cih|~|skt_a=2mAaWc{%F)3LTeaiU57rz-?$4)0NI1Tf!5S-1<A4ve!16-w_$5 zPXUiOYMRJQA?)_K8X1qAd`vHggcxg-m!?FZ8?vV0={G8nHS=KuwXKc5dzUcqPUWjV zp@+l~hGr{1Z-%?PjB-)zK63h+lUYyHs{To<(s6GvUH1#RudGDA`URaWcD$9zB+s9n z^2$NnHll`*Rz?{4GJV%$^uwo#y$^4aOha$|ej!0LtbQtLTE-B8?voXW{$wV4Wp2n_ zz4b3M0wcu5W(vv5@DCe*<8P!UUY(@i8tYr$mYWi^W{TA4_D>uDAr&B_6Dp{EqISrD zh1@o{JdRrBi8BdV8!;Fz&VWlraHWl{zIYsP7%Qr^3L})xR7Fp~D#;?%A3x+wp4n$; zyKeGIt6Es&Cq8F)28i%D=^`9)$2P3zc51ExmSX-hXF1L`nvoK6!ym*Dm?>qK@mT6T zslIpy?HxT~&52=y-bd>|_=VXtDoV=6f$lDT?f*J*SCgE)ODd8)5xPH6^D$eGU!}s& z{&LdcBH>w;H0MGHY}y^9CHmi!)xrLsw<q=k|9icz{rzL1CH4fstVVu*?FUmRSc{m8 zru8ypp1o2QTUGwpYZ8_qa6f!+eK6zi>&Tb=?Hv08MaHK4ivQWHq<JB(vJb2dvh-Ii z-}wG(=7Y}9526)P8^|C=iPXqT(h+vQkfeTAZ?G-_r-xkh-p}Q`{Zaak2@%>>c*QP( z3=>E_G9qVw>TF1g?%3_r&-vxZd*kPt@YVC-AiC4#H&D<86H(K)Qdrqf>7JT+F>pwn zmUeAXWLRNkQ%$x05DyWY|FaQXV#yppFNyp7bsiIDW&&_8F4heZfqXCVV057|;&DBE z4se3loScuf_i9`*U%WDnEGa<dq!I}tNYgJlC6P?Sam@M!5WfZiXE!eM9m6m{QI0pZ z?<hXeDdSOJMpz2vb{k7+vjK-1FQYGxLvxiw&of?x+tQoMBUE^vPtWF5PYT^51krs` zgNW|63-q)O?i;)Ub@z!&2s<hW-Ix~u5?rD<Y0Q4q{f5C%tP$wexL0Z~?39bc$P*1) zL!;KNMVerWCmZh=|M~g|Y8a<9Ko&g(B8eh9(71U7_`W=5Kw#Dk2M)~4a2!pnR7(Hj z%3kh$jiAlll#>i<6r7ZT(OFRjOdB9H_nQ0~USY2SIcUa_QYd5fh~GCA+(5woRqpOO zhbmRrCgIZEYjR~_a1leQZ8y{^+D)!+lw#u%(M!3QTdp#F!@m8x<!%v|3sqEWUZHMX zv&HMmw`=GLm~NR(lRW1Hg?XBiY_{?Ev@eZc!MWqDOSP+K__%|4CuQKxmnNLG<#?Rr z#fh?AX1PsTKvf!}mab-(7s1GX!{~0MC%X+$K9#_jqRYQ3X8Ca+Aktp2p`B2YX=u+8 zFl;E6&0EB037Rtu%_k{Wn)C5y=$7gV@s^e&9t!lr{*dLvy=`SSZB={<Xv2JBqe|~a zD06%=)f2|i7Sk5=MMc&)N@mW2d~aC0C4&UUv`<9qJWr6-EDgy@uoAO5vCgU}Ft;qH zAbh~~Tn4chH{FkYJbsDi;rNlRLN#w$Ro}W;F7wG0_GW58br17qa)cWDj30$yTHml( zjrz=#m#C*zCW76|BW)dxgg}{MGG?iG9FHb_)4#>{c2{)>*w*4jS>~<H$N`ka&?A$) zY6CuD-Eg<ojCDAn+|AvT6V+lMY3j%kJukKAczH5yA!XnvqA0*Jxx$3V!#i`^e>?o{ z&HJqBicaLxTS>!+byDqWWbwxK;Hppu6ET>1tI`Ja&Jus<2--zsQv0LR3cV8D8;dD7 zmSDkio`Q646QeVcrHGqknH{o<pFLzsmI9RHn=}niSRiz|`lX;=zg@KCd=@>DWrY|7 zN*nC?xnIYp;|`N!kgSfV0jcw0MiSV_b*yZ|E1Gi)OVtZk-$^_6OaJC~Zx$QUVZgLn zJoA@#HKW?p^^4!+xQQX`k&c~y1DhqlqN&~9+`Gofsx(3=;aJNkx5I5{E@?9OqpCKy zpAtFk7h$KU<<{e$RZ8tWTE1pKdT$CURF57&U-<dmKIdzv+<blXY?B2cq>$h>=mYvW zjo;{f&MqVVsxsgO)3av02TszqYqtvTU(K}U=GxOCl~q2NVKBi?aJ1R+nF)HksZJJ% zG;*K^b&ql+nxAB5dRn1mU{xMDh1EG69fozfWrR$<ABOPL+-lVA7ySFx_#(j#V&E;F z5Sgba!|F*ts?Kt`8LB{bv*@j$_hm!z2EA>L%eURi4K5tdBu5Y>TGlc#(kK}3srXHK zq1$hU_TMCV&>%S%MyO1*yv!f@CdWyaSmFK>wI=r7DXgm~n{+?i8a<NVO4A_}2ObkN zCG=Wl8ARH4%&&W^n^thA{uu9tQ9(-+`vX~b2K~`0$O+j{XQ5soZ!vW;K=x6BP@}?R zh<c`Z=k_ZTvmITgKWI*l_Kl1!|5sn<OIdII9hZ67Rzc0$D%yE;Ra3$nJm}>OU|*!` zrq$IB`X5Z+mCsupmend2m&&^^K!jii3H{SULM@59RSDhA=*gWY884O^tY8Ck;}JA* zl9LFb+*fyO&3n-G6ncjpbrWQ@?P2{G=G`s0q5H|%e?~8G!|a>K#l^fvveXVxs8^S( z7~tYk?cQL7bdku~GmNJ5X|R~MJ($g)r2Nz#N_PgdZ-JX9tPGYO<FPlNkPSo$&Z}R4 zm3|8Wuy^VT?T{8dH#RUq$1>loEorUi<PVu-sT6s33XwwN4O6qK*m5^7_5&RUgqQhB zuqKm~d(D~xC1Qx5DF|o2rdy7#dJSJ98(howM9jv)EIGiVB(hXP&tBr!V>&1p09Vox zrzll@{UGuM4;>tJ#u~DI`${+~YQtUoZdKY?_$<|kd7<C6&lhkTc`N47(XwZBJ_dHb zHz?|`Ng4*xEyi;9>Iyl5q=_ph2}A3whb-&Cto!3&of+9TpsoJygz~H)AwJn6ndduO zoe90iB&q(My~^cs5oK%GzAvS}JaV}Klu&|?AhNcRggBo|sm-@uCKRyjAM!m7;s0lK z@{2sQ)(tgDWq!Xs2NJikzX{Z|ikQty(GqSQM>A~C6VIf7*X<<tq-vQyQ3+Xo%6Y`t z3=pD#q^Ui;GtK-rj>Wx>|EVd;Ie`RLzUeuMTX3Tn3h*0$xgQyt()DP$5#fhzPio$` zJQlpYIhD2junwAbk)UK3zeI^lV%#Af=`8&7Jyznlr~EIqfdXO`!}#y;hazh%m#6)s zIf;qIQGe>#o>UWBSZ*B~vQ3vo8dz3R19du<J_4Shh%0WK&C0F!uDrhYi8d^=1E6)I z0+kQ9YvZ~Xy{yJn&E=F{^0JxHZa(dQc2rxTdtb1E?9wX7Nl@UK|2%SoM{f0sU8v!W z(6^8&8Dw|-Rsdd&wL~oEhLv=oNScuTQ7@NCf{VmUnQR$V<$zQfyIRvA-y1)i02ego z4fjv2PD1O!wy4FuC*H!F6tQ5dQkKO2OfKHd#U~kEI0K>Mp;0<#sSIBqc#b%0k8{Fe z5Vx;A{Bb?DosiG_A@5fA^|0#?Wv*Salb-U=FvJ;Ll3}4;PTP=9KxkVqb2LKXo=-bG z-9{k;YP%bW2@dW6aqj>p(Qv%1`XkN{ifwwl7RFOH9#pG5R3H9R5hV1_6BhgyWxy{* z$LK4<`G%%xH$LCwy|d2z_l;5GeTBK0jCID89#6&a0K&r000v`pVt4qCW7D35`@^qC z0n55!f|3<g*vcRA72zy=-a0p{sS3Wf!p<gAM^>CiVPznNLgm1F_wPS^=|nS^t?Z86 zJNO70`Bi0O*>fRE#>$;5CvI&cLpxwUK`Q8;`Ey3~FgA5ddac3660@AZ=6(1Xkt4zd zpfCGbSC-(?%iKGrC1ZP5A=sK_tno;o;oE`9cx~9taSW>R@=G_387>V&vjkyzkKO`? ztr{hsv!vFD<SSCu@*vKI`{@07_hBpB|K?aaN)%3<9fs{46*4WpEj(gHTg)7Le3I@P z`3R1n8oWNs){o2)Wvtfiaa7MvQMA}HEzRBT1n?8)<Yh|}uX-Igz0exlNU>N982diU zn<zI2hHbRv44)T&dez`WE{sHYx~l7bx~Vs}TU?2Vk^7=jQjyhVbgAV=M-Rq%=@?@+ z^lGC8oUx<IXF9NfJ)4NEzO6~RMq~TP#nmLZHv95M5}5v{CpRL8Ic#Q}-^@34@)PAl zW7s$$^Pi`Nv<h4Bx5C$(LT0XANkPA!Gd#pkxrcfan?8T7G_qIuvWI~Vo`{EP-@RuN zy8gMS`p=F@iX5tdf$|;^ZcupdxpXFbZ)9`!!&ihbtx^&<CyA9tg%$&tBZwd0+%5O- zeV!I)_UY!uv<SFW@s7}I7ikZEpRpVM87H$M1XYKJ_D{n7)O4+aUcS<g>Rma!*WM#V zX~f?O6rchHdP#glU2b$YVjTNmef9fMLnmz-bv4gq<Z1o&a9QO>Oa+tY)$K0+KVfr6 zOc4O)Pyp;RfUWH5bMrsr9NPTw><{gFvIgJjE<N-lI(c?Y_w#EY^Pjqjof|kvn{<m9 zAz$@#U6Gh-t((u7LaJ&tIGBoX(&e%T^5RH*et-IJYyF?8)@7Kt_DDVFAl~<&1ONl? z^PXiK3528q)Tlw$BoKlMu+XhLeJhj!a@YxSg5(HkMNN3M0IvpZ1@Xz91<N+*otn)c zBATAM8<-o)Z#qX)FqJ`2is?|z4k0o!Ao3}t_v8ON&_`=AyqDfi{r7!Q`VkNS05mUm zd+Hu4(&H(5hqA<FHSD46`ye^u2?KWZ>5vSV0J1hbWWzcMU=P2)-HdG?scF^B4mp2$ zwAl}2)DUDx!A}N_{bJ_r6++G5RpS12veKJ6_&eyX+yhJ_e`Nr@GNfi4;hg*fwkqrK zj>vV7g1{Rja!5P2MX;~;IYKVoJsnWS{~rj^M=cWNW0ouH+!1<?^0g>be324GYsrlT zgJI~1ahO*Ro-<l}arWqok%w%u_+KZ~)0#}UuVecIF4+-TQ6M^)D1O^1nazmFghowu zYQOE%#Ggpr8vx#s#1MGTlLFn}K0N>V<2O$*t~(aWqaMW@g75PeR1ZfWoF=s-<?K6< zt9RodJR0}k5uM3fkaA^@JnDJq)+mqM4ULlW<L!wGL-PzAsrA;UXFfq40Y&%yrrBj^ z{n5I^b@2$1OZS(9cgFj8Upc;{k2!RiWXY~tll<Ffx#T9FT_Z57GhRD?dl6{i36<;q zkqLWuO-w0^(~$AF{(@8DqpLuKNj;_(V2ynXRt6=&G#Vz;u#CzmoS3%Q8zqdbkr}b# zkm_Qp@Q#%iDuuArV(;U0aLw%Fc8g-~hY#xe8u4e6zH-_2NXfSesh%J%F8C$`Kr3<= zQrp&@?Bp+r5#(jZE)EmFe$|*!TW>U54Ahr@xh_XyRQcE&CDp}wo~`&gb5HeFeN!`@ zTFv{P3a%2eX`lG^vAw?!aSsG3>jEBD)La7`KlXdC3Ou|f4&ai<awZ`R4##?oz_bqq zh`4$~jq19#W=Hi(KavLBf!`GH?kfmqZS5A#HSOd>D9N363CKMxz!Ps7vazY%Xla2O zJ)TsbG`TRUF&8J$p#n{^I3SOsJ1vL2)7?f@<>UJrTE(I(kI4ciNAVUHMC)w&q(8gm z*E3H$ToSwJV8#h(fccy{77$mHNKumhQ*U#K(rQHMJQ*W4=1v*F(r?6<ph^Z_Cmfzh zhE;<gZVZjcCz%70xKY!;KJ~m!HCc(;GOooHW0`Z4NC2y3MX(JLSaAEf`Hir`?I-_N zR6AwyLYfk89_)t9@Hoa}2DGeH$E=89Jz{Q=EQ)HwUzMF~k$>E7IXf=XiDmdCan@)) zUwqn-cAdW~x1OHdc0*P4r$#%>3UDgMFG|n^23x;ihM;NV?Z@_m>n4(u4CC1cAK37K zuW^GDuSF+6covGH3cnX9ln4|uGI_wn^ZtduAZ2oH@8@>^4s-ZiAU*UjC`WJPylE_K zrR2Zm=zoG|Zv~Fyb1oL8TAGe^`pCPq-(EOYt*g%yYJ1@vJMTYpXP>1NLAA6T8uKHZ zG{l9hbZ}is-r7oog(klPg|6^f1ii2YI=MBf-~Kef($v&!!uDL0a|8LMrO>_!qr^ar zSHDzBgQmbv9}iTS+|T+9q@om(*Z^j|T{f>^zC~Af{y5#e^0vYMCY${#%z0Li=bg1< z-y!33t6&n8K6|KPGB0#9Frs1V&TSCkV<r~)I_JU`JM*OvAnpt~YoPCC*+{cr{5Si5 z%A&){xwiFJOg1DGdG{28&N$!?m3&bL5NmN(Syuy8Zfya&8N*}m%)oYPnA=cCmKeOj zbfc}Cb4xrN^TrOcepi(}b096zegnfdXJS0o>sMi-=a=K#`vvmxV&5&Hpa=?~@s6~z znUIO2Z%n6_tj%pxw<4lMVZOYi%L~<~IFol~{f0jxk21C4qHe7BQQE=c>C)1l`9<*W z&)UIhoV&sRfk%k3%@zewsD#mRKbHG^LXi}et6q=qc~gcgTIJl<7<3*h+a2PmpnkZM zq(3-TOt)0EN#d5gI%Ou)?wdqt2w4lpIv05!C{ZR~k6g*VR5kXM8t^UK;g?K{&b|4e z7(4<_wa$9U&}opGc}2oJ>oR-6>Tn^eoTQLl%difnMX~t|U4!#|RS=P_p!sme;+Biu z<7Ip8E^@rM6}IR)?B)}vwG`%@XX=e^*zBg=ybuMB3li$=rbhz!+x_8$4`LF75A2et z7~W%K=Uhv<JD5pe{ONc$XDsLSPLQ$}2%&8agcG!&N{32}8W#6-m%162Y$svuNj(kF zUJ%#p9?GM$yJ_l9{Dm6yMAG<|rn{*o2C9=VISbE5Nz;0_ay_FQPX9DHzG|cTNt?to z5ZwV4x#h*afF7kgv=U+&?-(UbxKJ6l8l84%W>QX*nTHb?s$V16W^HB(-^=6O$Kb9? z9!-Yahp}rVdOTOUk^BZ<<;k}nAg-4*?Asy!+*-lo)gWgtzC5`0t%-7%KI5fB2TUK5 z(KY=-rb8~JiG{3a*yS}tUE`zzxetkhm$htix}6r+M!|tQ1QN#x73S0oihZQf&`>9l z^jW4xH{QS3(TWCE(E!@KYEwHpvIaMzX9m{7hYxT-YuECeN|-hAudV@Gyo@=6_1$>> zdzUayWqfsu1?)C{k7SvM-+>Q6?3WO)(qtn6IY8um-xprFzGe?+q5wPd=YmE$lN52p zV*5P>;5AGTUhtFEQqKZaj<Z~>=DX(qMgrF$Gx%G+pD8f~@wWurKG`b;6vw~Eyzgz} zODga;bYYKY94g|FHe#rW+M%@d1gSXgaN<+y6mA%dpi?OYaBFt(=Ln<2-P4Z($tld7 zR6zY>y;LuYn>OZgu)9Kujnc<N2RN~lqgJ`<_$OgEk=pH9q%)Wgx8CQ6qxg!OSeq5s z05boAF!*pMfWIpsWpf_TonX=gM+f>U_OTF)lnsazz5oH-`}EO;o;33T!rxhpQqvg7 z3}lz6HFs^c2_jJDs+2U4L;GTi#R1210ZxTWpQ<5B{$Fh=l=BKOefq5b^77G*U3)eH zrpEH-n;D>>eK*Vf0S2K%0JE$sbnD56nB5I8>rZmuLCfYos4GZj4XOyM^Ei;18&P?| zod(Ap*ERY>0r6u2h109bh63?Ml;&+OeIqKtO&dir-XH_e)C|GktkB^{fQYx(02!;b z`xbv2qVgUX3OIyoU4Pb`m?af&Ye>l3M@mh7Nj%+j9OVLj&4b+>5>*1dS2`OikqzFd z%Dn$KYl0hTR~4OXn3vf9#Z2sLOx8}xxt)<F2o2Cwr>gyp5e&I*P>o7l`mlE6++1=& z^ZCoti^B4y$#KiqICkHbx~HcM{kJ^JZu%xF=T4T|^+$l7ZTcr#5IC|a#|=ZcN&fwG z{l6WBg>+7s>r2JpQtu}HN?uK?Z~!JCDDiA*GVmqqqd(DM^eAnNj}Z1*W160^^Rq$; z%wEHX(+rYtO`7bqSh(ESI{!FO7zyGK%c5Y_cvBcc0SFp#^O%Y<DCct2<&*=mdgJ_C z3{8{bxA6LRtb#Y5BxPv<SP7cV3_oz2<p0Nkw4I#o1aIkOd{tl1kTr-1XhN5CSX9J7 z0S#k3fcW_g66a5SYm1)Hq!Ak!KniIj#!7pikpZXySR7M5X;v5kU+AMlzmAk&au^#< z0Bcdj$lfrP7k$Kud$maQG?Tw8R(B1A)o1E$RHyqX*h&KTtp8t+4#L>)`BoD-H->|z zEja~f!&?j}L84ZY?iExS%MYAGAPe7dHBOy81;(AjnlX8a95$GzN<mNQUMDj6*mvJf z&}(EE08S)v3LP9u_{kiW@#4yVkZXAbw)EXsCwd1$yMhyj8k!~6$V9ol!%tX&XS{y> zK)^mUAPDo7z}!g#pac_u5=WRr0IJ;!h<*|NClF9WjBxq>L&_U~e*_S~wtNk;p#(Qz zhs74lE*P&}5Tp+M354A5`+gRTQKzshWypr_0|n4QYwRd-%5Q;DBKEo7ju?QK)*%(B z6T!}=5D%2a1i3Two;Id%H_sTYjnfT8`k8DxcL?5v!A1ZZ9~g2ChDQwGd;zS6oL|X+ zy>(jyT>ujemgc*xV@Z!$<EkP0q61?owIk$!!azCDvn-kVNtqc?iK8d0L>YrO01>6Y zc8cXR@#J#R?aTAxIt8%W6E(=*wG|ucDe*2^iKXfv6uPS}juAOod(e&|e++clT+#@L zEG%QrHYgn1Hzei}lYwb_3al7^XJLrR7~d0W9N@<BNrLF1nXzIZod-w^XBlA63#Y^6 z_Q!W9+}EM`lbE|M;OEW4UL*$R3uG!QbP?&VHvP_jPmCX@_NmV^=KoDFk^a4UAOv?) zjy<1h6()l}H>lzL<4ZpTS>6@vA=oJx%1EzWmQNp-xQ$t<;o^BFcPz#2#q2GG0yy1M zX8`;&3c<|kYiD)?iFZ77d~aGv0%Uty$5o;Ke8d{$mU^XZYJ&cg!p9cC#R#|8I`OG_ z=^Vc|F4iN&S#kSTaO=ZEvEuzUYw`3yV|&3<r?hOTmf_)dtp@dWzW_K{g3Re({sW^n zQB_gQxDqF(cjBo@+rA3hi5xR8gl3Dg#lRQ|dD82%HF|62K-(Q#seqTLzCE-auVky7 zZ*Qo?qfZu}emB{gzsxazttKvjQ8583$&0WV=yDF(if~t49<SvxSY_1!JnHE4Z~FL1 z&x^sA$Z!{V@sw_VF`-74&_m>0?7z&7k;YoHfjHQPh!ATc%J-Ic(YM_p{9(r7bX}UN zN6+^|HtVD|@o}H?u92Xkj5Mnkn9tw5q(Hu4DiS`rf1GjY>Q-l7&{u!4AavSNPOU@X zi_4KGT2(oP68Q7ud&?%77=;~EI}DdN#zp`u2W+(fp8OHROz;y}*YHOZHR<0an)IdO zj51frd&!u(P$G!-9)EKwgJkvX=?zOWBWX<dlQt~ec3j3xm*k)#dJ@y$4j2p59TyM6 z+hf#g-dQ{w{%L)K8Db)W885TcvE;<Gs2Q@AU5`EW_3yRu&i+Q95*w1ms86YWJTdw^ zdJu>xreoH0P=slWf;d2e+1K&M-Qd%ScTL}XjlOytV@!t3?>XMQ|5JukE|mr1b|ERw zsA(pJCm4vZY5{8UKHiRbYD}SRui=<XQq0w)FH-aq^RS#?2MctpwI_*lK2+|KUh<!K z<#?70pQ_}fFl;)87^z;L>v)(r=yk=24F01dp$&tVBS<LJ7;)AByrvu`I(#L1u)kC# z2w_bRTAl8Hxvo47u(ZQeayYyqJ1Jk2;h_T5^Y5*5@MV25;bPR4*YjHRfe8_T84Wk| zhXN<q0%bAos`#t3-+c3@FlhV#lb|R-Jn(IxnD2(|*z;=|?FD-maoaz{>Jl*mTj`oX z^hgdQLF<~N{=G-Oc0S=om~$~qkkMyfySCo~9X}4AAAIBbTQDxB^F_>MPb^FgGau(M z@nt305kr^5aF2>P_C1iq^!tn1bjkfczZjR397ib<M0x}xxk(&Oq>HQ;(Rr7943uRj zZt6B89_*-+pI%(61#i%t8L|<Y#BSUzvz$66f&q{_MprZGr?Nn&RGz4dM|`<^F6XUk zBdP3QWiIinKbM*-bhLS{$o6=;&t9(mZ?bbOJwxg0ebt4#VfupkY0EPh{%0X4VVImt zcVUv_1ML`?_?633j+xy{E<6~8bO$aUA=B$N1&M(=pANKm_<pL23I!OU7+v{TLL}*H zc!DJ+f=eE-r#cCUw+~Ye)ZaGQ<N_GIOe&d$E`5D5{WD}yOaf;VC9kI+k|N9;D7L8K zn&{*i^7)2fhiBMJFVb$3Woq^hJ1^Cqzea`8BKTN27C}kOIE4qZ=NJcI^zl^8CMl&S ziS(ZhdE!WT_^e$+24z3nlgFtrzpzk{ARRv}-rQo#mVt{a|9DZ02p?(_omXS~RtB*e z`B3x`WI$yYG%R<Vy*w1(N8NMq_~bd=Yn#iJbFC-z@VWI^r}&~HM&}vk4^!s8QKr|U zaDDFi94Aa$?60D<K>VXT#fock-^gNnwsLD^F_UP|{3!XJm_;Wb6ZPq>1P{6{;gZ@j zGOVer(sI5so|ljQNfSc+A4TUKPxb%B@z3R6?&Z?G*T_oOwP#t`b?s~KtcF>3lCr9M zFBcb=uD#2+W;SK(l1*l07DAK?Q8aviet$gwe*f`)ydURr&Uw9FZ+6+WAEuuUsfZwz zY&$30J3w1Hml@?=$o;Da_ZEdQpMN??yIo;v2?e3gz&XPX2SbH=zWOXYJ0F%}kC|wj zquP|4t;JrlC^92^yWaaXjj>iVjO5UFE8xhEztDqa2)lImt^3CfDl52@YKfQfh0*>p zwaB^It$nh7@H~LOjl(dq1+}5US$Y%LcuCz2%AK!2&)<L-kDPq+a>9snzkn&!>uE+M z(<YsftH(FaFn<Yv_>INLp}|sxX!7dcB4PWCZ&u?!3#{S;qbmHlR4^HmfXo|_H7D+n z>KSk;*Djqc1GezE;hDwp30@@0V1Hk1?xY#B#E|kNq}tG|HMa)C6RsW8-Xgg^i}@XP zPi-NHr}D71DtbXgu)18h=j*-=Ex9mJ>HBh)dtXtH{*~;XI^6Ne#MWhc!PzhoKIc-C znaA>O*$NQz;TqdpqhCXF4P3O(ECH;4V{8rFDjFA>FAm<A%&qvrZ;WTn79}&YFBO>i zw7q^Z^8IIc`Ri0n7C&pAbB0!Sl}*#g+jh(i`zr4dS5B8;dtS^#jiCG_I@|V#EC;-W z-LYlK5oXPL>h!Vl#D8(bm=5IZtl<qv%9(eDgmXvQmqr|MWlOeT1vKN@zOiZnydTwc z&Rxh!+w?n~rF_;;4u4X>&T!~&`<v&nSPU$)wn;c^t@Xk3X!k&5$GGVL!e!+3-nW*u zmUMo~Ijxq`g1^uRjA;sn)?UEH%PZi6`F!DlIr7X_iTc&E9UA8jPxA~A=ovdLP!ps3 zf?jIondgg{ee%4`!jY6tn>5L?SxF0u3KSH1ZpQ8$NG>|#Cf=1L82;T_3AsE_Wc_F+ zR?A-&^I*kXM8HGZWh$5@fs=<YJQqe&UZVb|hM7BbWxZZa9CiI1+PQ?Ld~azrpMT8m zGFSY_?&>eiw0!AE*(yo5e$llLc+FzpA(?{wxsaa0$<P6j1b4{evU9DvE<VTM3^Qy` z$DtusYlK>F4gAE(J6xc2<YQS!9kwG^>oVL|W~EoxHte5nJSrtRcca$Oe%z+aP4j0T z7Ygln$air2{XnyuV?Sv!T5=edL>s)^XdBPv;|=&@l%V~V89iAhu<Wb03nwgV^e#s> zymNn|IJBI7RTcmfZV^VO#C6(azrDKfEkyXnj#N>Anic--otRr)&dC*uiNE@T$@jDQ zay#Fs3opsh+7*}V>#f3<yZT!8j&$ET@EwBD{USa`VC=)Q`B!@X3?|r4z`;_e63j5% zPT>3!%yFq=@e6YVu>lz&i@9}PZDSlh#P{r$=@RwHm*raF0Nw$M-ltQ!S+0yHOCef@ zXQ~6HvtHxn8BWezO$1H!4Me?)ll}1USTWJ2`VCq?^Um*;Hk(<s?<wP>{$FN?EXUiJ zTQ>%t{T=!5qnN`PgrA8en*9JPSx}6LC-TH&WcRSFSh^zF#dr1m=&y$_n;Fqmn1I9S z822V4WKDh$?W$u1gY(hW>elFzO!W?WoBf1dAQXS;Dg{ahxLp__0M2rc&~49soq-@3 z<nkO~I!l%kLnL)mVa~jIE>;pi5jz(Tr(Hc7c*>r@D`NR}g%}Sny`e2pS3rzs%TRyl zc@Z1g=rt`CcyDqgEinLoxm=B!)(r}N#Nc3=OwhLGN@tkBHP`hN#xTb#l+z1sz&<nh zOQGZwMS#)TvX)#u=R?#3*f@qs0=%*xdY}Lp(c(bBRse+G|2|tP0-!Tqm>=*0%y&&; zwjkv^E?}AzNxb@SWw!9c`?zGTAJ7#*AZ?0QOsv8geSfNigT#$v5#P#Z_}KqoYXm(K z&kk>hzJL!i7-NEv3|YnH>zJi@HEn?h_gim&aDlyG2JHA(N%lH@ymcQOEk#L&KAvyH z7fiTap$^W#sAuwxL{TNI(YBp9!Vze~Sej4vWlF^&F?be7_{FX!w>a*zp#}PaMOAC8 z7yEW?U3IQsJ~oyv+5$1N^Imf~iIS)dl)RoA_*)_wXO7IG+PsF*m?@Y}os_#V^05WD zB2`gBK0hp;o;kR3a6{+qh8op$IW8Cj@cs0##B1}CKUfj{nJTm?T~K-yJFosC_9YkH zOB+JKi+;x1=-<v|<e&d})s>E0FT#mj4c?B0?PY8yvJ&~0-GDSzL`-_TEhTIi=COE} z8^kgDh;c8bI&tqD3C{I~eSPv;o!L*z$Lah1TX(wSavko5t2W8HI?QBF+$)LiUG!!w zY0uYw#V*2AAIx=cyZ*CX0wwZ^80WWohUk$BeD9LjTj_XB?tA)#F%}QoUItivZN+m( zFn^`!Z5d(7w{O-FP4fRv(y8I66**eF1#_E<b={~+F)*;={4|LZuRfSERrz`_ZD}Zb z_}125>tm`_JSIlav8SOVGurjvu#{(MeUwD?(NxKd)oZ4F{rf$#dAea<hW0J?Tro%h zZ(q=V&sCg>AffOyK;oXsy-%JYIxp4yIISzV19q#fCp#hi;7Ok8x^MNLTUY(GPNEn~ z@@MRXvcse>D|p5chnttgHxwGkvVX$si#|!cBSM{<e)#h+2G%FCeP^QA40`mXT+dRs zUD{<xUeDFe=#}<1>wBc}O^+W|s`ct*6`yvDmDw~s8&X(%JL|?Kt6t4-Ms2^zUT)q9 zbRX&2?~l@(k47|y22U<#>&m@ALh9kXuN0jULpc;YEGusT*tw@a8<IN@Wre;oQVf;S za)!3_Bm7tkp@z5~)T!%6!nBaZp4=p-z0Fle=#%c6z2FUEG_LcCX1`5N;cJ+{;ZYT? zOF2D4tg<y?E5!-Gc2R+yKS@8##PTcrtSmEkz1V@taw(=vMouRnh_IHoQ52L}8MveT zqLQqg2UVI>6IK6j5qFmw(ySDqcLCrZycZq|?_POgF!bBaHERZ|tv!B|slxs@mZvtd z^LwO<+obc~A{>}u{1W8(l8uxOK7SijkisZ5bf{;Y_j$SMK3OAAaKIr8wwbJKSOxoy zYG_WK@o<jiJV|@KZuo4oB*o1ncx?Q!2R{T86&49!+1d3#Zl1g7_%+o^-ZluE?XmAz z?>xCF6KN7_N|jZeWV_dek~@F0o3~|Jrv7ed>_OX){Hym?**>+t<cZ#n!FLUo<*qo= z)cifjNk&Up^V>Y{uT5iKC{b=2Hz&h>$_R0QR~XeKE%ho<l!=IIie*p(gmu}?2Rmu; zg9GBpk#a(d3_?a&$JE5ue$05GyIB@jKQcWS{hDQ_Ac%922ib6`oW>esEXrY^?s122 ziuJP}4F&O|U`HeL9eAYhh`sA$nom6>74&%XchpFZ;*iuUzxs^Z%9&FbkFP7KD2x!x zZ&zTDqbG+~hXse&)|0tgZRHL(5ZSx(hNC0y0xw!@h)2jmPgCfRA_w8@Iq#xJqFD}h z(-+DP0^Hf_MoiB9NF$TdpB1oGdl{N6Oy&G+vS78*@~17#7CkV;yNhA~rdaqbF<L-@ z{OC*eaCB3Audr=3v{6u<8fes1l-gFLU#u@H$AIAFOTTUgbE9@wk78tkFbOwWwSb4* zyo*zn{<Fr;pS@-zgyNG-;g+vmV2Y9I|2|T}ecFRWN%|idr$>k5DT!tw!mrxr`Xm43 z@RY;=5yKbEmsap89&79E91oqFQM|QM!^z=2I&umJ40I9h%_{Zl&-HOZW)S~NQd6Bz z!%hgoed!Lpm!9+ENJKRa;!a`<W1)XAC#fy@a8~Hm#~Lo83YP7cihSfT>W$QzP%O3A z^$hE_6tb@If)trkJo1Zg^XP_L#PNs=yCO>=!zDhu!92WM##O|Bj@Mg<O#15uN)8S# zwOdt^61nCb7!&sLJajVRgHLF>DWaMea^$n$r}|f1ylv3GIX<a-QX}+(!U0Mf2AEqm zLnE@^_f8zN@^@8We{LB$FOa*Qc3s!G*t<s3bOBy3Uj6=9W%&`)9j+GXV1KZSPjY!u zB!3WK9_WYfTM6(@ZN21KljxIdEjXAJQ?eT|c?}J$@bGL-?vvB`{g0OK1L7QMKMzjU zzV75rl7(e6!o04{9f{7$Ls$IuYgDw=*=J`OqY_J$e|;lDjY|jVx`2oJaHOqGL&eVZ zhL-kb9*a=G@$OL^cw<q?`R^LfcuT*^*j*o!)Q|Y+IDhP^EyW0_^cWl}`j~M;!3s=o z{)}wU#bt`SmN8A?&A;h?FaLbPP7vYUC^sX$H=KO*7V}T=cWbitIa0DT=2*YK^v8x9 zoax0Y6llW@%(&}p46f;$yULiHY_mPA5*AT-sgmu7P3)E@5N6HwF=>kx1T9VJQ>BBt zX!yDY1rs29{X?Xt;AhC*8=<{P=^2ZcWg;3D3r9>qQ+*kq=cg8#Y+H-B$$KYxTU(3f zENHB@$NRx}Q%hhOsR@#zJ*9#^esT^bhgJCsl8)DJFn@lrM_?<eDP!NAs?K-<^Y!T_ z`KdD(Y<7(7%U*tNpi)hLV;|kM{;#Kb5Z@;DB+THri$l#+GIQ#^bjp=5YVLo3w=7=$ zem8z{zb(<+Kcjl+i3Cr6)u3dXcvsx|zO)wgTP?ZS;NmJPPd#8vyl0ScZ$3y8gJG#C zJUf889wT-gz0R2+=80)EVBfn8Uct}{c%cYxs{u{46};9`XsZMW-xaYTaO~*c$1|)j zU0Y*fv;@LeBQQjvG6hH|nk8V@2POZ&^OIti2a@#QL0-D4;>^A0>(@^d9N?h{)$DcF z&AZy+E6DIdfyf{r9t;=J_EXRX#I4}rE1aV*AEFAiJ{P){okjIwqdK_p9AaJpndeP~ z?jRV#!dlRQyCU{3f}NYEYF8dSjDWD_!U$@IoA>*_m*=u5XQpMigBqm6cL@)p&EE8g zE)#{o^ix?a<QCDMbZDsb0?61EaaP5J2t~<$yv~02&dF7Gr5QjD!(uGNGW^MiArNv= zn?)g6^6eyWUWaA8+nPny<KcnE1(m3AAvY!cpr!+4Ua9+6`^4GM#5sIc;zCQ}Wc{rG z1Lv2J+pX#D^1{G)azJph<$WZYHAr&y7SAIUuH#i!<Gt$xb0=ys^)aVS3TvHwmnabv z?PV}<vor|H0Al4+4T>q_t45p`H@N;R*(lsauyPN%Um69%%7(87y4nal+e_YK(s*Y` zI&O~PvPb%s#sBORG{^5H$1>Y`BGK%0%xhtu%E=VQIxqPj$pS`acN~y1Iv!7hr8Ys# zpM@klT*D;ylD#(V4nL+WG1`D7QMMAu@%nH<kWWeGZH;4Iz|i;4AcEiB$2U}OV-NWw z3)?D=Vqi`$zs>Vf2+dicRW}#kc{KyngK90ekvlf-3QS@Q#3#AO3U$nQaMi0ks<?G( z{zt~#?wG_Z@nol{Wv4l2XT&*SLd1j0v+wjfn%KedC;RtFhIid3Q&3iq`6pR4=Ht9> zQwJnCiVxg4vmYD_+W?OK497Q34XKo$lGIIB^-w7xAqoBNB;g^xM#(%32!4GYp@I_* zoJhC1i!08+o86PRIi>=<RkhS>CP{B2Mvs$06RCrQEGBtg7B`atF=TWLvJa8>NljRU zc)Qr$9`rG}QX3gQsnJnrNAb?9S3``wL_P`2!3dF~f|Ep7F)At-HO^jC*yHWJCEGZ3 zw$AGD(L8qj!CBM2yx-y|j^ku7;E7pf8XC%}^?HWyZX%v{1TNNR>hh9G7~n`LB**U@ zs6F!g58j1YlKZEdlj}hr!m{<8Xa?alTn_EzuO7>pIshJc+HnYnuK+9)fP;&xGLhNl zBIHrI$f*tC3{WCNV|M<`B*+ZEf`b@{ve?!E>;%YLCT6w*z-Hx{@)S$JMaUTfWJ_KI zZxt_6OMt*909!)IAfo(EeC)a+1YQT+cjBpCVLBDZ*aEC(7#90oAOKMix5^r@0@w$} z$oJ69)ggJqPJz3CEw)G#Ri5fpuDn-LP+5LP8xo<eN(Y#u!XYH)Cw`wxkHuvpD}gf; zC6}jI&RCWNwz&s=F2}2vn1@4}&iDv}TL9Kw0G}h=cd^>I@kxge2qckO-zm)4^jxQz zc=n7HL*}0d7I>5bJywAZI)&jB##6wjKu%#gh4~cdDX>#mPGLO-ehOQ&0-e3sF;kp~ z;9+!jcFxqUVLNLi(W5QfXQtkZQyQ?koGx`MQ_eeE(Jx;ksMs)K_`2z!o$eb?+c9s) ziGUlUE*2AaT;4|bPX*ta!QZ`1xulb%u1~#en2a?^)6FcbVH3g!J@<c5eK)N3UPRr4 z#|>eTO^;@Y!E>?Ub8!#fMTg2O9;#^^8sL7~JN^s|I=bod>oWH6xqWPz1+mF1wJkWe z-Yu!?QDIb66oo=bO-;?s&5e0UjBkxjYL83lN=$!6rO{|rRaK3RjU62wuL#BOvl5q5 z$;;{SYbCjBrTMS%G3BE<FQ;go8`UM7jn6mg%C_5^KEG;Nd6u3*Psw?m@w6|ea3H^U z@LB0_QN?I!^;l*7M9qt-`qr739q(GZ<~q6;y1u;bd_q00tN-)1vS+%CzSR0=zH#t< z*Tn1BuSZ5k`j&cz-VY3a7@VG-UR+%KK%e?H-1lvye{XthW7KtFt#4*;c5;7V_Tc@( zm&w^Tt0NO1$7VLC=eOQ1eO_GI`Ea=Uer){j*QL$%_4SY6)=twee{QTDf89CQ{Jgol zv9<SU=f{_yU-u6V4*nb*93CGY{r>gefBzjF{@M9_{EGf3(+b4!7YscCtTKtcjM?~F zWm-%9#{sIa$y3wThK-RdXLSTnfGrp;&`l6DYirt`F1L9u)(Q}O0kCTIQ?vG$Ul&{M zeR=<e-z(}}?b!oC^A1&8>xM+>n`0fVKhhluuh^-7TMxg?UEzzIS^++7gSk)iCYw@i z(J~f!<@m_xdJFRyz#HU2w*A=~y@UVoVH_`22Ab;R*2janacJ}z1Y#u;kN}`&G++(P z04PAQ0MzAfs*sh8r7Hm>0z^k>-$miLt*U<MaYyqUq0kWEBK<UED+m%M_w$w@x1}bX zz<^cQ1vs6y46_-yG1QMKrtD=9#t)8zXhwquTQUbT7`+k6plO+Jf{#%xSjnLC7C<a= zT=oD4D}_)xhsY&K6xylH0GodKx+?%;_UN|ut+A5)<cE^FD3;Bnx>w?Ek5i);Pz`+e z(9G1<4dCumPI6X;u@U{YtSb>)#ws{bWagxb5U!||1S)AK{N7VyfH^pw5Db+uPGOwl zA_!L%B&R^qs_@1G^xF8l3cdvTr7t_~(G(|{sH~?nea7?V?JFG8-mZj~Q;?P0ra9O` zZ2n5yOG3@KPVn>KCnw<YV5T}&6gMm1gq-Jwaqc%?hHI-lDbASo@7>T3`onkrV{-7v z^~lxvy{?@JN1;!wO{JeofQl;n>2I=jb*(Pqge@!`9PoFH{xefkcx+z9vhNF*h`Eq0 z@T%&^n5S#<*HK2EJfx(94B^`-C`kh)4i}dFNDxQL)=y7)5B|_@P?*D75dFfiMnB}d z4rd-iQqVK~nA!ad2I|+Ji_UjZmu4XAnn+3eyo5_9Q6P`c$>S02x9HE&{+V}IY9#;t zY%kf@8^#xM2T5B8TXO>;Hw1N)Q~`E@enJWCn%wU#bI`uxg0eFwl#_Btu%HWlSEufa z<sH3vZVQRPwl6@Q>CZQB_YYc2${shpOnZ^~{;JUCw{O3*NuVi7&SCpIk1RW^HL(ov z!H$A8cy?$s2h4O-BXA<b<M%PqjT6VY+<0d-KLDS)_Sg5p2v{@QI8v$O-8;pRusk~O zeejO<0YBvzZM_*#-zCbf_O6zC5~O>*1L#P?1RO;MFMTJ_x6d2q5t<ly=nv`0F}<RT z+6X3z`}V#$(ZMOo*8T|Lw8pefv{$;0$58Z%b2#1Q>4fCm-Yyv@V}w?+mjTnBpr;z~ zmRp=U@x`D?9a1|Pto#5F=Zr&(rdof(==4YjY{y;r!nYVar6cJ`5&kKhPEW~7Ka-QJ zPLwBc$);(l|K5ATJ^!HzwW1NVgH&Y`APW&B08S=D;TV^-CLXGOB&SYFZQ;}Q(H2qU z=N)Hfh0{^IgA7CHIz9u1L09OonBxPCQt{c#r<eB1Zec&e#WWM>kD*>QhQ&bdicG<G z0q$)>4s%tS@7jH&EHu^MVr~^1G+3aA5uxmG5I`sbV9HQNg_`hYa}rW@PNyC((#YKL z5YubwC5dDXENJYQ&*sE4KmY%sGQWl_tbKg1!yRd9yIBaoB7cBw5Z}YjM%3|D?=4tx zBPg*l7^~=e5WO_$j9pND3d8MqVVjH+7su3i?vX;I+Kn>outlk*Vj$Rs07(Qx9p#{j z;d{3TmJ3r))ptQFe83TEe+trx6iN@`0|{6fkvQ$J+>*jAa9}K2lS}o{H8NiXcaikl z6b|)#i7Lw>dM+M!-$}KaY$jWx^GvSfzIntn8zg8J*iOB0B2ec1D_*Z5#Rs%4LWav$ zBFsZ=ox!2lJ;9*42Rb4V3oL+<kdDPIb-g?^E1jVZ;XqW1e<GZK$(GSbt@cUC<R*HR z*$&y$czTki)lUG<O(!Z1Q+FY!pe&esap8Rmd(?CS9_qLF67l*(y58(Q`Q~-^);O7F zvZfi?pO@qm<8tYG&KsTEtU=}(-$rP!I)+>|l;6f>**K^CsJ3F+Gc_5?c*)!vKv>~F zyP`1I{`t*?`B@)H5Y0}gG(E+^2=vwsLa5-W_!69#E2nJ-ZXiXIx%;I>K{5p$XNb>( zUoMKw;GN1VFGvQqVc|$?LZ+?A>>Z1TSv9=|ztBe>mRG-^R%A;Y`cxlqORh+YGETfh zBQmBExhk45KD}K4l}u*S{78ldX?Hx@3U0OqzPfn~f%qEo^n5Bdr)d4tC~4iu(Mkb+ z2+P+;W+xy)>QXGHj&VreNLmT$rs86&BQ67P?JS(Ksdl;7J!7AyZ~m80{)}E14TDV+ zXSlUZv&ZDodlUz<T-MJ~Mw1(1(SH(>c`QsOLYR!XOASgd>Cz@^Dt=shDpR5#`+LT$ zXWvIMXy&_-NUil-oa4Ek&)9pRLJaAsa-scsSuOQSx21Qv8u}C2E^Q7s8=;w#tiDC~ zbzVI0UNE7<FLNL{K5vFSB(}l~$>uyb1DkZ0Qf%-`RU?@%7}IMLd@I7vcq~}=)agCV z{ro69S34pJR_WO16u%pq5yRbVs`o`AaYg-FSXk(DF7rJG?{*ur0J4~a@^?J*)+^+y z3UG4ZKcr;Byd+ScmT?9XwDPw_=pH-XwcV$);A}35GxyuuVI=0Rwc5)y)gd*&RyNu9 zV>Cw_WNe%`7QA^e*opTJIZ~Dr5Kom_g=x1@d5d8APF~w*>uuk1^aNUX)8c~zGACy2 zQg8Fmy=RpC(`33FoOPgyO|2eee*QSKo4e{8;WoPi+qGqK=)Yn_cXL|NBcvnVgt??Y z|7xCE%E6EZX@a%rK;Mg<;Ht|q*`6^(ciad|eEo8O_{u0i!}DJBV7}u6@8%MvXTKM| zi)}h%!gN(HoV%hz+i>V3&zAI3qZGHw1HsGHMkRk@ukmlxSw9T*jy(1jI*(})pPBPN zd4@WXBQJ9AY4m<|dr0Wc|FboKr~E3hJtAM@S8e*M_`EI&(R|^a(9dSXSG9(_3dCn$ zj6U)0#Uh_)`n^fPPwfSX$=_em34sv_e)k@44<I{!@j>j7Ua{f#t%zKTM8OumkWBBh z$wWU0a^@_0!Vr1(ELty?rMApoNGRe52lC5pd%o4s&UZ51w<KMfQJ+iY@x7u*0SVE8 zpG1jO|Ef%+(BOmn^$!%>NR|$KpZcUSRFIwhX!LDF!EGT&uW*l)5Jn=YDhNQ$A*6ZG z+AR@PkpXd;!5W5WWga;e2h_$p$v^K97QZeqTE<x6kg6@{l7ZVEL67dNx^k~YoIJ`R zrzbx;tsjWJ$38z1Q)LQx9;?S1;D;a-zwq7YU1ntLFFr~Ll0Fbp7Zd{zB3^JMuk6P# z5btp^#>6|Qg0fV3y9ra>@$Nz~WK=?jDzC|r`a@Mj*(bh56-3q%-<xK{D=1LtfY60r ztTseCLnGMgDYZm0=U$}vI~j8cpqocp%uwtnXV5}1XAS^8zz-nBdSX&gu|laxh=c2W z*TkC1=+4k5MEU4^loC}>iUx71+Q(m2v4$2}XP^LfhlGs%ClK!-xFoU$C)VeHu56K2 zT1~17ie<G*4hrTZVr52^lli(~XV8j_6H!q`iQI8W9^Sw^+AL!4P9l#~Q}NwobWc*R zft0?)^(uU1BBGo4o{ZpeR2Bop710oDw}tAq9y4br%_9x}93}E~$1S8#Eot%$#~d*$ zk0x<Q8r4*KTV|PuVjD*Z-ix&~NcAz|IoRU6?1-G5^W*2G5|t82WR^YyDLW`i=M$Mh zC@M1r8K(9q#Vvt#KSSD;%BGmaZl%kXN>LTUdlx99Vk{pi42cMAdx3cfXNI_64@CL$ z<`DLx@>3#tKtzBL->F1t!uirLz|LA$zO{<VJ4v}P#QiNkljGZs<W$IhcDpKvQMO!V z1wtGr^#;mmLeAntLX(2C)fiH1c_{<Od>ZrIuVI*k6O7Dh#|f<i{KRtBj=3+v@E6SE z((?C%VtCPyvk{&!fspK6hOJya*Z8UWOz_^*+WOeD-8ZD|xUN?qau5YLV$Pu|htxdb z2~^=Hnd22Xp{&%IuYv<yd6tO<cn3qyXKQ~lLUK8A{Cg*97!CRFDu7UbD&fTC4+Gfv zkRzeF%<^##B8gQ!&zK6Ib%&tvU*?In2XWcK$Q*jk`AQT40lC}*m=hquzrcA&VDuOP zX3W3r3e|iO<$);?TP5Z9WX(bpzGmMSXMmU^AYWZk)6k2U!Y9|}P~Ua2xNwLH69hm3 zn2Mxh*BF*Mz+yPSiHfl#K*Sdigl&nFhqx!am3ERnz#SIoi(m-eJt#BK7J6?m%_@#1 zXBViuUoP2J;Q-3>h<wH^p9ObI=g+x>P)n=byLov*N^<q?l>7t#p%T>OeHudr!dhul z5wN5x?w3@Y#;a6Er7(5F&glS74YyJk^3J$m0e4_B7(qSaJ8(qZW|8X)L%@cm5I(AK zH{iZH^6F;=A-q+-cPOgGSk{87i12*Q-wm^`1E|6PpXY@zh=U+eh2^3=<1R2Xj3{RT zzWze!W~H;p%Zw=k=2XQ<r9$px2%9C~pCX~_goqk8ys4JJGhD&9$W_83(6o&#e#gs> ztYJ(~iY_Pt>N00OUp!}gg7oIDD@PZ@8M2{!PH}j#bi_yS*NvNyyLW?(3_xz_ITJwa zI!(L~#_nPWT5(}OHW;gL?5Qg1@F#hnMLJnN%}18Qi7%$x9!7<dECRzBfXhK=fqznU zHQ_>R1o0s8DugREiwEeEa;3d9t(qz-$Ff-N#u@k;MZA5%Y6UfD6lI%e04Ki`On^Mk z!B_Gxw%BXu^m3qXH0Oem)iv_Xkh>5bU-3@87fu>TAtxV}yM;qxKC9&BxMLufAFvQH z3Wz{Nu@r*~Vf5HmZY$`(7N3VIqSgDQ;$CguHbPA7#TCc=DUjtkp-R@s5^6^96;}C5 zXPJ0iuLfTv?F8|XW(~}M(wno8F)sMlNcVK-_89KM(=&5AX^nj;nzFqeFeJ2`4}e7= z=X12RJzJ7;Uul54cEXWDssyJ#sfJ<1IsPUnF(bPSrJ8fa%0!G956MmFQoIYX{lll^ zmSE0%Z=64-m9^0c+*J$G7@vD3zDF4ttOF;vUnIxw!vw&)txUuhYtl%(w28DBNOgfh zD@3I}yS-&JT3AcG`;4~Bwp;r*qiDAF*2xmc<-dGai#uxMUo#cL{&TV*I3r}2Tz<Fr znOW7tQE5V}6?CCqhlkBq=6iwNj66%3OYtbk!!$@?k4FarT9vQr3MD6mQ>D)-X&^#E z@=pkLE&iiOE6Z-n4H7<T2i4Xh3buURIgLnKl04vr<nm|mXg6FCL8)a9o-c%j`3YrA z)9LkP_?QNFfyPfFM54>^R5BpjUdg|Mu&lzbGWP7E8YT2vS%k7zFo3wzE5+BZuW626 z0ClxdkoH^M411J&rU+;6YM9l4S~<!)=Gl!7^dm)N-tN#AK8nNAa_Gay%6IXIqQ5vM zp*JA6-pKeDPgAmsH959+_z2X2jd;XQHQ5;r#8bFJ0Si)t1?YjdXB3S|gU3LT5M^>t zPeh@ZaL_OX@t>ch^r_P!ubvY*DKv`c_<LbVJ4^J|2zq~l>C_8^0bmzP{nJjydpo97 zk!{7%jm7v8QTA2Ryv%(jHb9Ff>E;6R7hC`|@+MCa=|s=D;=@4$rmi)Jej9Or6WY*8 zdBvzb#0(ygtsi)$7a7=pKgLf;(+;X<CMLCv*kGQ9SiPqCA*HUl=97>_O1g8=1QVzV zrwa^8<vTke(E`BE;Do4|Cu(&@@!srRW(6h!-f5F@Mkaqw^lsq?pVI|fbEBW_sYTb6 zjNoDe?DLSVxj6a`pNnQM<l(c*+a2iXY-Z#<K#f8Cy#P)`c(W;7>_E1*#tO_moEgfI z`f6&+_>OhYly-zXw>W?-gwfbYCnJ~NTtnp1$3SX#_TY6ZKEqZg&H6hWNJ8Dr!)biD z$g*^FY(#bS+{&YSVk&e@VT;l<Vo5p)E<gU?)Of<;xKQ$~{Glaax7xHyRwEI$DShQI z?|$9J0B7ol^=nJG)Fm<Eg5G@nt3<^2+pe@o>l{`&7J_K3gnu44%7K4zE`B*VnrOFl z@%WsP%?22EYlXpT49SGFzAiJv55?a!lNWfoP=x_3uzgaE*Yp4N-SK{x&GY{94Gu2Z zIROyV-X)#qO;Nk)N=oNQ)mpohJPGxe0!~mq|BVldosHymWFtTfyPlnytY?@Eg06HN zw9hbGZcIsW#Cr>^{ER!k_Bwh=QX*`=I#T!soQ~RiTB;R!0+Q(K;C6)5H}L1!+tRdv z3-7}MZVf`Hm*0y_l_M4abf00h?0HsqrgK{sE)$CzV+WDKu&;<k|BZWG^V$DCmcB=t zt8VxN1fi;$)AEa1KyPcmATuKJofeATMNEq&q4FLFy-Mj@f1~~Hg?o5E&oc?)AAgq{ z7=-k1zK+g0+FJX&o#~p}l5BYF6ZYt0-t~xg4@aRw!Ic5Xa>vgs#FY^f%=xZQP|)17 zpXlDPwZyP3UlYVfyEbOx(AsYVXO-;VE!(5(nlC$64B_7yg-j1-rfm&d#U+-?-tWE{ zl1i%Kos?6`E9hbqmRr4NEkmsLF8RtNSLUQ?Jgrj(0iA6Bn?>|XTl~Q53PaCKNI}P7 z1etNK#|nj|wR-l<*;m5m+_$T5*D#MksFGZ~JFLh_+kB+?7rxuhr_HY6L)n$`m1m{~ zh&Sx-kn`*1FZwwK5UpR<WtK)}X<s#2R{Bui<W!B0jl{azmYE6Gw%cFX&;R0eEzqmo z<oV-u6h1w*CrPFBPVC`xJ_vr*<buSW@a=Y@uFDChryT{FeFCik20de(LO<Ioq8Au` zi6rMzVqeJOY8LlaU_yuP<<j1{RYxc4XsabqBFmf0K>FLASPR6MnymJB%5>2P4g29K zo4G*6NZGTo#BD$&k!pHVMl-i{dTR8Nh1ge8%e|AOeTgh{jd47BT<+Jb1+vPhM<}DS zIursc_$A@x1@1b{g{iz!_Vwc^%wqR*Kp4lktm@AG!mv!gVvXviTm$Ove?rr?53m1{ zDEtaoLAj*N0l1(Z88M8FVdE7cc_COUK}cZ*uPiGY{e*K|)M0YGEg^{s6s?zy)E**% zt-DC`2$m5Np27XS#}P@amm$aU(p>f~i+KzI$E0;6@4-o9W?QzMc)J4R@)l<V16-0I zsyv&rs??!NMy6>ADwJ=ZI2V0U#rQh4eqxM4{tOvHRTh(ERFX$Q1RQo<dZO9R8{|3c zx%DTWyAmVdxbHEXE_<_ol*e+qDI4<SL@!6wn4tqN%BTnOE0<&#hpR=GgeiD{XpC(! ze_8l15V6&FbNs^zHpA`KcV0bo;3E*nFlxWgQS@b;*4&1Evm3<&Q_S#M@L^n#*qf>k zQJ2OY9^N<pAsWjR@ai7j-K@>==T(6#<-}D9d*iQX%4BwgFO<B<36d1cr=fsO;th8r zV%8>J#|M)IH!^PpYIG$NwtHB;LG=Qo<+UqGy83!KC{rWWj)i!bL{1*P#(@7$ue{;8 zko9`Q^LVfVF3V$S2oPcp(oqvdN)<@urNG%VBsO%7u4KIT#idG|I4cl=umejeu%#ak zkiSz@rvy_}4-}ULv+BvLT4PT1WoCo(@IieswjM*cv`fX?1merZ?F(t#n)0FxHE;@t zVlrx_{y8;;P5x}3NUD%d@;-<7c5nDviBZ(lml7qR`wfMcG>p-uR*tBH66}pW6X35U z3yGd`6fx9W?dD|Hbpgimc`U6(kL5+K0MvM1_*wKNC-1V7mrlO5eV0l<d9m2x@YaIY zty`Ixex#Qk*DYq0+`X+UHA_?q)9DQK{wx1Z@uszzl*~<?tCio@e=A?qrL%n|m@+q{ zl-l|#>AfRM=|`_5oy_3Y$lzT`*94rNsCflk)!`%QJ(x0Hz!11IU5dM0g@~0^I1)AM z4Z0*&>=ol}W$Zq6>_O%~iL|_)h1X>NJWFZXYHk9l8hEZeiS>szm2R2AENyj%8%1<= zF?^DhuESKZ;zrSSzs7L`4gVMKUdrFxP0~}kR?p(XTc_UHZ@y0MH_*RB4p;1r3wo{P z;(CtFNM$05IX<Ec=WfmWiMsAt;asFTAN;D%N~pS``VQ?y@qOk7l}l+%&3N+qQ<HdB z(XTW<z{f0vVXt&B*@u$a>)kL>*PO$^Te^o{&J!||DXrL~n#(E}e7WJ4;hd%Zq2e&6 z!OJD2BRm}TqtWB`)`J`d;3jP}<a4LcSE1hvQWXZVLmn9p9_^3+d>^=i|M%+`QZ<Ld zHuZab773!`F0M%%eLYdoZN;Zd+<5@G*YmlD3m7>bjG#*kGCJziXXe%FtZB0x@5HoS z_OC&k!3Ye#!IA@y;$RmP2R|yHUdFMBm}<xiNRfjTy5xKDqV>6ehII#h@Pfo2KDfBZ zU<yOp9kh|VQN>PAMwW+c*hN>NkTz!Bs6YvktNb@ZRqsZF1M4MkgyUh7N^@AQTfJnN z<2?Qnl%Xwp0)z8_{_tuL%c4exYb0a-1FPY5xTmPGy&w2xi!{%(-67C|+)Rs_IYPpi zC`zj<*qx(6th}tDrJsw)?O9Hc-c-EyUXd^LcCu-|Uh+91tjM|6)SvTSaS5k+<~nOC zQ9KDG<f^-Y+(|13-avuGsiTAwb=T3Q>7g#Fq#4VDINDO+1&P?yc<7xTQ`7hBncPVF z+KrI@BS^_Zyhj`d9C^W9kQOPiddrBf>8v7#<n2f^DV=akiRzoibn`FB%Ax=Z%v1rh zzLySH+eCk8V8K{NvhHFw0>XJ9#t=;gDKZ)-$n4~DMB|~Lsb9r5!-}yA$;PtE*5k<~ z>*)xXxXUf0)Uf?3$(NIprW!?~?UUd*Hbr}U%zUz7ky~OBqqC*bZ`8v}8#&LkOZDIL zX7wk2r(HfcYaTp|`m$;wMI6Q1eQH+q$^a91w{u#tr|GnR{W9GoeRMB*Bh?ka#RwQ- z)x6~-74LEj77cmCV8S+K9K$_Z7pw2*22&f(&wGLQ{ffKJzhV0U{z5q44QC^iOJ%q` z(jZ#lTpQq|iO*Y_T_^%QjgS`HH?-zFDR6<)St)=eJH8<qU@PQF@5dx_}w!zuYD zml?=ba>x0)7`J!#(C&+u=?__5*c=^y&|5DdiT5^qDz%7sY8ztAHFGN}(jcqF^rmXz zCidBH-R(kB=eh2W*autFg{L}|Pu6~q58H2^{QQM`r3G~j3$~}q5y%dHXCJ8YB`5RQ zbs%AMM)rrr-!JLs^rQ`2gTyk9*n7L6-IC`0acS)BXC&`WPKvN9=^8h*<T6eQTiIYH zPw>R22U!r|;UGtb>)mPhlSr*-Yo$@;it?9k*4`NNBwxf)v`5!hv$&))3|%}|c!csh zy{_I_dszU@LO=g2{>nU~qLbVB)`hP);M$j)mzw9_+==<&((8j1`~sz;WeNH>8)nF% zVG1)FL%!7y5g<*V=-I>bRu2}DoUirTxOwpkQbz*GxY(`ds;+*PIwN%p)VO}=F&{x* z+7q~Tmh0X(ax$}y4{*()#zbmwgWi$)p5@kLvM5Uq$COvr!>q=>!zA0M!yDYMdIze) z<7!me0hd}QsTU7!l-)$h)OXUJn%#oF;LVpb(^NCQ%M{YmrxoyDL)-jIfrGw-zo~cd zClQ;IFxT~JabrNjRMl{vP0^g}ub#EUE97Fg5eNElqY<UQIJ;~WE)+TN$eCu1^@M3B z#-^F!c|$J>h3W}pp}t8O&gfZ%)>p)@Gv5B)s?x0z6u0&z3dhYQWI^t=S!*hKqq(f< z_`?|)>{4;g>Q*G=2n+aIysJ;ULkq++_;Tq4l&UOmTZpf>mtkn`(nbLD(Lv4EWhz8` zeIjvB1=!6U(B?<a9=c7mbuK5@w8?!zZ2KD6nx@7V_jXVty~aaQmPX<K(8B__{#rlN zo8NuEX(&(Jyt(!(D(?|`+cRt;4x_+ep>@&D{72iFn<*_HV_u{OKtJYVp2P7WC$;-b z+Z~N}1a&8F$GvzsZWL&p5^q!WuPcE=Q^)$*KK?d|!#wMdtMKx}wX+|N-l_+DzAtkB zbm{?e5T^r7mH=3$0AxAQlL<#cvUK?`4s0BH2FQ4r+<5@7xA;&UE@zC?D@EJ=om=Be z@+%5Hhq*tH^XWm;<Ja8+z{Au0ebQECK_P7GcSc2b=87&k@j1$YPmb)>PFH=J1dz&g zvgs~e{lf8#n!E|a*r?shS-Y>I$aJmNmQ1P&c~B^|Q2`VfS^F^$^QWtHu+X*+++C?; zYeE(@j{dmD5;MpqI#2y5+=Ef-5k8<i%|VV!fW=!FZU@!yNx^jk3HZ$86V-RxESU+E zH^OL6S8a1^f_g-TQ3BL20(Oo>mfmT}Czk~2#2>IeOIx6eM!XVOEs27vL%@Vzp>&8Q z`+G(5iW^kHlw3ao)eY4kdDT(NpCnB%jG91CmCZ?fnR;LXeNc;h@pT$n&$2zvbiGP9 z_f?Wh&IOscJex~+6zOShadY)^;R?&k`NCXTE|I0sD~>WSI;&>9a6Yn1Y)-ewg|pvP z#2|5wcQgy->{yyg)NW^NL<q-Qk)ZZbaBm9PX-((34MBV~!+=xO@sB~)ph0XqwREm` zr>++(&{DeFILafRLFkVm_mFqvSlr{DO}^I3t1sQE)4@9^04EaK)<>wM9;gkthOO${ z<=2uK&dti#l3^dQmpbCeZ<|skU)kx!zx`31%W$57vz8%H^WE`)H3KD>GC(Q7y^o6v z^OH<d)nZJDJd}>pl<v=I8p`D~z?nkrHR1nUu<x+(_u!PNIH-@FG|fS!zwQcYLd<>G z@KP}F7hlYMQwi!KK)y>N=S7_Dww8>gYeeY^sXjyxtPTxgb@kWv+Cnv*hM|@o(mz$T zYr>4{b(66UoSv(SDKd>dZ7_2jdkLY1+>%rR2A-StMNJG-fZiyou}G^@(S#9sPOck+ zv__luYrbaYCothm@217;n~t23Vx3=P%|YN#|7d!BLXs#3`55K}zj;S8Q*k#M>!IxF zLjO9O0;(zpktKATna&SN<rlKk=iYgp+z+PEA$PruDIHrEWniK&rmmml)k(}6BenFz z1e!#Zn~&@cMw-NNDv|fSWFE}N32|7E0;}mM@e{**x=>T{*107j42#aPRFnE*gtq_? zx^EQ>=||>cUrf5y%{cv7HkQnRi@LJ7fjv?jQ}nqpJ<6ad8AVGKP3<Kf(NAnUlYloP z0tKM0(K(Sxl=5V>TgNjJ++SnhBg(its|op{a4%>8?}3HpKf47_VUh(R+?7*g3~`bY zSEVh}=Egl(D5C9seBH)HCNR9#+ejGYL=~cA4v;H$9L}^-jhOW%KWkRHRF?Hgg5yp% zL5x$J-rRYrT2V*ZMP5@;<*$X3S?W2}Ii+fZ{fCL@XrPHK_$W@p0|5>NcspSTEt|BD z@MbL4Yu%*XS&LC)5|{qgNWWYv(fl_Wp$mWc!-Zm`IBZrDclJIUe>s{wjWXY8dFu^p zpEXV__0p=;)VMP$JD3(vlQEB*Kt_?E7jn%=b*2X}SP$n#tQHhZXE+*-e9cLxV9~L0 z)8tj#w4?m2s0+1AaXVGkqarNV&0d4FEa87=zp1fGK*44Ji8;&UlB`^YF3>H60AT@U zdgL;gawFXWz&|qHNK>*uflzin4}ZFr!icst7M+V!p7T|+BSE_dLrXqSi1tIVkG@Wc zc2G_in9-2Q0vUe9i;1+|K2a@W+MwmJPJGh+hCtDHQ4_myTwkgmxl!hYIYpSo|MITd z6zH>bEa&Bz!2#uBV_^5P^~Th;_vweQu&XwcnW81N_(q4);39B3zi;KZiqcao0LDtZ zYiJq-Gg4IY<KZlY)i$(CEE5TiHi;i6qU;u5crK#7od`{o`C#f7C8)aDe2T-|1TF5H zDLjHQ8&lv2(YoMQ|Bh7fu1DXrdW)V#osnF|W~jf-YO%ZeCYgR;`9EhsZhxABaDtR@ zl-S@?5Spr_5%S5$NV(o<n}e-usru1$Wil;zx#^!_mwt4k|G=~BDJ6H)3obeh&5igh zUVTi7`ydOm(sF{D!m=O)@xi$$9)gAc;#T_mZGX1jbca4_P4wQv`$ID^CqtJPlw1hV z^Z6R3U>K+yJ|8yr#gh#8SWeQWd%2qwS>kVegJWoe&L8H+G3TIKO2S=|&f%u8x9PbE z_zE!yVIosXxh_@v<^$34>PJuV$ol&_#`!ed1R(JgKe~MIL#6#bWr?&{&81fA6Hh#3 zk6g_vZ(v(ezS`Ro3AzX%O5gLnT;<!GjoKRSN9!sK4IJbTR(-sAi;aa-jxyx=9B(=_ zuuC0!Q*x5Q7*kOzJbU|aF3_|%JZPT1VJ)}(Ll0-YcqkBl4*oXXxNRBMBV|6M<0d*; zC&vV^HTISayUysrYTsCj3OuW2)zE66Z<?8IU0Mw>Qh|_Z!jEna9SzV%uU?3GRWM=O z-WmyUAPBT6zCE&H#u-o94DfHR<IR7r6M@<xvPB0=T=S!qZm%hu0J2nxYfnr2179ds zIn7(S(Ff_;_2SK0{+#sIIOmPU=C2sQQ}SD4w@4D@pQdMdr;L6@t3+c1gG6Pnva(5D zCAg0#jc1vJv#V7m?<kduw%=GQxl**X#3Lo>!mU$mJ8K$10egNRI!x>0fA(!^QuIuz zDkp3N>NT~)zw3{GetM}aeCINyhNJhN-{{D5&phn4bN?u^%X&S2N%rqyk2aIx57#p# zK1p+F|FyF*{ApzlqXaPlTK7a?-0(@0D}=Am*A-Ln>(f|-cNCPsq{`EI?^-52-l@pg zd-xV<<%8(-R_>N}*^Cq)zRI2#%uNerkifmOZY&=vxgEn+SlezVWgaK0;q@A@W##pW z+Ima!dV}ZwQr~5ClXblp-HXj}2U=FT>D8SO%8MGfr}C{OXuPV<?d$|@O>=R2;PQ^r z$K)>9B*zxfMKWH{v$|Vpt_3?#cO}JZtnr+ACJW1i(oR9BfbJmv+Hq)ig;_?XYUhbl z`0(HBqZqcG5OzPJxuM(a#AI7suqKSwNH^+-z2oxR2^}ssi0)6s6hVbPC>I;p+=v-V z3U>8xF!;7Erc<cA-HqF+8YQoh-WxsSr%&h(Z+$*z3ab@OmJ?hPglUAoq0>B}R~6r9 ze7!OHQl(N;<rV|pE&6>NQ0J4Dmdn8Pi5d?}x+L~ZSC9cmpdK_cU+%mbnN~LZjkR=` z)-ft`<0;3<jeXzs0#!aHha!+FVT`+;No#!&y>f8aH)s||zdrw(r~Ccgk*k-}670Tl z-M;JEp}Q<d2}v#dnRus~E$*M+m#u}kA@tRAk6~K2mp!$7@q&`KXP;ghaQ>2$e=-<e zw0y|w`?g~+ozrw+&O)puPQOOJ(=*Pv{m##9HCcM3#2~{1xiQ~aH>`rev)4GSZk>N8 zY>)fm;C}-?W{)IvJ#9JA!XnsYpx~!8-v<GdrM!D)@i+VQ?+pf;{C4fA61<T>+~bZt zz=bHX*lqM67Vy~5K_stlO6sHH7ry7CzjbGDxclCEr{>K0D>2yP;L}U!z94yri6CSc z-JHLdi~U6Nv(%bK$Jh8j*<1@lR`1Q{(UsT4D|WI52e3ts#b1}6k?x-?&6YL&pkP03 zpE&xYZCNJ5%a?ZtTTCB~d1gR;%&y)WKy>B|9YkdXtm9h@j6!~eh^s*I9#o$seRsWU zf;|H>AEY013ocaj2hV&-{dc}LbXfaUvdH*eOw0VN$&g%cob5rdEpEU#WK`yWQ{9(> z{A=5Gc@XieZ(qlF5I6qbb6=M;!&7FQ=?u?%Tc0A;MVPbQK6^ufgdgdt4Sz-1-2tz( z{32=y+zB6Gd#D!tx~|GC_E)jt?<mxQ<#`vyo|gv#^9unJAz~UU{%|w8l|0GX`N9Dj z*(v`0F4Ggwj_$Z{V`F5@jjJEB&{tdg9KMiZKZ&YU^nqWBH1GBK7UmK>Ew2tOKbk|W z9zPZ?Va&Z2|7-EbPVwf(AzRwc$H#ERBp;dBa=};l-hn}S$^NVICoq)H&I#?;-|;Il z>jzOwMtaXL72iL5rkmkzUTAyYD_GUp1gwF1iy;JQaDQ~S8M*Pbs|&U{eSD?6-k+;# z`7d2}Os+Ij!*<_a6y|YL!{c|y@ACNYt{dA_;4pV?+$sD4Fz6%s@5rF}A~h=i@^9?V z;-LB#{G&eXG8G=8Ivi*nPI>({44d~0YC$$*{`dFYe}A;a#8spF0H`%HfROQ;Ky%u% zoMlqqqPhU)tm4*HEp=34EFbIT`mN-ms6@#5hcd@j9H3;rvsoSmDQNCg4vr2PGFEIX zPhC={0*1z#gD(piD|vf)8RnTkyfG;m>_x=qS;U~=BGZ;YBGZE$krUB^O|!h5a`mO~ zDRFe3<4yJzsZ<-|XZlxC_|)xJr!vjVE<fUpcGIl{;Z|uzhu;h{WAEM&Vnr7k5|d!1 z_nocfXTTXM5xs6_KQT1K1YSm)5E=)lIN9);3h#R>vBg%?HU57teOqb^`SI=RAC=wA zD{XKl{NJP9DXBLL-=6Oi`XrRO{KQIfWDegr-MH24??rIm66=2M_dL~hDaVoe#dhr6 zC)>(plb9MwLf~pnR7uKxLgR$fWqr|UET5>Sv%4}^3I{rst7*khtFt%HXge;LFM#Hu z^!CR2bDrn*t2=4gMvx;~pPodrevuK1z0b|a5uX*qan*y3a8v&z&rg+?)ZA)l=ebk3 zwicusx5W{CzVDK4N>kq_8$IqsyXl(&$!=@9KVYq*nb*UQMYCMv)x@$rb0leEpa3O) z9~#e3Ye38V;G=<jYe{sp<*JwCQ+8P3Vn`B_;GloLGT6l&_)T)nK0FqkPBHC#;beZZ z6W@z9Pp*uePP#1gc`~(OwG?ZXwHYkp`0VO>InHkQpcIE)-MnUY(dn&=8KYFwxwHr; zk8Kmb%B)J$c<T+R>+5WNC}NU!hI?63VJLsHZd|iyK7X=@bx!YtnNKEdvtsA$*dE#z z7?%dk5DY+dVPYM7!x|Sl4;LaXbRF0HkD)V<hN=(a_?^X=#d61tu`@HqF8fZ*jFEjA zOZF^D6ou?!hL9ziu|{NxY$^MeG^9c)ltdd+X+`z6sPsB#{=4(XJ?EZt@AEvr=ll8m zE@I(&x$hq)6FS@GcG66v$5cI_!$-Y)h505c2t1+JR~(wn-8Y@q9yh3-`!_;qvZ_*k z+U6kJ78~GH^)uvce<9XqmX}`|5>Y16Iyie*Hr!!<v1pJ)+g0q;At{xf_hR1|sF9vM zsy@#yi`*s5d*Cis{c$Mu*mb~nIUpCleY9pR2*w?p@N~{rKT_u^x>**SKOP@4`?#mW z>e%mZO_759zi01DRg`b-+j(bdw2~#2X0)2CcHm73xz11KvTC{`^8ndjZU4POzRjpO zc?*is;Zn@)q$8RYM<qhx@}Ca9A-^8x%x+XP^w~(KxbL1oIxD)p?2SLvM}rK<pT8ws z&APBVRf+d_xOHnAzSDKc#3aYSYVk-(9MQQgM9peop{G5hSnwZnZRGr;-<K3r9Ou{2 ze5=1g{yq-vXCKJZaDAL>{P;wU5VT|4>9e6sdv%ynr798v3=Ht;bfgQNB*Nv56t`tE z!~JIAn+9{kdH4;YlzY*FNSVbFa+7$rn^iQaXfReZ{+Ss2&=w&#H=^nNfYh~ZBj_<l zI=eh&j&86K)?`#p{+X8NKWY0&U1W^A7MeRMCFeBLuU7$&mY-2W{gH(l-VK~#SzWe4 z>t~SE!!{Ju9G1Si1m%c79;Yarbhj=1DKh6sNhvg5p+9coYMC?qt88Vwn@>xtuuK@~ zlWw_x%-r|AuG`7ZP_28#__+>-<|^cuaEXe#Et8HhUBwrk`CP7@AljQ}rr?<pWXCa- z^2GE$&yUaQ)Nx1ylh0@5>J$KnmSV}QHiy%CIRmP6o6;vSq)K9=WyD*o#C3|g!n<XA z4Nv8eD=m~B*rj95D7J8Arl-3ti?~rasF_xW0GHfziJ~!1MMg1<pu3`~T^$qUT2tg? z>8TzwvJU@s7t&2~KA-5^(CNU@^JJ8wrxA0cGc~sYp3gm1WW!baB@FoLoulN3h=d_F z;#7j=*UePsxJ5k;ihEUJ1X{V!95UNog(uA9GBd&^&$)Ot9|V_~cUjGkod2G=N8R{t zch=_P4(Zo30c$~52MrIV{Qb4se+QcC>Xx~A`gIM~$=mhCRS&bl=QdTbFeRqRS#`1A z34LKQ^BA*0H=Iw=*DP4MG^{SmGCf31<_lYz{7zmdPQY7CWMpzpK%+Q!j&78GrGOgR zDdpX2d(WGBXqTBnUt_J9S?RdDFUNX!Ks+5E`*4S4DGkw2bM%<4OY>cQy;rQlO;KMS z6#>w4eifdRsE%g=H5<=n(_s;&CG1tjW`ymYmw6_AHOUMGWUoU6YRpmd5CNDdX!^IQ zsDI5ob3k$Hf?bCXw&~aLzT5CmndZ=(q|Y;^n%aAuE*X?mvXV2e0yCeTfEI3dYtgkG zcrH}aO6O*PWM<|19%Rg(l)5~TOqOG{m#vAZVGDP^!gO(jdV+`Q-Qigx|81}Go?lkk z?g{chRSWcwJ?Gi}wf5*+lcyrZpNtp9yIj4lU3lX1D;Z&@F~QJdq^f2vY&@3q{m>@u zY^zjW9tDD?ux^Q}UKW9B^$)fW6&#csyP<Jtk@TP6gx13k+=?a6Egbi%&An^jm+g(a zpFbR#Ru@6OmV}S=&c4U(v3wgpJwV=WCyGrs;gnt6fcO|~#(m{OHAaE`lD2Df69-XP zbK-dOz*~C@@>(V5O8y_cFAK_DVW3;|te}<#?W1~wBkNzLzQSW<no7nIK%CdFzmu-l z;I1y>_mE#*P6e)VbLv$PZa3{}{{8qlX*K?wA{^7J#}e-nGCC$P3CHpT;$R<DuIht= zPr98OA}g%+m+DpmhK#Aq@Y7T-zB>)5NV(+I^^>WTU-%y#d2%@;M+cqn2WSkcICCHU zHu#{y%4t2M^Wjv;Q!>lIrZn27(e0BIz{h!5&rfW+v8}06q=D=j&InObDkWl$Ho*)& zg}O&&TthVfTm#aNm4+NHiy--*5w5?RhabCR5snU!-xX}AmBzpWj7FHWyo%NRq{{?e zXu;%rAhtr;WQCDCn8X)jDYAIrpUIP($0D3rr|lsaBWkbU*im`!6lDReofDC0?GpeP z2yu!UTYM{IeU}q6w3LK;mM<Su$`-;*M4<2d9Y3)$1P;Bk|9BI7`C~yd1{5{$j5ul+ zxV4(iOEt)qK7I{1a==hoKYT-_#$PQ!=Bom<d9F%Ank`dgJTIamSv21`{VHgM#~Njw zpdB0F=*z~I28SlCr3RPE`zG9mUkW$e-EDw`eBzjj6-8bv=JSb%4=Y~EQB*Z!Z#l|7 zKF`O1wWdV7i~TuiZp-rnnExHM-2d_W4U3(x4{V?Hr^@rKCma1IcVzzMv59J64hQLS z(SMzt3Rx~Y>3536Gec21E^g-0^w?Xh3g5(+`#|0%XAF1m85F!dx&v{8-mCfpyzE`E zA>Nat^~i03(npZxMZFWH(YMXFFu~$<{Lg2-jm4yOf52VZ_ff6zTy-x^vfgUhjE`#m zN$RfGotS4A3`lI44e^u=d%B{~)+PYTKBE{0fvw8`T0kLC10!3b2n-031q|^4cWo-# zI2pKmZjc;Tu*(Wh#VWxwV6mkz@V2j2wUt=_O`L}+vxdHxlQ*cBH($N3?q?PBbU=DJ zvhGC`9*XrjKhRj<wuMN*)^n&&V}|onQEZ%9I+Rmqsa|jO=!LU1J1Tt|TmO(@vj|~~ zijKe!%_C-W>t|-9S)P;wn~vv;kR-AsbxDQy_SS_R1*f^Y0*`gO>gq|0w;ads)YYrr ze|8dlrAL4IaT5M-)(tAnQ|uzW3wv-P$#&27OC;6{FyrCW0e#~ND~3Q3kqQ}>q~WPM z(%ecFtAFqC6hZ?{mO?K>5vwjf<vU=TS#gR&6_h-E%~75O%_VpmNjhxq`w*U~Ez3VW z?p&z#V)7*UaAt@V7I<6bYvuon(M<FRT8re+C1%AuZNzVVggaizjLdwgM*vvqH5hV5 zT?GTNza*grYZ32h<se$LRY~z_u>5(^iSatf7&4dXViJe4-*zVM3d5u8PHU|_>2X%$ zYjn_(GiE7JeES-GM;ec_1DC?b0lms&fjbbj3l1>k^QaKofwDu#1WFp8BQCW2ox8jc zBF<BbYdH1u)li+n)5#YwVgbZypX-&CoRhN0mfa<%7@j(fzBY3VpWAaXfsly?o|(KV zLE?b<E2viaJx7E`wt)8w0>!)0lEQN}ak|NO@E@yg^+Ob$St@ld;(RT&Xue@B?1Hz~ z_Bdb$nG4GcdOuDtD_0v+h!1Vr{k=CvLTeR|MA5%61@R}>q5_u#Zlm{WRJ^?`bF74u zlAWt-a`<>X{gBB%^5k?G#3?DVOtC17(0caNuxzxn%e!bReymc1*?25j)YeBR@r9G= z?j$Msz;oEgOE&6kWl5z}NvmX$@sOP|IQ+$a0*_L1vhffes@`RlWlpKB&LwHB9Vr{P z;99}N<q2lZ`%4bn_Bf^9F87i3JbX-vOK9OrHjt?4Qe%@4BY<GE7V56VHi2lNQOLCB z(|duEH{$`Mvg3@x@(a0mC!5Tr!=?xp(A}8xwnU}j(IsfCqKaQw3nlQVt7xp`9cpLz zEi*yIH{(<Vg-AbI<oAoXO@&AmAX{=Ax~}r`Z;+J?fQKKb+FuU&rt-istdfu~Os4W| z0usX&o#11chya*C3;kQx=7hb>+{67DHBAIKO#D4#O&M#<RvxmYJ)wy0O=m@7*|2l( zxrnw7p|&T{83gJm&WyLyGWkk0a5U}>f<ROqRi@%2T1vk!A0zN!W^IQeWN6>&BiD$u zait3JF<k5-pbm5loy`mXa2G%Jz%QVme*Wr|s%qHSp!xVNffQ#%A^envZmvgj#wI>0 zIk)5v8(_wNWfRPJE+XSBK$(Y&I_k+thw>^QdOXo{Z>_^<QG!;_Y3bK5*^HPlhBTUr zepX$Ju_79!KZCQOIT68!NVk$F96iM5_W~jNZr}K$d@d}b=zSaXqxysS3s*DVCp?cx zQU~x+A4H8*j-NXUQ)cUk08n)*%#2nlqP7s<zL2)ZKX4S+;0I+<cu=j~dpx?LcNtQ` z1&FJ#h{#CFj>^=VeYF7ab{eCErxW}}MZ-oXpol01piBTDPhEb@lNzkwM`A!=%CCIH zk3r37%TD7jzV9L6p?6&2!X^-y%N~e08ya@GcNMYE@BFi!JK2fE$R6p-Xnv&-2;K;? zSoj%6g%DW8$jC4#fkEps;k{Mlt(%XE0%LF9z*WL%_<I_g8q`G{HjY6flpLGbY<~&W zh=fD&M!?E}^Xo@GeI`JO;?Ozum3>j~j{_MS(5p}i05bx%9;<_s8)Y0iDQr}fkxpnh z_9Nmd^y8~kQQq1Y&Gi+{ulqC!K*r~cJupL72h5_ww<v=IrxPequis#l{B{Fjn*}@J z5Q4Pk8SPg6-WBMH%@sI35>17H9jN{e%ndDpI~@WKv;-Hlp6shQh^OM&9fChPg#T%Q z{GFh%Hdajgj0rWlwGFGOjWg`TS!m;}JMjx0&AaK#l1=>KPQr0*v4l=BmbSPii=#N) zdLXM)qDEV?sZ;W*wp711M^W|0V5js0ZJC8mnU~tKn4|c>@GEaR<^E|C`MZe1I;6uz zBo0|yw2Q2%BX8IxZ=plsSCy6<Pv6(25TK)YxJ&W44!#&FVJWC|x=Z=2j!Jo#3g!c= z?|I+_9ku>0wHrF>cXVuN>Dyc~YhX%8<87D5hK}ZsFVSbhpkZsbT&`-0b?<1)>FOw* zP&*uW<IK8&imsk@x1O`Ee!!Q+9R@FAmCsYxFrnL!rEA0={fUqI_?$A05@FQTZE{uD zv|qP#y9!u)koUOVbfJ6iOI`D~-3wNpX2Jn~*LA7<Jyc;mT8c<0{W)Wo{oY2<vo!3n zw9sRmuw54&zZvN7$Z=#G?%8)-&pJU*EF8CF^mR{)o^5%LZB6W6i_77H2a-0m>~82e z-05++@#SlU7$fb2!`mLG4L#@XuBbBpx~k%g?|MwJUZ&iCG6CHT2{Ld-&(%WT-MZIZ zcZ>0=-3r-j@7%lpxV~qCekaRr5dhI{roEo!z1}tYK1vOSlJNJ~k5-3w;(YG(`aRJ1 z?<Z93E!WkI_21AB_|Y4XP-Jz(v2eY5bf-5+&LCJRek4;O##>>pnn8$lUx@SfXn{k5 z=o80W`*tPPhZFjaDW9`!Uc`2F94_w*ulXKyRiEZpazqL)P;U@%r!Ru_?>|j%Nh})B ze$aPp!{GQ=y(y1OAD<(~g$<*{emFgNG#0h|OVaR!VgHGndg1ygqhnuBc=pEy7#dw% zXv)!xPv}oz^_xDOM|#AaO7BmqF-*2UvF3fulN+CW!|>!CL&^;%HmmW$lwsQ2{xr3i zGk*)3-h4{qA7Bd)$Q@=fqF7^jWB7DUqf>?hQc~r>aOIehQI_XG)^Y979pNlwfYIrM zfz#(Vm2Rw`K5LX)o`^X-U<b73UNy?^{~5n}iPk)j|G=nVVL*OJ-$VUM!G_V<9|N7e z-)WrQv%<z)u_W8)vA}vSSJSxI&{#3c8{*Pm>}*`>`D-}hrKL-K>2Yi0@`R+7KS$>^ zsJ+R?73G5!HO7@qgOyi}&-V|WzhPW;XRzvlarMGr^-JRmZwD`I7}xw5todhL%Rf{r zY*HsSR3~RruQXI&PW6KAVQqBn4#)*2*aGeuhc46F?(hT}hT2~y?|sQbeH_Ag-BxMf zU8&*i;FnE0#jY9V(>rPaDKCT!<u|3Li?|60e`NRAoA!QXi;7?CJDy_ILF+o6ap)ek z<0b&lr7O6M4SHq_HC-EWgDO;I*jCXg6X}v`JfX`F8J7&FIhrWzBTw)nTk;WPn3Xx$ zc1<B{dPwdMw3pUp_y@%??YAE8yGiYM$vzZ8@45+rUr)c8@CU`9+fG0*iGKvx!?u}F z;acjQi-73m`;rvX%P9=X8B>_{@Ewcc@waAI9-QoWNV}|*V!s!>^YUbueTKCQ^cL<f zYMsaPWl$Q}Q@g}Hj9H4+@X3x3JZk}Z$B%93=qRcdcw(K}aff}sd~d5gt)rXzaASvo zfu{&DI14GmPiok+p5rP5?3)i#JM7b~kr^*iPNLUMt-Mk@+)}N={$8;>34aYtpTGVp ze_N%Q+97<+ck|Dc1sZ%Z9TQ>x_6F|_ET!YTnbjus<_8v48aXDzOBc`^e&ETNYq~CU znI?4RWY@y>vf=P8U-)Vbu%Mat%EEjzA-P*@<j_azQgO-jM)GrKxB|r#gWO>V{JYXk zwHl{&U8H`{%#_j_CO%8MnZLvMII?O9zS=NZ<hR&9Iy7+JB0OUU<qr8GmTEOY>pD1M z1@55OzcuMq^r!r$BriC1##nn3F5u2D+(oi+LC{ZUB8Q@kxWQKWV%njP26narg)$Jv z<rjV<rOL1R34`TPa5x_;_T8ndD7z_dFO|0~rcsxkapo=+D%YV=cJ)Sw>K5|Oy9h8y zcUI148EM@1^18E9nFZ%#W*UJZckN==fJ;YqA=kz+<RFUG=>oj8+wvo0t2z0Af?d2= zg<o`0P@lN7ZJuQoqEJ81K-=SbW!%w)t3h|l_MVTAeA*xV_VM-e0SU)nwto`QGj&B+ zRy95A7%<hkCFx3is*X2}M$qu$A40C`{v>*5WNM%(6SqlEaH{6-6@IS1Zpd=gK)a^Y z7g#ZmxT;%>u1@bvO!4W*<P%-gbv81mjf(9pRKY*f<s?M`94pE|3^`ZVU`N=#tmuk= zbi9_3{Yqu1LwPlbWM|WwP9)%cb50K-i&haC>*vC*;wZ_eY$?s6u^|`LR)(=Ce?5&N zJ$F~RFbjEkf``DGWTBP$lY>NrC)FR`)17s2o7P{9csOmia^^%mjWCr@(MQ^?3|2a+ ze7@52d1$4HCB|<TK{g~5rP~)!dju{jIfo(ZmYp~m<Dyax51HixdL?9=!$ug_4`puh z4ga=>Y<THi4HLY*N;;cxe4u#T4XfApJQn<uKFu!#qzmqU5|ry<dt20TCnMJS{FOh- zLal_OvBaTdohXyjl)*MWlc?UXI!PTn>>b+_#v%R;*0yDs&G!Q_c|<prn6pHjjB8P? z#JY{+ZdD;OAyViv-|W4APyIKz7q+z_fY5BkSMtxPx&BG6%9SUp`P%orUKJQWK39^q zB4cZwVb++7$Z-F;P-pi=%4YQfa_@@I>B8%62m`xgU#_1?qagQxjb|Js5<ux+@c4i) zIBK4<6$=uSNz7V#XR<9ABd=<BJ!~20QxI2YRq9mt;nc_K(rbmYPQIUd7mq#t)W1^r zw7%WryC%6x2on*S=_G68a;~w>1|ME-pUyw2S|37E)yYUSvRkpdbq%*OVH)=QT%Y;x zTKr1AP078r=BK1@2=w5Vs`gTHMCO5No06>eUx!(*adV|lzdwzB;Q!-!(#G>2HQVMS z_abxIv(1zFYm+`>_xarTl7)w2YgKgS>eL_Kwc71RJ+$l}UOc#TfoP}*J)}{b@c<H- z5sU=yLdB9zin3hWkRNc(|NQ^`{k8G(-#>^r&&YNIKJ#j#)yc)8&f%D!2Kt%Rd-kcc zcl`W&SVarpbYgDc%nFHj>3kOu!C9xo1;aJpRctEibl_v{<#mBaFZD#U)UG?*Z`s$y zX}D&kpg5=Zep?Yv7vCj6Yb)-bz+trO^;EXj@Wq^)l9zZenR|e%;Ikdud*2m}jMsVl zNijLA$T6ccUd~2qk~V8S3p)73*D>1I2UMRB*2VNhP`*BAT<Q^cOX?oAK+DYk@tb{? zo~e=KVqIxru)>C+I-SReU6UtC*xEW36%mfozVD+`+g>w3yHl?6Co-(K?ogr8n;7~t z{X1tSqKU|iDodo*^^MXQg{Eeo^6f)S`4cOAfnT0(Bj!fV5IMG@+D{%TzP)SaQB*O_ zihZM7C*c@=|8|&;+GKfl_IP<!y~&gr4Rf-~tO&VU1m8M%gO|mX7i>2>$GD|J?9KJQ z-w^uV)JBFA%XR!VcRp=AN5D<V=IXD@oELr*ahEDwvNTHS1mo6sEV1<4ja<0vubZ}C zAH~4*cXbJ|;5dt#i;FJG6#1*VVxn|}#a$HKAYP3{O4Ie6E5rr)&bL&EtHtEuKi$!j zZa+nIdH*0Ea6bx-RHDg@QH{q*$L%9q-AIxiEl#Da9=)p1#tk`73g9(x37pgC4vw^$ zW6TlMJ4b=<^F`-GXiALcR6;P*-6gM(pSue<`z2ztm>a9)@_~rz%Fcs3HxpQ-BScg^ zFLxbmd1Cq4gCylW=~UKLnu^o5kD=SHz%ze$BKJM0EK-?Z_k2IY6_gP{Nj?kgZM(Rr zgUy%@Z$ZbKnaEqc7~l*Kg~U8MFGo}wvnz9=G)oT#wC;eu%K05%0&(w-sO^#Rf9F&_ zG~fIAh^xC-!8u`n6Vw3{l`fVOK9ituMh5B4Bx&S%)d%#pA?;3|e>&~jP&E}7(fHz8 z)$=}z??=6>ftt{ka>q41W>&*W$d`NMHZAJnstDv?vOmiC+?Z(JX4b1X^P=&~RtCmF zU!=eIJs6|(8(HP#lpA4fuGijFIv^b_wt7HU2tK?gt|@<`>t&gZy@)bvzAEp!4OTuB ze@>+r3E@7iz82NOgSTj_+p59zg3nEP^nEGq6tG29!W%EW{^(ZqbOC!~TqL0dnz2rN zGv(M2s+2<`ywkdd)BAXVza4s+F&lbA=o>ulwQu3ko!|?{_8lq3Kpxn`Jk}_lYZ`9U z8I_`>7oF;Go)DICqqc~3$nkjP!|Lzfo)QnOa{M;oL*uskS#J@>&2{H7#gm+N*eUUe z#R(+VDwUsnN@bu<(3Sd*8t=lTvDOfoFoTE3E^AO9X0o5(vbpC}3oG2evT&neLaKp1 z5n*39qV7T=JEnqry8(XJ+EprL=~*r(*j<NxiugH@&+Ss}tr}L}kLz32$5Subj$6E# zSmR9=<91YB+sK-BPRvMAnMz$8{2?alHRbpSwbNjv-3oE#Ras)p{{P}_#zx0ab&2jj zHR5o$5-WoCdHFgjvmqy^t|X)C)A=|0{lBK8&3B}x%hvGSy8cd#y3O=~K%8q(lY>Ff z)a#DGVgeR!F}j=j%QGDpp*y>4|N3}1ljHMBokm3K>*Q*@k(_(eQ?t9^>U$cOiD&|& z``Ktkf&lq#T>tOqTNi$u4=IgTm~6ihT~w9TuzassE75UXD_%BHy5HpnMlkdM*U)H3 z-mxafeh+!}%GI?vOy?gf8*M)0YsC2C56>8g&yFQm9p0(40&j-I+#PefJo<!@e9GXz z3n|YxF8qkMF7cUZ<1RP;RH_xvBm!rP9g$F>rV9Ayy<#Yn%js$*?47Cg8HD}-DL~xE zoW$tIx!Pn1#pP_;I5BfgW`ab{Z2bMbBFEbKby%WtR1uZHKeqg9qvqe=T>{bHvya9K z<nJBK0yY6GOA8_z1u<?HVmP5MIZz%0&_?QQ@lB|<7EC`1X50bWy9uLd!L6d;wjFTC zO*m7F&m)S@yMxbvlP^dMaVQEA-hqhRL_}-x$3^icb?~Qd@~3Mdv!al>9ms-BBv%Vn z8ilIpKvi#|>a@^}QRtQqbo(Z{Qw!4@g&FK%VXn_mjA$5u^mA<->>`3AT7vUYf{UQS z72+<acy|d5bJ7a33IZTo!0<Liq*hp>RuG~M@?pF5AVM3vguU0O&ssuKwUPCK*o%Rn zLbQlVbY({%_EiU%cuPoZrxSQ`2^7Er0<|Kxop{GtE&#znsJO%|h!z$?%w*xvBoG}$ zILakpXu>M>gu`4>VLBn2DW)_A5U_&ITjE@8iC?G1H(Vge3ZRxYhPa0Hh{o~*5NS3} zj}Cm^6c%0;*#JR09lOziE!~oy)s|Vw#!2%4As#AC0o?Uth_Ho7Yv|TaN!T*#n-=~$ zR&-Na+A<g*%z~^(TSTl5shuPFl_@F=$PZ`>{liMXni1D06JKdT@G<hnUGir^c}VT< z44#6m1?XEsE3;(!tTZGBdn;Q0oVL)XS^4lT#mFv%gb2{VCIc&g)+||ROb!dB1n9`` z)NTpw-BK)#QK|R>r^P6#K_LXLf)bew2_*Z+$g?K2h2&~gu76P*b=5Z_p(nc3r@Pek zx$<2+6k!<<pzb<ML@YD#JpfvK*NVb}Tmh8T=$NS(Ma(D!zYO4)A+<4z&=qyjVs-g7 zl|6JEVT+_TrrPOB)F(p-(TX=?bd9@p<5rcWbcE^x<vVJDFHFEyN4|qiY{NnXSaW18 zU3q3Y-e^lSKvz+csJG!FB}Y*bE+!+F!98QD-bKoWtCYRE#-%5W{h@lh$L)GhbSw@a z0P=by1F0CfpszwWHa^%@6t-*-Fb27V0}^!=FDyeIo!GnBy?4=VN5gl_P?N5j&`r+# zBGo;oEEbKg=(hO#)k3!(oMPcjwCNbFEy+|7oLe!u!_AO|BX#IPWT}R2x{4DgOdjAA zy}HeQd{vNsNOt%tbh=v#n?Z)uDr=50T12ScJyzw#cz`Bw5D$jwiEePHnq(S;2nZG9 zy8<n-on!|*AWH;oNCI(q070}At~ZeXvJ3UX^em$c^l%5qSYT++zFSfB4{nOBC6-oO z3TxeDn;<NTs$h$^*n^XA_$qX5&T2)^>E8)#G~V%56is++pIQ;wW>nR=gdC&mC{s^^ z0M5oMrq;Sj)FNAdveD=_A%$)Q>KC;7D*aUlU1cXj=d_N6_85ww&3vurZWX6%Au135 zCM2il-0052oSY>Id=rx4k$0Dn#bdGhMdYqP>_HEv7?<gr0YCwvQ*mCoy<VsEUA<Q= zWis#s--LdNknVLU3y!M${zr!D3#r7p_s02_7CC8W;0Uu4*1>Ai56Kgywo-U2nX&zG z!OW&;ti&>^mU=*r3K?<tI~)ulFeL|j1O9rDSl30#@;FQ;mgJ``6h2Qrpf5DvOVb=< zLUx&lWBw^$nZmV!OnSfuC*WW2!My|t*mv?09*1E=>T7+}=+;47+V*iS8(Kkb--UkR zl$0OSsIG<*JkL8Pu-*S1O#OaXK|5sUt*)M6t<&jF37T^lb2o(kh#VUmdb~cAC9lM? zbkhwVb32X?>y1CU;1WLlAH|~+n2RCP@xW%Ob7@)l3HQ*ay`CG<SUD=Di)yEDAe1n# z81uz(F#h<j@967~$u=u!JP@(L0VY%xAH+YO>x)`25K`z<Z1}DqJrAlF3aKSn%Rjah z+cFdk!osMB1I8HtI*;4-$DZFjzAJkHuLMH=l-Q_bnBROvb`tefqDNMjMJDyyA6&IJ z#vkzvcEHvj^IuR5HKaKHNaX%NG85!&MqRf!WOe;rK&NMQZ@k2hc$xmlI8RGCQP*3s zCzR?FEq*Ar;$w?{oSZF3_<rA^81#h8j2Wq|`ao*;znV!^Sq<+s6q+_vNM!Y!rFtrq zh?0(+NIXhUG&V@Z8l@kMN@A{{gaF8<2xG9AT=g}YS$Be4lm_9YDM48$JXwdK=&Ha> z+r&&ccBb<{W;I~$4Nb(38S@3QJcC0Z%g022W=D(jNr+SaBaoWQ)h>!0z$$`M1i<Sj zF~TtP)g~*P9Fro?#zI-~n0ZAlBcW4zr#qjh<!XCDmf07hQq`b-@?RlcwO|i54YKU5 z`ICa;g;WPdEqa_XenN_UlyP`0Hwl&}931o-Jjkr4r5NP%Eh^?e$*<$2`*!WlwaF9u zrc6TaRnOdm<)P1a`huDB<Pn_n!Hlz?5;=P%NSHx1Rzft)h$WXYKu*)s!!2`3gK1I; zMHl;uA_*t6VzGR@v(Brg^FND|BxEcr(4#-edMgm0a;$fSv&^zRj0Zry3j+p=50aIl zy$$>l$wUHh#z4{G+y0cn^AEQw1uGOnnTUMDsw@fc3K0#goYRHwy9!{&PZ(7Gmp6Zj zHobU$YfyxhZ{*=I2GV1JM{#_w6C&cWa0Vs0#<y!R36)<5>#lE>`>&doKY|O=_Q6QI z-$!&qV%kf_J_rc}g7&oG-4?RXIxp5SO~BD#3RT7N_8s0*bJ>dxENyP>!W*=mQDdAB z_~VztPMXot03SmPyH0nlvTds&!KCH+C2-Cd&ALLYjdY27_zQj6K!NB}<-x770FVCH z33(#ncxK7rtXIoqW#mL$Y_yirV3I=ewnEXPD925-2#_HRXiDt9{HfUwG9mlAuAsUh zRn)e-$sML|E+=Uz;TBqdh$`xlcD+*_q^G)W5K%=_wm=F$EvDTgxba{HZp5UEc1_WW zMZ+nl<8pkCY54NbFDWdU^!Wb{FdhXpOh5tJ)i|Zz6I$KgDV+h=`uqRG>!k~I@r1hq ztJR*eqD<Rw_A-;6_E-BlxskvQp0GfWPzMo=*nNh-5pmZPe0~p(N>SZtxGn&LrtJ_q zi5T;ggubT;&!^YUn-0G|Z){ZucCgqU9yDAJZ`k>1<kB_7wet!iDI=&VU1yTO^m&{s z4d394x%63izu2y>3J@SdzHC!^mUqh#AjC+^uxe~Y=Yka-_u>hFU;{#dkb2@Z;nf@Z z8Tk5T4d*|A!*|6F_En{4z%DLE^goRg&&Ir^MWJ;N^FMp41Fu^{Z_5BI2x1xd_N9Bl z6@p~%{tpsANHH4KsQ9zz7ghmXcR-K|xSWI_3GCFWv2<zq7rwk#Qlj;>5Fuc^nm7?a z$Gk|KavN^7f`UIgc8ev71oeS4IZBEL?C;@W|NgZZ9hpCmcTLBC+c|%uG~=9<&fz`u zo1(SC$BXfq3nzPtEZcysDbe_g+Ov>vS{M=HL&Im1zqKCf`gaItc;_$Xag!B{>L8)1 zxmKwPRm6oBx2yKuBvI<PHgw)?FT~3WGv*^SU6Jz@3*r1B<_rsa4l)kQ=-WdvBW|Ml z#uVkfa$?J7y~|H<)O!Ex^LI=rMpB|ZwK*GFfF$qi>!o>CcM^H6b6%_jm${qbyiUFl zxY#~Waierel&uPb1nY}{6aEmb?<SKncWoeONh(C37C^HbaMi6gqpMai5b5O$ug~Iu zl_AITcp<+bNc#OqI<D`!<l7Fi<Re-A75hm}TesWto($ZM(0)VIu1~?+@R|%spzgJd z&XOe*!#cV5oNw@Y)7RJ9(1QQ4kCmX5f7tihTMa=&k|`JD^M2|l>@5EMY4SIrQtH~f zPg|jJZkMd;+apILF~p@v^G>CVvz`P|fb<SVolzr$IR`|w51flkax1@<_X=El*^j&W z5uGSjsXJ0PE{+rAU3$BLzo&%}Ac;CbzS@#-Q>@=#3hKe47bjrJ?Cw$*;~_G_%kV=g zIaJo+^pc;P{(6?#w}Abx)&65Pj!>v_4t3i^>R;nsiPNppBVV`JPtE19mE@rp(|<j$ z!qUHQbbK}p{$cDcook^tZ%(2AYT5;obDq8V_u_>qen(U<{W~8pdD`7j_&M3^2T=eL zp~m`F*?ogNlD4CCW>da<OQjxX!-m_j;lQd$YdRbwX_li^H<l$JWpWa!T|b@+cdI5R zc9N6;Y10^Ws&>N!mttROmaEe^m01M@LB`*?tGKq<^p1<<JhbCBAQRVYi0M#>1wY4R zfOin@?wJ<j@RQd9K?r4=2=;K?AWbZOaXllD7k(<!xvKKhI;HLs#Db3!##?5)!Ii3w z6l!@iXkTPpJ*D@*!!CR$O@%g7IOz|eN$orLR<-i2hqA`f+&g$Y{|q0qRe$0__)>Pd zv7}Cj1n{Dj!O{o|YmU1EAeWECZ?BP-cdnt4VtbdqU0&=YrN-aO7<zT&4og<p=*-gA ze`EAru<)>8AT@&z>6+j^19B38V>0T>pP2bKYpk(GhqPwWtzp8mmM?NGZtVR1<E9$s zONGoStl7vH8m*#e7o-ydSwiN>6}v{Q93rjSMLZ~5^4QPiECIr!oOIEc2@V;oLZ*`` zSHeiyaOO``KG;%kEo-$)9b?G0>M`;le4y3~Q5_-M5bi!9hFwv8lnz?S!1z}PX_tg- zQ$(mPY9P50#%#+E<jsW??f+iRbLMNd=8)o};YfO3+&8#Nm*5P5cOhopaz^ynf+~kR z65Q!ulGfOY2--?X9Y5p?b?2gR$s!X{Xp;AaRu{KMt%ZrQVpOaLxeb%f{Lji2lL52k znu^l;`cUgO0^W-0CEgQi4HchrIV>|PwgmCQy63bc#LO*K@JT>hf`laQFiEytr4X7k zd~$}>y*FK4wSjv0+$D^+luFCx$5V%i1ty!oK&#_68@6hfDN8tx?kMSbRnX_s4zT+< zBv}-Did6$;n1V{jlN*}p_d-22X;sY__6fnHJGK{OWHzbzAGU9peJJkO3oiMrLkv9& zvU!EBOkd`s1zc8lnbbMDZX;n(PU7Y&*V8yCWjifhTK><KJF=<pf^Q6kTCemBwG*@$ zd9}84dTHjhMmsc`+HWvcH3<%he-eo6ylBa45SYTA^td|x{a#gAunj344n;mc0dq|t z`uNplDF(}W6f342W+uEydf=Z!s!SX%zH%+u9wb1PkM6=z%tp0=3RT9`<Y`igv2{Y) zu3Se&xFIW|(hz?%R+#i2`<hR|UUm&XDny0KwMnr*k&N$iA!jZYDYYUe-+7PmWwAz% zCw~34Th8{~dF;oN7OXWZ!oXaR;j(-pWx#W}@!>d3`z<bTQkF7keNhvB^4m@OV`jf( z-xZ1^duIM?qiykP4QH$$r5^burusyLy(2olSC-^OAODK=Bds~hc-PRCL-#-$1VUtu ztN*nw?DT<on-p2nGTpVat4t6sz*0LgjtmeN(fH#)c6};AV{2J9WI<r!699jp@>pYa zb2w~k{9(O;KCx)+h|-iKt<ON$Lx2|H4nHqTBuo8KiO%=?gHaOTW~syJ$4;nSl=!f} z(LK!GVM!<R`Msa}1`p9N*+`<Di2`7%+7Z*4Qj8L&(+WR!63gUyzYrjc?I|;*D~NJh zl8w<BYPO2okg|mVn|CsZ4?L7cFUs6G4W>prlLn3wETJn{+ZM$Xcr?X2c~?cso+Gk< z=6(b-F3`NAxPoSf0EE`vQ(jK_=&c4i!j?0G?WU{;)sj(jLxqntN!zRCbORl!ox&sz zPO1A6{R?F{ON%4V5(=A`EP}BQ*9TVt#QXGtxK@p+6Zv&?48wI@=iKy(8W?vam(1xd zt*$$4EZ~Dn%t@E~;ucEJ1hC8?2A&ofqHl(sCoF-AbY3njJ$TZUmZ_SD#|aPOZM5>{ zO6tj?RpO^`(m)oyfsU^aR5@1`g43=hixNnDWgXvG6irkqE<F+I5L93DQ{RESd2$z` zvV6_F<+Gc5(mnc{+noDJj0|*i<C3`Rl-WozSJ7M5-E8$fSGkmYo}y$qQ#_gBVr^`W zx<qp_P!<+q_>1@=lgC6nGiu*9Y`!`IIgImo^tYi1%M7)1$eQfm*#(?7vkwPy*RV?f zyOV`LQFxNJ-tNHJ4z#hv$4iTg?gp9F@7-ID9@6ui-P?fwDLrx51>e0eGE*ZZsGNr| z0c)y}VJ3`bdYoxPwz*!tQf2c*Y$$V0mT^(qD$Ck-KfDuFhfL;W%F-qK<eNK5lR7oA z57froBQka^T|9_1nBz84-elUYxx99s)lmAlUy*fmt_ZrqhEaGZo9PGLSCm8&k0_=K zL@R{j=-001F#?1bHhK_ZP}cfcQm1~wDI>1rcF9`c8Y))}5_l)Q%IKENn+Y9ZsP;Tt zKP1f&Z>jzmd(Aa-{F)vzciI$tr#>VF&{Dr}xs?M6-I-Upe(k+8#}@k$Aoj2@56|S_ z=2r0+$@-4_u9oXQ3hLHq=xYun9lLSQ;008VJd*`PF-d+%aH00LmG0@14|=&|td*FR zW?XMJ`3hG6=S~T?>XPa+Gin%)Kh|^4OEO1U4}c)T03wjkSaJDLllkl8s&<{XZ^X6O zdWW$g;4)h+%GRRQzKy|HWZlnh{!qq0*g>*&wGTIVA}_HI`OT#Mkh{9Wy<ekFfJ6Pz z0Skt|=DwWwsu7%kgpmCh6$R@sf6zUdaffg5#i_H0?TZJBp1^JUZ0K(tLo0KwEu!_? z&5AysiUQjOnKHfh!N$tC%!zH;iOJ6e93lI;omqH*?K!y&I=%%IW%ci69>X~4=>PuC zFq1+GotEONsZ$|UpB@M$CHm!j<$qvhwmPx&?CsZ`U%ATL5Qfo8W`ECqg#gS`QNj8= z`OJjbDeT~bLk+n$&PxDhW~?*}>dyQ1ja=m<QsVWV;u5%G)?7$;(&;MplRG@-R593> zHufnauv`9eNlwqJNEQbZ5Kl~J{H86x`(8bB<s)|1#QNJ5xB>W)%KtdsSXv#f5tksn zc-KjD$Xd$mII(<0p@jaiu<OLjjZO<&Gy0RHqepgI3{UTNS0@phFsYCfsuMD|)RE&F z{QK?Y;}fGYF=(Chiz`C!7!t!SP~nq2_>P~Av84ztTaLX9V_6VSZD3pxI-F4fv1mAG z;sP}T8}NSOX<{NFpqYA&fT(qr`~Wor8(SwJe0W0X-ZGy^$ufTcCygNj$(B3GgAtX@ zzvGH>{=BugkDaj~fBDC%%?2aChejJ5UMsb$^AKt2K%QA<=hwoKy%50xBz^*!uXO;v zg-YS2%djTW^IgESj@|JpM2Z7H=mOTb=t+yqBRkV&jL-s|$P^Iaz=H>M@K<p3DEv&t zJK%*)J_{}A5I@{+28o?T9cHHtSwsCeNDPyyLI=Z^VMG_!p&1m&)b-aoc`M;0yzXQO zTeq2wq|87Rm+7!A)Xo=As2`DyUP1M<n$oB<X~zdZwFPGScQ7kTr|q;z3lScq3r8_e z1Re~-aMddolJkEO84BSgeSlXKem@<zH%p<Bt?)+yZ8xXTQj7BB00<7yQil5tarWPb zt^ekY!J51*1J_sLK16E^L<co{g4N{Y@7-#`a|sy?k$Suc$2tMAVt3~f3!Ebyl~z<0 ziq=UyjlMK@9FDbd+b<$R@Y>GEqZuSweh(4SE{G5Du4?iTj1DY6Az~C-sK4*H;lBMS zW?}Z7oUJf$={9yP8|-Rw#xT(bI&}VeLBj{Y+-1n$9J1_YCXxwJo<rr%oDF278<!zi zHkknIa9|Lq!&eT4%Hn{_F#;<{$w98zOe!WCCD*}~dYz4&MJY`dxf-#dah81g2S4@6 z<<D3mvx<##i}%=oXE+d(3W%K+SiymteJeK0g!2UzBmd(^&GI8lA;fcF4G(USRDx`T zYa8jBP57zb1gmHGM52m_n^_1hB6yHXbm0<<7`Yq{>#s5-U}pES%io_6??kXhi`&fe z1!q_<3?XU{A@N>dIRF>2<%nu!C*+WimYr52hY6AnjWo+;mW83}(7|qS<T>*%>lNEH zbUldlS_Y6V04j>FwswzxI+}V2`^O6Buu4%cMQ4M2C1t>_Aj2;s?&r>EguHga(bH(w zwyTrSs8fnHwreGiZ^Z-mP+N$0R_6_ITO@zJs{qHe%S$xRNH}8=bQaEZmRUK5?9>`m z_L}cJ9q1|YwagT~b-ri;JFO_P&P+zn1_yaMu0Fx`d4ZJuRSH1~WebrO*!+Wcus0{v zZ~v^oEZNn(1$!E!e#M5OXOUtvMQN-g4k|i&4+@S9f+&AM;b+d`mQhl9WQ9ObEQw5D zqh)wSvg~qXI=>hiLg9e{>@rQebIlz^dP`>mc3YLK=-cn`Z8>uGEycEZE@sBync4=r zF<P3_;80s)v{-`NDnTlg@{<sr6%CTh{Jyzdg{H%3CVGdkR3ze3_JZ}cUd*Hjo*om% ztHaO`>61kwR0RL1A3paS-(o$y0)gZrjZMk~(oa8bJS~X5P}n4wB@RFB1-7um4&JP| zI$m3zCsIXJI7<$62~^hKs$3E|;_{Z_Pey0W9ALbKUz3PXOqX>p&9g|a(t1<7wr;L4 zs=ky2P7hZ1eF5`ZS+#$dcK6r!erI5>KQR*yI{v&u_Tw9DM=R+1I2!ieWNOJ?fh&3D zFzEW`v>+)&DP1-?0c?HfW7h|MlyDXdGJa)?mHA$S>eSjdw5vw+*vf4YunX?41b-UU z?dtx-jzF}JfPdC6VywY`OXbRQeDOm%*eF(W?N0sfPJc)gt4>+9IdiHgKM54D<)r43 z4UT|&-(OTNszYG2p7+=B4}c5=px@G<nGbQuLpxPA&?VAsD@*o<H#+4O`}%;X%Z(_7 zMxz#piI<MwyHiMPXWAl!xLK!W34tC3Ba`cJE@{nRRwA!M=~tHYH678-t0zOjdsYzt z4lc@+!Qx**`u=u?tCXXon-_XP&Yj&cqDa$nGd~yI3LFT22>wdGnr<p`(FN(f3`Yk7 z{LAoxj9kZZH%mTr4b@#Z3gGY9rQ}LW49LAO7OB@u<PVY)PQMJ5#5R(y_TD}!Fq;Q% z;o5!nFQ|&V*sA_oIrJaa^j_t``#Ve6H%a-d2ddtyDD3)dyD)@~939+z7hJ+WEX=%M z+m|E|JuHANR3t_I`E};jU2r=idEKZzLoG%O0o+Uk)gJPRB$JPNgMx3%!<Xq7*a%oI znaBnUmpdsOWTOi@7bsHhDs#TZ3|K~nP@Bcr{CO_r);6HMTA2)wFU$oIw0Ks5We>Vz zAPQ`R_A1hUrb*Qo+)N>pE3(RYe7?UgHE!|+P!Y<*JxYK00y$$L07BRojC`Dm7>LO4 zl)I>fFde>W!*-G6-K3czDpNp1sgjGFVo4rEk^?b*+F+XBxHkp7*a5MwfE)ysFK$Mg zF&eE+FYOhtL(PWn5P8MrtWB8O*FOFr#NTy3>vdEjbyOw_Wd1Cp1|o7@5OFAo92;x| z`wkG<zXx<=wfbE05e0#LYL;cW)KUJ<9wHmz{RDMjrb!6X?*$9vgd2oH+SP*K8Hr#r z(Us<6(C|&O=EL=td&b$jUJs5$-ZgnWW-hJQ==enx&3dp5!{SSQ<@PuI%y^}y1u1{< z1Gw}%h8@MXuNOeEf#)l2n9(*g)@Er4Y&|t4k41U|d`>(7wLC4QD3Xr`wvRZ;(uT^u z43F$PIP>(f;H*mZ$;5tN*LS;Z!3jRiM&QLgr_@8>s>6M5boCY02ST$dZRIr|@7W4! zU&oH_Ofi>Pa6!%k)QrkwsVl<R>LE$FmlvnV*1MQqxNxBAV_&edsROQ^0!H=1W>Lni zmk>-ee)uB3stG~sR3<|aD>r0v(Z4?wfp*b+K}8{#=J5CKklH5rX&p)#JVf-I9Q9n@ zOcS9EOtrOCbGxbYF2rK=nrY`PNh;PbA7V#Du*@F8^J`0+H&N#K4dPLa{M^R9Yu&JD z7oTMCU{tYqlpf_&&!Id}&=6v}<nkp2Y$VoGQb1bjZnqXH)LRxaq=V!>0yi%;yCBqb zABH58^WTkPiR{Sl9sY}u>yuGx@}qpww;f9+L9jv~{qo|<5Lw%*BsuKjpJwl!-n}g3 zGTgaiUh32JdJd{xKoaeOEH-kZ$KCBeDVYJ2jDsR8iA&qF!L#SCBYHx@UIPmS&ljto zf27m||A1GMrJK&je>($ix&uoEFBbh1mFxI0wI*YoPakgKHrK17pxBL;``w+BzE(3Z z!K=MKEuUJj!dexFqYoiwgTD#Rq_OT4$jn~nr<rbSADbTnpS8@aJ=YZEb#07-82Od? zGg`=KmDTB|0oiAMx3KxJ*|&d?)kZGDn2QRjVC0*$q<C^h>JzoE9shh@X}|D=r$0HK zjm{B-7##q=<<B=qq0}^PnhohlV%GL#f=z#4xn0-M6gsUYdy&_4(q#nP@nR9BHizZ> z|IWL#j7JxMdUq`&Bf;YZkTCNe@eVj@6k@#ySGf85nI{+uW*-{7A?yKGZ?gU=T~vd0 z?JFRc?**AiNTXn<ntX5b@~BlR=zes~KZ)h;^sbrL0ey<{F@F+v8BDs;sWx({GFA&t ze6E0fN(+R;(^2iR@TUqa15VzdWkI~cl@DB1BbQyLmDaPPj}#`_jhdLq+?&b*0N?bU z0AXm-g5SMYPuj+4pT3TQ&YLeDIj!z;G){VcdU+rFPXL?Fb9yQJ^6cRiT-`iK3;rV= z`N;oy$imC-?S(7%KNoX7gtcTJr7iPqeU#s7hwhC8nT6@SGjhc{tj`B~YyNWxe(5y3 z6Im@oi`eY@P^cIQ<pIuMyeW2(YYr-GLP%HFo0oeF3Rw;Q;Lh*tLhuG(9g{xNQ&@;r ze7_|y+w?jG{5SMYSNaR7W)41E?zI!-!{NJHEpnm&a$qmkfm6Is?Uc*M$F6>$%^8=Z zRM58y{)h2eLjucspFaYlLHEivM=X9pG9N0rzJkv-$sZqK-}hsueMi{$T3iKpp4JJ~ zE1)lkR2qYYl5hqaRc8Fbuw3o5+9%NmPfe{*-kX5)CMr1i?zpVs9j9Mj?7>Rv_#do= z%I9Gj+BARk>T=;tIk(R*M?R@O{&Y!cdp_;+%<%TLr-=_(JI2^`pK4fL;DB%NP)hCB z&nh?WDuO}ApI<!SczpVMU!one328qj3jg!ObVZtU1;*V(M{n*@v6Wz-A3q%yu8Zf# zR(I$BRLwf$Px`Fdd1E)O_5SJFIYEe!Ex3~(C#o>tOnt4zdX0*n)42f}w?2GmJ)!^s z{fGjYF6em{EfXcG5%Oea#WDx0AS-Zcv_3l*UFy{%9!i!k6yMSNh>PKlS&?-0pWVbB z+;>j<kdvMzxV!UN5V%7W54uD?e?W4z(|cc?{Q2DMC9|v<98DNC39c2nz(?)1_keoZ z4?lQbrHvz0>RTtgI+KLn)7q@bElOxKP>ZPryja6KN&kI*{d8d?;CgM3*(f;=-{f40 zmr{LXG;?qwvxhNRkJ4hO$Guxkt@ozw;zq2_D*FG>uyi_MtrWIQnG$`{x_fYuXr&9w zLECL;r1D+G&G8X->t?BZ*!0MaQ0ym<;&rNo>4L)Y3@3C+#LBlYk@^*v1J@IqLO$!c z$)dyd@w?1y>qkK11oc9$NE}ZcLT%?=wNI;08ge?g4w)w8*yveO$Q>HbWar52Swz?d z>dBRyRfC)m7%~6Mg|?&YtV<W~-neV0x5dEk3eAh>gq9gr!pQf5ibQ1nG6{|RLaIX} zb=GV5A)zFa9MVLd1R}e5Bt``JRUOM|b7#38L$m`{R5OOWkSZA?6ZXW6O4sOnXDXw@ zFBKSVht!uCN#@oS8JVb%%;`R>PG(yn<Ob#hrMpBnG9wTQ4!fZ1Dg3R0mxw5xJdy@~ zGM=OtA(;+$(7mNMn=T!VR&8mvYldZ*L^l^R=GMpf)jFk{)hs-ugVo8bLh1)(|6@9) zIHxD)c+dM_(Ri=md=DmWPc1SN=c=c@=6xF-P0%?48zo~bZMJY0Lp^`dRKWa{vfi{1 zmFE|Wb@|~Jzo6egnk53Zvy~3`O_&aKomi(MNIukV$dbP2^VsK(o|ujSJ|chsf|R?5 zO1|1*W`_%MakJnBR@f-8(|+@F`zOj+xyGjK+{{WYr|ko9S`W@+E2}%%>>YY@Fei9A zq%7Ar`p2BsP=S7T1u07KWDXuKs=i5bOl!wL)Lm|Fl6KZtwd7%X_FAOp>(E)Rj+=yQ z4A-8C)x0Y;`=i^^_npgyXAt6)U63|5Igv<_BlrxF914<EkZGRtw2n~~(u~)L!N*4L z5k2x{Lo;$aIzmTn2sy25fqplgwb~QrlzAH&9y_;ZDo|nSw_QlaEmTo0{C|qhJDRQk zjpH|w5VJw3SrL2B+SQ04_TGEeu39ylAR<;9dsahHbfIdiP*uB>s@2x2qSc|=s<!$5 z{QkNBe9pP&+|T)p=RVK-dA*H<a;{MM1HmlOxLmuYmy5|FyEYCr0@AX?Pyw7Y5hpz6 zkZJZCeEFTPrRPJ}xjM%Z;^7icUE_IHT3T3I&9#(6{N%+sI9;A9jpeyis{mQK!~hb9 zD*)dZD32I8pIM_Z^u<SH4->VYFLTMeejTJd3vc!|%fWNQgyw>5ZmX*4#dD=Xtw+{j zUYwQ-k}nC-iT4y)Q^@}zRaJrFdx4cbl~|-pS&a-fFfNg17|aNis$etX+SV<)8$_N2 zH)Y~E6Gc7Y>+q;&t)h}Cu;%~)O`^hqbH$Ym&Msx5#sMUNoQ{cvDSgkh&1)8O#@i9Q zo{U2xbCO_hK9S)4*~~lz0$i8`RX9zQXdms5+khR4XNqI4JehonIhXZ(?00Zpnace8 zfI>+&aZ#~|cGw5RrZyYlGqO(3Q%a#7-)J<m%|%Za3)tdS)rF-HY&FKWN@L3?s_^!! zH12Z{@>NPRTfOY~(;N)KK+_d0TCAdy{^Mmk{2(8id`86w6sutoY#dY2EDhnU^CACK z*>TMz4>J@8!cIaAstL2hr{%tE2TF5ZEay9mLO#yC{46De-lk!DsS^2Xt|HziV2n2n zCwc1p7|1rV?#u!beu!>Tv>6*4Tv&vIHq}tLdA6%oP5e>;I5p2|+zK#DkacSlwGynv zaI{pUo!F@Tw~$NHlI6V7?jUNUJIg4xiItWO$cpuCGSusM@wF8$sdd|&O^gM|Hnndy zf1k@;<c8{fr6L(d1Vs2Tc+I_9@Z}=<YSro|a$g3ey@mKFn;-Eq+rX&=;&lw>pCx3$ z;M+{B-)`4)X;a2kUdiQ;(9He7rV<v>G2$xO7_E>3l~1B=*>5uZgzqk0+UK$JLciba z?|{EwK0Gbp*nOrqQPh@*tN};`KC@&uRRXAZNNfy>X)wQg#3hQq1vEm<W-~i$KxZ<h zS^_u=a{{gh!us9DTt`quvR1L8%#Vnen^h=V2#UpJDagO3A(Kgn05C<Nc?B{C<pT^@ zU8s=(=CKYy@RZyaBFyMx-P=FGqZRNTQRcHR(NqoF;I@_(gs30w&M0KSbqWSm)8T{w z@H&wyX>Q?kJcdUDYskb)=Qrl}qa~F_1+wz)M?0;YWjEqOF+VW3;>OHp)uTc*J>3j* zj_0lzwTk|eP{ty3s)*}n0p8Te8>wt6z5NSVzqtDrz3aVMBXP*a1z7_wE}4ht>TzT& z*+ps{UZ-UyDj_XrSj+~J6shN~8wfK<spg#g!4re$8$<gnBMS9f>sy(J0&dOxEwK|% zXY~`tLG;?-if6WsJGa6OQP4C~;ra*guLz6KL~{qeGvGcwTu{YTia^|63xu=rhV@Ws z8=r3lYg>s+9-K4r)wBMqL2-9C_L!u{K-FIuq!7G51n~CCX=WsymnCg5ED*#>K>FmY znd8fVr^Epb#bCOZ-pYK|+R_u2IVs?{2QCfd;SXQ=J-QSfUY}%Sh`c%0Z6rPSQ%5W9 z-CVGz5QVc$b-N}uP08@uNjr(4yUhQ4<C^;S&(Z&_ids3K3>Pj?d6kF=&9^Gp?zo6d zn2KccIZg~3SLV~>wl(K*hhkp5SEW^tz>A6WVEkNLNO`W4u-Yo2zDkNNhWdzU0|B8= zQPh{PQq26@*Lm$&s))al_XKfw&N#DJZ<mPr2$0*Vqkzx6?nWs;<SdXqkfCTS8@p+Y zBu`<s_NiSJ1gX3Hi`~)$;7)*jOWzj292QD#$1_y?w)OfglfEu0dE?qay-6lMn&?45 zhIo)6^zJ&8p)wU<)=KtPPUC&73|V+iggqPVyfSs^oamidEH71g5Z$lD%C1EKaZm_Q z>C+^)G7Vh!mCyIqebu{+Q|$Jz(!f=Fwb@Z~e8Yn%MqTW4xHZi7?9QF=*O|i{wvpXK zFTFW6)i*fX2A*?AFN7#<Bk)XvXZxBZ{ZHauM2D`9>6o{`ccnf(HK@LJEJhmn$?&cb zJ``eT6?!Uizu4rGXL^{JLrE0VoEAhM_FPmnD^O}>9{8jEG(%xPMTi72R0Vfrkj01z z+C-qI_im4q9l5ekTcuC8hgFA!ZjkUL7rEDDjcKO?1{X!42m!)7yl#Q|B;ov1K(mNW zwuUj^@HxGdbcwKRmD${zU_!iK3xWus(<M0j1%<ygV7|-u*^v$EI<lJ@P`WTv!y2<9 z1qVRKGN$3FAt%~LYx8^VK6AQgFnOH?yqN^cnbZPTKUFh_9wiRUvJ$0mz`QxINd`+t z0npPJ2@QP37u@>Rn~tFl3{tzLhA%+BpG})*jmUs~nw0wLPEKfHJ!i-%Rfo!o8W}Bu znaFo%D<ic71c;l;vF0kD?O_NvebOxDdkic}7vs>~B@|8h7YZ{`S1I4s{8@A(duil- z`XJX`nR9lP0sZ{baCDY3RZS0;osoT;tIVIlNM{W{>ZgMK$dD&52y>*n!Avs<OQvM| zR%TY4UL|5pe>)l}N|rXvl*u4)-0NYbh!I^n44(FF`I0NSbsVU&5&^Kbc3IN;%`_L9 z3#g3Yu;}S9u+XM+oz|N-29&ivB9d_r?O`12Fb>?E%&!^Z(x&2M*nhfDR1S$};Ay26 zcy%+=oXm3FX*XCV5g_H6h^cf)Vxe;LV?-R0<12w<moUE3x5>%lB|yHXMUE|&Bf&bH zO$+FCnuw66W9H=N+=_O8;gNqQc2Lm0-gJv5NhY5Q5FbElEPYmvD4&qdxc=1BeG&tM z#8eJ(^>jNGGc%|@gKu>9YjwJLkny3D`oyNr5Iq=+fDwH#SbxWl{A?swfdzPIQ+{rx zEJs^YD6BQ7MfrVLS8q9ND@-fXMQYFjCM7VHQEu@gLlpmU>hI(fX>35E^5Q?PW@3|u zYXHo|!a|@ZyJehX>#2FGycPF1W1jJQz2kRZiIU~q$zo#UGf_iU>yMOgSK-IgRLfV# zWx0#bxF|TFGdfgtwAu?A^~iQWk3`XM6|TdctPLx_o2AvkLPe_<)J+R<Q`X7ifOR$? zU%n3Hb-*M6GnHAw++2M|aCVMEuf-C9jW#BUtotD-#@*lX*`YqONgF;UXN1)0w<8Y} zXxDi35W7v`Q3ej(#3sBMtbRnIK@a9UWaCgsC&a`~>~5<g43v5SEpA)r$MKR3n@l@y zR?$quhw4@mnUYojQM&wAw={vlhQO3yXQ`YQ)MhT_13;t!1|Nddc|k+?I0B@4*W)2> z+i03*RG}sNYFpsYANKFA-t<^2;>yT#2l8Bi#nf2&Wp4Jj_!!uYBzuQ$>;Yjqw<UKs zSL<RvEUH3dOV<)$t0gJVA04*#Qe^t0D$o(I8(i?Z?2DN|msL3Vq)(YuS3nIi&0fGf zppJ0>;5MFiZcsLcPYaV&)5j<2icQ)uT*gz7BnvW4=@`s~yUSvu)1OG|G=;HaxvJpR z%*O-~WqjI1FEfu3w3$eNDX00-q2OJ9*l!PV62fHd1hiWL{L!oKNGEVegDhmyxMrVE zMpaBBi)_)e6kNJq8}4*TkFI2hbdbfD81#ehWu(GX_=MSg(j|S;*;`?_eOxA=OYRb& zvddr$XAqx#{bG;fi{S0f7%MI$gOLqH)dp|Xtdqki1Y<=yDSdr)#RyjUi6-^Y)S*e6 z^($C?Rt+BPnjC9uV>*HNFoS7XCm|4iPzDj8v01MmZg_e!*sy&zLr+?=1DT%P+V6I- za;Oa*ippoCoreSyq`oS~o+wx;L!@{{UT!^jJ$p+9q#2yYyb=pzX%S7Zd&Zdq!;{pe zGMY3@FOZ8*H9r<)`qOFH4FMym=qC@U?hm7|mVq$R>h#Cl`IO{mM1r!@V~y-txX)U% zXE-_eY1dS$u|-4f+%#)hn|+p#*1&m3Tj7hVLfy-j<0C?r?+_QS`D^BUw|&U|w!d3* za)9l}(ajP^a#V4{<GVEF9(3ZG6}~rPF|C|nPLYtqlC6N1XQm7eTw_Y%uiv&Ule)(j zeV-2oKdH<v(fL;2Vo1JmR8K*BA1j=CP!hxe-Fe&Dj9KsBk74>07|GxMPzLHOTF)}( z)LA5PCE)aT`dx-rhlIuHYi%(TZ_gTKdK~t#WddwJAm7+^to9UWF5Po@nj=kF(Z9XM zHiMif=CF}Z-%#1;-@*YhjsR14I(n8kW(Kv1GM6TsFS-*>?ccaXRr3Cbye=m1m_H+- z0dP|nkupu<v!oe8BVFH6SX5_^n?~}<&I(?{D1QA0`~9yup$ver(DbAO%+OL3n+lsb z&p!tPjPq6k)M#>eD}PKJR%(WPv+|XtaQ=t_Mn=C){r+@dKwFRpOfBwBW`g6327h`k zGxy9Hhp0+{B3~<g2a9t>O6y(*d$U<K#4sMjnQq&2iC#B}gv5K#*|F{HUe%v2*xH_h z^^MDaWv_|w6k_g{&;FY3&N26$Ki|-}K$&kAG%a-FulIE%-k#(GVRzY~tP`xidguJp z$)zg@v-1rD!)wa2(D>SzVl?*?jjL)|nLNWIV{WsCrn_ds{v?zBrnq!w`|iz}lHD z$`2AY;>;2Uj6bp7^YlHR^7LnK+xS5MNnb>sJb7vn`{+ExiV&2kl_~!$UBMENy>Q2# z`kG6|BSId30~-&^T;6_4tksy=K5t|flG~=n=;{})2|{oDSN<l0%14sh%EI~A7<-W1 z9kedo$V%`h&w3Ecx8%$m4S4eTA(|^yxq@N~!~gb(-Cc6mnUi_8GQKv+={vH!2b@ff zWGppLKI%H|R`IbQzbj@I=KvUlc1bm1t1)1)CwX`)Y0x*Gw4FGzQj{C48}RXh(G#j~ z@BVAqJMdxFg6Y{<F~dQQL1ZhwG^IxkCUb#g8pD~U@W_84wi1~2*Yq<@0JQ`-`N4`_ zKLg_1Q~6C)MuS1@*}pE3kK=ac^~tt2;Lt^a@-BDy&O72##!5W13NVqSJfF!SruX#~ zek08^>nnr{=IlOUDh-kAQ?o^^g&PzAFM`NyZ++xCIx-272ArQVzJ9p#W2D42gnKSS zov4>P(}jr|>Ae~Dhmp<l^z2Olq-K53m69D?+|k`&;dO!(Pv)@(=c*vVagu2HWVL}2 zVEiS+a$<Z#XL`FzbYk1xDi4;q5gLWBh<YfE`B_7iimtp|oDKDUJQGGIJM#dWLY9k9 z)}Fkd;wTI0T@O7~#C?MSKaHVp;>d{%z`7$jci!CKCyF3C!|NOnznM#anGbY_A<wc4 zo3ynyvdWrRR=*9&!YMO{Z1Zn<?sez0_gz-MvCYfRZH<Gdp&3lNBeH^ts(5t9O+!vA z*YE>Nh}I2elilSPrP<~*22~speJi{Bd(kMh+5z`<QaaP(E5k(>NKZW3VmIT03*^7p z1xkLST@(b<6{CHbtnu)>G2f3#;0Na75%=%!ShSnpvajC|<nA=Xg;@rQ7tD4k-`^_6 z`xgu7;Vq00Z@E^U_uX46)A%1;DoCNqp(FUW3fYjXRtJdkLu+~jSzUj-NEQ&b9~JsF z)mwh$$m|=qDBc10SUyUiio_hG30x8Zf|>TCv*it2FYqZkM3oK-T00ajUo2#%@ZY;S zhb+hpUMqQU#w#}@OWK2h`U?aHzSmJt=q#cw6@;z<0OtX-hDH6sUr{_8lNmLVU_#zY zAawArh2}9cEaWZyi&NM9HaEK|@g8w2DzWN6)*Gnfs&|RLzjt$G^0#*qYcG+Xu0#C( z)3|+!H&9A&l>q>c)y009v+>-_rl1&n6b&hLmXeutE`q!)guZ+E51+~x{<<+)43Gfa zOaqh556gYx87cgDI~#uZ6@l8$?G||;A}@)r>ZD{Yk**M&RBQ~p-Dy;>4{In@=0&M6 z%>G{BWjD=C%+tl7k9qQ~?A-5}ftUVxS0p%mm3}T9aBlc4L-*A4ONmxYi5Yi2mmO1y z<Q0Z)i@&PG4(23>;4mJkd@qrthfv7h;zS7^xeFgsH(!wP>+;vOt#8^Q*%_A(w?F(d zy9zV0E;x;(ADT`=f=@I)n}^jSUq!ILd_;e&56fgOlgdv=aRHXf_QnfsU!40(|4aDd z3ecShEo=aIF?0?|U{bD<Y7!tMoD$p!>1S+2Et;Z4pJt|k5qYNyZZIP=%uId(&I8Vd z@@QoruHy+N0EdR6y0|Sck$LX?V+)*W9jz2f7xx=ST>%x#TO*2vXfl$;g=}>|4!8pe zva?3D=lxa=PKTbo5E{@le>;tljZK-nT!<dM59LP>9X<*GwKbjlg!ni|aqs3l+Y!F5 zLST@0qsGdUfmi9|j0m%-%}&vbLJ+Uvb@@cR>idaOCI6XwiT-v{Y`pSO?TP9k(?}$> z)F$ct$HfQUPp=CX6=R|8m$zo_Cu@FLtVb(Fecfhx^LF%xnDv8{#3^ZsTP6<uv!)T_ z1ghc1wRYv7WH*}%D4-^Z-DS5?Jg7<d9`^&_LW;Y8-QJP=d?j*Q{J$qZ%VleOjjFI) z_-E?&2Ip&I?PHs?qC|j~&jJX^pkN0FIyQ3o!+M6`fiss^iHr-}GvBh@(PF_Uz}*~d zjP)^(=Q;Ad2JV(Z$clq~&=$fNX?|XbAJ3~PhFq@o1$S?jt`wN7F4u>r;fT~Cdpp;L z5@)}PhEjLgSfj*!qd9nvh-E1>|FbY2o#Rr;2YX}C)Zt9Ymeyvvna5U;emlvT^3&le zge^0Nc&T9LeX4KW$WAJ2)7~N;Y9#TR5cyap&`=MB;EM<Ow7H0iVxCLM#_=u$TabFQ zf(<WXm_*22b4DypFPMQbKYwu42jiGm61FZ1Ay*{h(~t{DdzG{m|A6XZaRGeU3yfey zi3pW3E%c>d)j?!ESou!pyL3VNgYK<D_ejHA^pLyduPlFNH+En+D{e_}&dOjiaYr{@ z?v>V~%$kBe+z(2d60l`Ri$)aOy<M9t4B8(JkdFm5?eCg_o?x4?Gm>Nx*?OE1Vgy8z zF94mSGu^!dHOB%If+61;PV3(;jG<1|QNKJu&w4WN4oZKM<<0BKd1eY;{-(F%?|<Lf zwF-cTJy@`}zi(5x=yWsgm8;h5k1Dqe;m#%hBFj!*ma)GzO|8(EfH6g29T=wY9MX(H ze62L@MmJtEH!}>51~Fq*ei_$ezbOI`acX#ojXY9xiyg+cx*WodKUX1X6<h9)NC~UB zhspHdDFE@9Fp?Qyu+#D|h?RP6`Te=T&rYIN(#mKc@8ZU0uxqRSqk$KGb2JdhW`wZS zx6vEB{K62wEp^@I3-0K(|E+<at1<5ee$_*`$X~h&{BTH;`J^eb<c7JK=%%-m{@<l^ zoqo(IdZ7N#cco@L{rIgl$@>ck31SVVF`$&wSUivng1a;(3`Mj&2MJYB>qu}^&Jb8b zGU@IPok>?FqJ%aI_f3Y+bY`bYd5E&Q?+%|GRwk)di?Zj7^$Ms`jJStH&m`|Y6#=V| zF+wQL=W$O_(blY=FevV--4Q8_N{(H%AFCzqS$n2@Jl=T?b+&K!nNqq+o}a}G=kwqP z2H9hIp&nv_^wr%_&EdH$?mYia^*L3Y&|Cyz7JTw`_xVMzDkc5sHV;#?1ncyNd=d^2 z<8IYZ1cAj6YT^=dA>-zLT;#y1fT9(|dCkTw%xsdofOg1)eVuAai~PEz^LX`FIP!Ys zapCoD{81BG?`28vnuJpFp1J(v!?M0PY}PJ=iN{SQ)&1mm)l*$h{*D`GK@%&K?}ki= z`KeV^?os}Aj0@O#)WWN!u?U<DLBGAtP&NSe0RFQxb3^hH5S**|G2}(^=J&FpsSkmh zM?wmn1@43U6<CWOR&Vt-08ay{i-P;JS(t@9d}dy7VE22@%HIWuVHVndi#(hejpRC% zu#BlWJ!vAlvcvg>DPXwD*Z%NXfEN&TXV@-uzG_qbj?da1EAGOYeCET_0v+4aE*p`A zpX$wKp0f7dV*mt6C=d&im1X11WIR<9TF-)a>EzK!PIZ*J0?f|91;!-44w|i(bzjBr zFLn*b<%vE;+Fq=rbo~oIZ@VPt{b%BJbLYrqYvI$IbJmU|-T<<R0PO0AUvET2f|zgw zh6l5+@TTIxLY~|u-H*#J(tl=djDIv<30bJ@4YG{{jm*_NEqhv*?lUVxli~;81|iHZ z5hBLqFQ^hGNgCb5!iraN?_LN3;pFk%U>R5Mm|JOe*zA23Ad0h2>U;QhXVY<rsm3Io z!j?GFH!7@@I2rc#dt|fWD@(G)a~;}3uZc683b7Sf*MZdMcQEt2UG?dGM`lA4bnHK0 zoC{lL5YrlBS)6u$Juy><+NM6310#RB__BUs>Sdo}wM5iqKK#k)tqX!k;qV(wpC9lT zgQ%RKP8OJS3J=h;FcA~lw=TG)^<3wzimaPETu`%q;HuI6NR0TqOlm<#^>HEZU{0?+ zk_+H-gyH!gQ*MQJi>fHf-RS%DUMYkB!J$Wu;YkZz{;OkutAT&1Cl}{`C~>%3`FFPh zx$^w}$tc6Hi4+O0dJ^9-8qd5NT+SM?Ybdr-E2KD<*Br22-hUtX7(tF@ZFi?TI0yg> zLIUVHKJzXJnDwKDdb4@NzWtr(In_n3D*r=8Fg9(LEn8LRfDPzH1q7pwaniO2AH5lL zm+lJ1?0)7dvM?b6di>|FlP2K465j{o-$Y@nr9OrE>#nYNZS}?DFElure6l_RM9%0> z*OG%1f@!bjJ68`rUwtZ=?Ok%d2(u7G@~M4d;Of=meyHKuoGg~x8Q;$u`87lAZ$^D} zEb|<Dg}gkWxWY4R(Dtx1*05ZZ!CLFN?&ohexM!~eZ@C0+2yt5?9>xTg@D07G#>tvP zBm|kXr^6z@SCz5$<ALs9#h+3uq;&;(biV8=#PCOrI`joYTuxqsa=zc88(!GA!{@gM z9t8V)k3I(g;bIinCUW_BSHL>S;xF^#=GzwzLcRL}&_-X9bpLuYmHz?J%g(JSVzUOH zamz$heal>LdjDufewFp|@zdJ_AD^QV*ECU^d@A*D@0XXy;P`cvk<m!`OGWaO|2ggp zSNOlxiCoxwr(o^D!2MBr&juub3{}vhK5;w62tjB?Qu5R%DPH6ykoC_}hnAyZ5&dsz z0|8CS)u!vl;|^=w5hSFbZr{NGCg?3!MPlFa$~*mEXY=H=yqmZEvMZ7-YT(O$&w;m% z*D&`6IcwuD((#A41{1Yyy_Ym(o`RCnM=q*{{*0g5bYc1O?<NM~WkH8guFbsztNJi# zl(f`(m8OgXokU5Z8zML@V|j*$>~>f(3f1<3<*dV2iZ=(&mSJ5r3ns1qi7@xBvkp_0 zY76qmNR9>|?>9b(?REAYD#zznm|$=w2y=W&;~SgDFI!GugLty3`f}@R$nd9g<2D!q z-i5--GvI4HrP$rfTn?Fa?sQ+ioLa+>4Wc}j-)VI<FqheQov(L8aQ~%N2$iqS_iBLe zRe3aPka_X6sL;uVhyWK-neh3CFE=lS0qKX5-9#yFVp@5@v%+8q(`gE&Til2P>?avo zCyH-gsSn?jO81lY61<vNBVD;EQ->-aFE){{rNoXhuw~JCn>N~sE8Kbjqm!TP{-)v~ z3bD5e(i(!E7-vE;nTbA_shJpHOTH7rtH<u32dHh1XYz<4w^4qM{yaZ7HKP3)Lc!T- zlo=54yq~c><TeJ9zG;!iEwqI}8vuBnQ83OQQ~qYtf;7ehc^kK-f4BwSgh8Ebs>;1X z%HL?CAhb0m(5^3r0+xw?4)E2B>1S0&K=eP`T=WYt<`sDm4r99DWiWL+u>7|By}ArG z+Ic6Q$tDxPMc8aX3`p@cG9&7T23W2HY{Xev=ul?nio){(EQm}FLIegheu!I(re=jb z48i<oi3O{l(iN?m>N#R@w~bzITlxh$>C-(;7hW=^ibNvn@%8Kg;g)3a)OV1#%~ZK0 zrA}I5)V#1^XR6-mWuRwtspKgc@)RgbsR$1q_WB&?EsM2^r_^+8hyE2e^Kb^;vqz3G zomIq+mt)NV%nEMB9fLQKo7f&(4!o4KW0z^-{Mk6Tu-?Q&01|T3r_|W5X40!)IJF_$ z9r8Y))N_Tc9z%QIqCj%I7IgWf(K7RS@quw;c91z=E+DkSkTwzWz}Te@I}V5&R=@BY z;d@~!?sShg9`<2;`u*jk4_Eaaq6C<(V2pngC^{RAVXBZO#2tJP<o#O(W2v{2m~Bay z9_Z!tOV{@AXch!rrd(n#u)~IulIXHTqqi%edig95$Rmz*7kSWCE|=2cKU}j5&iq-J z@Y5Lo5-y_<5Cjj#!1#>p7~3PHNC{Zta5fe}0H6drtESB1;JivM(%~pRvIz@o%1Xli zbVbmOM&o3f@Gc9^xurLAIEdH|QN#5+d8#2r0$lkVcgELk2#p`E*FhcxHwKp52Nvg% zb);q2&8(f)b9F*0D)$5pnj@EX*{%eaZ0^R)ScH@#BdkUhK!6*nv|y#O@ji1!&E74r zEMG%N<h^FL$9oYe!4H1R1Vz=8RoO4~))#P%a!E|o;TiWEz$jj!_qS|U>^W&b|8?%; zrUP^X=(PP({6hec{suv#uikV7BWM7E0M<fhDPrFUp+PXfSLH)9Zt;}MA%2Y`BpCEr z{>?|NeN1qZs=*A1jRx?c!AI8v5G`RoX?N0PKXv#MJWiWqWCJq;0{Mm+q|x^{tnS+} zmf+u#Vl=SD5yBxOOPvD9c;is)Y|--EYN6l$6P;SHIAM@(L6vZiX$p8Sg_8OEaS(GB zFX2uJI!lu!WN&9nMU!*{j325(q&%D_>sv4s%%{MeZUtlHv7DGG^URc!KmG1tXEq=% zPcyzFsuhqkCa_l=KKbO{xa{5p{cgZl{JRl#w66Zp<aIVA&HuqzSU|m4Jd!{bupF<; zzXg&PE7%Hkqwg7$#YT-8ojpie=Nd0otU9ONB4T6*D;3z@ilk2D^=yoD>OTj96|O~N zh6Er1e~SlpvrLp7Om#@}AyE4yB6$6l=t#M0i*I9yN$XN=<+S9v(#6yTv)B+kY;LW^ zM7ro%5(ETms%c_*>b1~x@+lQ7CCk^86ty2D9_pBgEwm%u41IecY2>5VC4(dJE{}#n zxBcaPMTU6Xy;!Sc6!D%<?d=tTw><|j)TTI7NF4>$6M}o?cb{Za=CCUm&qiCV@KFfC z{LnErF}k(2BWxGc$aqaDe(W{g1Wfbe1F!2Cx2xickwl}%EMc*z<HN=6n$HBU17ivo zdyugW{p7y;7+b)#kgtnnPYWYIfBp=9F46=y{|CN29IyyN`hn}GwXb{_+gk%EqZwSH zOk?FCb?Llbye2!iC~5SMoZ!ojg8m>duU6W~GjS<g^<>gBwVlhDlx_T-X&<9?=fQC7 zR;7|*lmFX$RzFImF~v%;6y6g?+(vY(pJ$Y0_cQa_^zG%lU~Hf%QaP~uBX+h03_+qx zBd=~N2epP77F!&a2F(XIgU?1q8ezGlh)-0%3QxXs1`V5xS|X&S@e*iyu>3(ll>WJp z>v>a1>uQ&#%3#<efTtP>G6sV3*ksUYQ^%JLgKuI^JPjad9{qfVua=_H97l~K9(6E! z^xGGsKMO>)XbiM=J$9PhML^+0q1H}qdt?69{4j-!gc>$L{?8%9)RF@8IYXfh(8B3q z`1)wk5hViyFYuo5GlrCV0@SxWyH!_HKgkWYPbmZP^U(l)a)z!!{Fhl4BviZDiS1vM zJCG&bY@rBmUAYkET}7*rdi0qmd1NnIJm%W4MP#NLw~xoj$gGw@1N7kbj=zX#m5fM0 zP;F5gtkI}Kb@;(ZlB>8md_+o<xLM!A{PJ5#93M4}C1A9oI46_a-00$^*ZW-MLpbN~ zM(m3CfpH4n5%|Q*yL#6>7I)pxcppXVYYzz0V>gQ=E-qg(98tjp3)d{Rfmi9@9mL-D z1*fHd`W`<mZur>L!cD@)=c_Sw$-sPsA*$S}_iiQo^noOC(Lf!ej*c$0qu0flet2%y znv)Rm(16LQItMC)BfqPBQy=*7z$MZmJUZ?lBBc&bv^WpgAOM~0+oAf^CR+0C4g0kx z_1c%QLwO1T-QNR+e1D#gn{W_}np1PU8}BF<67v{xVkh3tDIonRGt#Mk3jG+fp2Gl# zQ19VV2Yx&s%X>A>w##wOVNBpbYs6^KX>|F>A~3|PY9`VyzAE;L@53YC!59OiGV58a zlgToEE(+ntHx-ofihpuGT9X*`+*lxnq}u+y0e&thb}v3RBn7z_Bybo?|K7D5a+4UK z`uO}gvoWuR6J9ZI3-hrBYVd8KS<^81O~KH+KrL4b>K7riqSX6k$>w*wFB>O}JuqzQ zzz28HOhdi$j*Z7I6G>AU){G}7pzOis!Rcds(CY;AfFT!w@LsbxL6ebFyMkn>_VVYe zctPz|na2_C)q--8-dmBMa*S-8d`;_`^fHezyF%`N=5g+MSQ>9rYb5DICq^jB{Dn%$ zF5Jw&EAz##!qxNNq4_yw*oW;+LDIiu$VOEjzbQt<`=#IWnRx9P31h~jDQr|g!a+R# z?yqk~Basb13k*-@3pRZ#)>V|SjUhpMI<hij7Exv5fv;a{M<*G_CeW?jNfxyob)<!j z;t}m9=D?r%TIbQS?&IGLT4t?B##7A#=@Yv-TdB7mnXGkS$Okg(iRM_>`zCzNVzQUI zh@wr~Kx{asTRjLO@v*e?@PQ8eXF@$bIr;gO*ZhN-4}B~^k|Q<7SKX5n`aVCa53FqG zPJXg(T4g_ax6kOYEaY|0Gwb}w@cVx>{?$Bq*Sl46oWXw2y~&Nk-C<A+J33;mbE#{h z`}d8W5G?S6d$+rI+HZYd`tOsj=3K33#&OHnlE>$Tt_H^4NX&B?voPV`P2q@3zl<mL z?TgE5{qzg=yxrCnP#-a(<YkDnKinU`WPa5kDsiB!j%MBUf`QOrO>f!1nFDrrXrIWt z^&+xa-nhd0uibN!&4=fsJGTwI9D-ow^MSgU4rcChjI2;HxTt^p>4npeTdlogZ9dY# zFRgtx)!@^8llqpL`u@(dM47?d?vMDZ^Iw97`aIs`7>(s=r*h~8{ar}9|2s_X3FfHx zWM3i3G{s`UIc4(qP~WpY$gi0}#;jx(yXYJWN6*<m1F0ro#@hakolRU@)gKNKcK`5Z zCu}MmqFZ!h@6ByupVOvu+_#;%=E!8oocV)Y^BfmYJ~sB#EVc<(HfsIY;r-SL{=I$Q zk<w^QONEhwaaQ-`4>y1N{dKUYq!YE11AIVwK|e}WTTG7LFXQtT>GO1>w{-g1HEU3E zGXn%jYl88rCn%?((`-3-7wT=0R1!Bc1`?HtYLVjA4wUBu>aaJUnzA0s1qe_sBRD@C z21S9(pis0twxHNZK}`g$=e4H-A7N0l1rHyNfHEL3E;d3Fvow}Ljn#E3c+8Ktu1Q|C zo)20F)LHR-Uei&j9fr6IqUF~M?$Jsw?VVfjyAtV{!685K!-dx3l@TFYc@s7kF<QeC zD3H<=Mer%RNr6h@*&BJ5mbN@IK|)#yvw{gx>jWO1+GCg6+WSZz%(#o)hD9zL;Xhvb zxit-7jj8SERpiopzcgry_nF9>J?O8DF&Kw)=TI3120T^`f)WNvUs!5`>Xl}n6tt#G z-)=!pOg2;^l2Br;`(kDd?b5o)C-+AfknMS!;Pu8ixbCcQyWEL@tQd>vey}R^>%^{M z8f*-vou(r$J<1l+SLRg!J&TvJn-eeVT|Hy=MSx1?zTUYqtCd4#SbtW~lE-C{`L>Rn z_K%I`C;4QUjoUIue*d!gdFaXb#oC!+)bM!_x}feq05&Ve0A(RO)9gZ7QJGY^Y(=>| zSE2@b;ZR!IeIGmAy}UyRU@#kN-()`ywr%anqr+Q+jfbq_9@?l}z)wV)Wg**b$K4_Z zcwT$Ny(xL^mHLlo$tRP&a2)ID=U^@UzDn8{m{A2#Ml!t!bXle4Vx8ih%yytaRhE18 zUw>%Rz;?o6NIfqoYC$5ZEi(pn5u~8pn%&+?F1~MpkY3CdLXbVXS#F2hGiE2L>aa(k z4(taN4HIk<e!a}bx0~LKi0fY)o+ul2&HBf;O))xGv0Z4X&;P#Ik#ye$Xg?yaMBTal za_hd+`(N7RMFCTrim;$7@19go27_+>5$F;%+^`Q`))A?e=`-d}0CMCW&^ChraebUu z%YFoGGdDZ5VunQVJUg5wCB_5Pn}qTK^y^Y9$__6U-m5>tmx3srwRq@o@WF^`Xu?#U zq_9AVfU{Tiw^3od(BYWGt?KA;_tW;=!Be0-Xh!#g(9sMh{LS~WGdTsb_o<HLFQm@3 z<=Y@Zo|{K=7tVMdwY%n3hSXhZxDdN`LCRB3^OjDR>5T>U@;X+Pl=XoO7<X`3MsK`n zJYaWA`qQI!eB?^F?xpnNc6QFIhaXA1K?z1vTE59|(?9EbE9J&s#Jw5rO4a#xOYT1r z!vC>r%r0n#b2ib-D#AuHjrS+j%_9|;i&xpW)Ru;DAvG#QhEqS#9E&r+uiF+q5UvY1 z#+ZTi+%g9ba2EsCCh2*M+hdQHYHjrMkjPiJ$LeK&;Ca58+C&sCJA5>*(@v8ScdQ8& z30jkY>$g3>R`jiCvRJA+FA8%JWh(^kSu#?(#+m1f*y0=4Dw^!s_UfCPDw{GwbUqG2 zJ&a*y{>Cd{h_wW)<zXyc{uTBCvtnoMd=3AO^pgVefh0ZL9HI{Qv8|P~m%KeZ3NC;O zY=@KZ)q>a@sft(30Tli#>HjU5n9kAeM;3i^7dCH(Gc5+11B5N#d*z&PS*kxpW=k<~ z+1#6c8pt3dug{b#rUW*+Hdm94`hRfUG|eii&u)O3j1NxM52GX<*m~<;N`o?us@TV` zb1+9=s4;CvE;FF(RsA@pe$WrH#Fi1d159{M4=yP2q2Abuagni2NKnqvf}pmi>a1+9 zYN6ErEyb*5n=E}q9cRfdwr{E3Tw{c^QEl-^N4qd6q!_94QOsz`c<4n(cruT8VBjup zHr)e9EP^cITCyJ%q(oc4so&6KCUWOay%dXuR1a<@Vt?3>3e+Ub?B*Jk#S3@Bh43%) zZ1{r<Y8Ro`Mq^9N+k>hV>=5^Sc|N*~yE#2NY$_M?4GLP?HF)^L!Td$6>8#>Dzg??B z_0?4ijd=&roAeNIg)m7Y4I`TvMi!Jz#8~6*RUQY0mZnOUI-kz^!2;Su(>*rJsg6$m ze;%)p5l|ZR1-Pqs;vv11Kg}iJNfO@a^%LICwvvNz-@CL53znwh5MEBTP3wb1>~%$u z@1Swf&Ffs)4#oSd$gbtS!O(W3R@}D1k-rPBhWkPAH@TCACF+<RF{LO?kWJ0*<&@+% zwexXxL6t_<4v_ng;(S|zLV8}A7(iI>Hym91z3TlR{Vc7>{I1Cu$s!m13waj*@{ZXn z)uQq_Gxf8*yCe%)ew}pnp|xsJAGME#GH$Ock0v4w6(Jj!J+GoFEUJhaC-W5+wiQiF z@T3b2!-8InCHxzobh9zfp<7Cirw8({F?a-siSUn`Iz``Tf4bHEnbcp%83EL#;F7`4 z58NEbd<<eVHhIN$>0%9RF;#c)8~UlQk$bkEunU6k)UwJ^8Vh{n&vz+GA|sb!8n^_h zN6j{cT5Vz#Dk1IP{T<!1gWxJ1(hAXTrzkne1JAue8P5=NZ-My=MQLoc9;e{BUs?s9 zS%WJA9pyC>Qs8^FWs2O7M(g}aCM?%16xW<TL?+BN`Ba%-+27&82=ry(1(;WbJZBzb z7OR?rz6IC>Z)UF_)mX)qXV%&PHX=mCiRk^n%HU-ZHR|%EIpVd$-NL^Sna#^rIvbbY zL|z>feCz*M+E$Xs{wEs}q#keKJ(5Ck;c}=yuI|ucj*94|Qf}6zo_`IVCG7ET-%u6G zMkdNqEKK7k&(S&WKNKv)59Er)kFfiO{sr=zQFV!JMLcYI1KXS5b8<jazhey6M^`ff zL{~05j<s+P2(sm_p){WRQdAbp;+_lcnL3}mtWczZm{i*o<I0{s+!a=QC;05j)Zwbf z_3#5i2fXL8Dqgzq{AEp|7RW`*pmn^ZVLC)SR>*Ww)`C*w;CvsBZ*Di({>1t2<=Iui z-tPtu_deZr3bOy%ne6w=iekWOJODyUcR%!^pa}tA126t$KC^b5jy(^Y(H!e>?7DSZ zQ}{=-^S^!9hj%5pp}8vByY@GV6oBdhWQ647!LDobt{48M!V@1$R{KSzH-$~BUp{Jv zsuBje5Q$U^x{W%21pZwu13<j^`uq?7teFf5`%pxD$i~N%go%506<gPxeuD-}f+G5m z)l0L_b<dq;OgOj5bp43bvGuzZM4jK4^Y8R4;cNN90S9s0fX*sw?Bq++6u#T}^_k_* z*T3+R-#o&!{Mxx^+nC$To5y`PGLX(lX8}KnKf}XfaB=?uN*sUvd*KJAsXU7O=BsV% z<OQR5EPi&;iZkH+j}G~$cJxKn7s$i#XHyUT5ciX`KzAlAXDv*X>KY&H<ic!+{9v>J z+|cM^w)E$nkNuM<GaKOY7y0&ST~!Kb-iG}(g?%;3R4YO*{Y6a&GhD;yQ2n!Ixj*Pg zx&`n#z|s8}F5ppNk(XQ9eBsX&!@$TcEz!_xGpr&2sg4j4^#Xake_)5}UfXk2SLtvH z1SLt1+JM&HX7`^&er`0p;k3tLlK!{GMl|n+;xGwdybDiK0Dfi9K(@XZPZGhtaOZF1 z9P%tE9Ctg-53?)pXNnX;`{m8;V$Y1-d$FiI%YJtbFYu64(Del<8ypEifrL)kqtw^H z?Cq~cRuC$v4q&bJ5&Cn0l*g?df3X&zF$(}79Ws;1w8AM#lSTA&)P6X>@dWjM8fi5e z1XcxPA0nw=xOiSHIn|x=$AJW!e}0?H9RRCV@ML?IDDyBW@-pfSQpD1B>sSe(^R45V zsWcFn3-D<}=0!>FFssolb<ZJLstH#|;AcauRV!htI?p9!-gBu?Vz#g7eZ5@pQw(4O zKqR|ljEVqLl-xq|?{-ePM|N^ucH=cO5?ZVl#K?C?*AeSs7a{1y^f0+bm<9aancL#8 zSumGr5J`8+Cl7FD&<t|4Kt-T#8virHz^`8Mw_Wq`%pX{DMjclE8{7LNE@nA@_=cTK zAR7zxsr>B`p!iVfbv@AWaB4Uch^C-$U*r>**n8{(twgy{28g@>E=cWpTYHU5+;78k z6^pN2JW{1!H|1U$)x{J^uNNqG05X42YVSrhe{BKSq6-8rGnZD;@o+i{?-P2eAym0K zf!tALD_}+0L>)aSddjA@?NYC$eMQnu<<XkC63+KYvHhZu(%A+!**~a)#X{v@3?S;9 zSSz46Aa?O%x_X!2S!?cjh$th6I-{(C(gK<>0Ld8S6U~?gwOWTbP&r5e+&%=1ErC6F z-tgkW%l^Y>J4NREs$~eg9|E>{ow^OYwHE`=Noa|xKHX%t^Oe*x(7n3Fdsaf*A0x{; z%q0~GPOCG)e_}~;0A`ptF5JVZOfdQ0xEl0cY(r*w$@&76f#sw~b9eKb@fh<-k+<YL zvW9@IdZBw)b%#a-=utn%S{1>CXr%*2=_7~-TFFWjx*N+PNylHp>>;3j+_)fum5e$U zdco!l&yNlt(2@TscGpA@oX!Sj<sdkKk)Q_)YAi#bofm)*`l9s*kVb>8FhN@_9r0lO z91lClLj61&NYpVM5Gtuw-*9B00tgzjz9YH@DawF!x<ym_SO*s%M97yoCK3@X3hvc3 zBSS-O0V*EQAp=6|Ca(3M?Kb3#4n?gY<~kk*XCB*Z41)2o;m33i#yBqVJ6wz<m@i0m zlrK{P+G{J$>nfV%DBaVV>haW3Y17B+eF@X%d9N*kH|yd(TrC`IU}5;N9C;oddtMzk z1P9l;KHT(OmW7)+mcxJg#TjvfMO~Z?xjU$*plG>8H$e0h!yF)C$Zg}~&(6!U;$vfA zpadzw`1(YTmUv2ts?VJF-YbS4)miTq`=m)Aq-(h-8X<C`AqAyeHH#8h1NbJDC5phb zLgmodkUxd<H=>y$2}}!UxG@+}-pSRWA%-0a58-u=U%#|h%oJ>n*rl>0tTQ&Qv*Q^> z5qg-2veJ-Som}!8i2ZcLE`cQ;2!BQ8V0<lB%o|nG$p!EP{gJbidL6CwT2;Lm6NXmO z@U__>L`SbfYzUY@w0g?V2z#{Bl8=qMkM9j4(_0PiU!M_+gjl>2)9j*{tgjWm6uM5h zA_!(8Xe0;@v+p`EML&xO)Qrr+2ht<=fTY~lCRVj9<<8OUe(V8d7<V7WoOp4JXgr=5 z+CrVc7$jR0puuPsX;4g{c?YsHb?eky(AP$(L$STg>fzbw6(7a`8cThb+AaXaT_s#D z!(=!qZPOS7&@4;5F2lc4tf><a-{3%Jc0Cja+i`@i&*jWA4>d3c1+VFxKp>ni$5c7H z?EBcny*80FhzWFt?)soyG}Avikkl~nLx*HnLaN|!O4u=^5siPZc~7>Ce1k8W8N)(w zQuZKNT|sv?6097{qLEtO=d~s@44{N#cIi!a!V>i8YQmlF2~0Vr=$CW#G4Y~t=3a4T zA|y`inACQbY;qMJE=9+{Ewtizj*!>*$gV!*BECB8$2jOR<r25`4+o{)GOL5Lo%P2A zxjQT#>rf9`p$tEx8#)7YjPOc`y+hz&tmRli=gX)=U;aR14YKwSjKe<}ohmTRv<#+K zEYg^u7kn;e{Fxa>@SvY2xY~4UDm0455{)c(1xUf=cuWJDeSyl-xXyU}cRurQ(MJcS zMSv;2f-xn*#*@kzNo5R0Gp7HBX#Ju{O^{!>-h6ugx^0DG>Dkmvtc7xjG;Em_Nb9;U z8h^LU>M~Vyhd-6|74jY*RHz&|nvkP=jGQ`#%q}^bB{J#na5x>C948vSUq?prN1g%W zWfrJ-=1q3GI$!LW&D?*n*O@UDGDp{0hi_P;OV9Xm-#do%CfpQhab53fj9C$g_zAHn zi*oK^*{;YwgJWXjBQz80r0T9(6LMIGW6~D6B!}y)k#+3gTAm(J_1>1$2B=1oi{wgv zY5=!-`6WTrb&2xpPkTkplJeO%5wb4SGpOtM)XD~?IO|IZHvZ^4f;p65D-UhIH_OD< z?_oF?OKup6A=Z6ZqR^+4z_NmD=}JdHKpY7K#&{b0XC#H$k87L2v5n-=cRzi$+ioD1 z046^I)Q!NnS&96N?l4+?Wb&sqd-HTpu~QRS)=u}QuGkKLnhA<4psM>l^_~g7jw2|U z-r=9zW0KqfIz~F!w_WmKT0%c^e_A6`+#f)&Iw(f%(+FY7*?Y04YwCW{3H4!j2Wxt* z@QEtQw`b4ikzsAmn?w{kjbo9(6ir~+^l5m3Df0wBDbp2O|MN(Axu0o+y^+v+f3-`& zkjp9N{Ee;xiM3%755#9Gdjj5v@j)jCqE}6)w^l9vjy3JEQA*`06`Yah5<9AXPn}71 zxaiH}2W?3xJ^tSRD)U~tK2Po!&^@vKk=|#1RUMPYa&(**rYp8hsGd7}TL#1awljE- zQ2k~d>4#1pxO#n&I_^qkkFG}T^fX@pr~f#9U{W`}{EBe#1i4SW`>-6}=*UoGO+UpF zmXA&MaUAw@uqBPj#6BwMEx2E4bx_^%$c?DR5NC^=VNW&uZxtz<M#S?n!c!!{DdMAo z(9yrh_ETs0Khv*L<}@>A(_AKRSFuxspbNm1oFUWfd9lsoaod$Lsk-8>W#nj;jd!Ze zDh=s&GWFkbYifU4f(L#n_a?|(d-S89=brlFMMH$y?+91)xP1@f%r8cg)&#yYR}3_s z_y*Zh;aT-Y3<Fw`NPTq%Gj+*t=KGJ=YN+XVrPIt9#DkMdmymBw#F*I1`@Q&}GpQ&N zFGdZ+rSCio?JG|1MoRyM6bh^1h6oX<s1v>JGpHLcy55*<&f~9EprTSY>6!z5G8jbr zpNNA2HRA!2^$ODCIK|TkuCtYS{vT3u=)wHTZK+KJ+p!mWIwMIyiZQOt{iH!Ez1A9d zpD&z;l{3os+T)IbGnS0*p;jw;DPi$8wmyvQ6`r0xU(BkT{ejZ6*HCpeo?Gkv_{CLL z@EX(O1%q>I_(3`(`kJKHHOYWVPbK=hkH-*j&#Sv$j28Oqwual|VKZ;47E|7ep?!B) z!L{#zxPQw?zRC?1u|8Ym1mPO0`(MuYl9w02b)Kj<GU@X&eqZirG5&qB{f!P8@q9b( zdIMCU=Cs^5z1s7BePnJGxw-V%c4J=mCd%pe7u%uNYIwhv82nxznZA@O^1F<q#vQFp za@x|pUADn%BWJ+E*1gM&;y7Hn=~!bWJRr)Z#j(N{>`93IRr1JLZP?lV;1a4K5Y5ry zgeXt3xsfcs;|dL`;}SRcPt1dB>=x$W9MXnaNV<tSl#yOv?ULX(P0MQ9SJnfGy`-6` zO1?}R!?)djenTXV>VwPiug;bVSOcBn0<h=hrQRlxGd2Vrl=<9*U|F>srD)wn{+=i? z6K!s(xT)Rm*QFh*S}X#t$V$teWlIDcyD86}3$gje)~mH`(o8L^smh^`?^kO@ZCNDp zcSSZ_*K2&))0fTRbSq+&ROur2_33$T%_~C1VEoso_S{!mr<UnIHhf6-`ZMLQiPjG< zsD`=cEPFfl=9}#AdQIyzNdm3DW#N{6od>JkF(2Pf_jP@FN6TOpu@XWxkFxqE@v2|B z6fshw9qH9na$9;^DmY5dr~+kPC-rv0VuNJom{#&Roj9dzHTzk<Mn6xT^ZKivxeHfc z$P3^RtR%I#*a<xAP}Ez)`I~6R%Q_aZ>xLmJL=4Aen_(_jjW+B$v!WiP)J^lv&@9`T z#~Xa13^m8I?7nf3919_XE=m&mU)(T<yGrq}GuuGx8xmtQmcfwqr6i}J8Pv$zr4}u2 zMoh2Y;WE^^Had#Eyigk`6pAfpFe$MZd51TVSB+f{WX)%$bH=d6xvW)1jmmtej;$Fr z4R3$d{Glf0=iY}~1V-6iYI4m8JU=aUOf)jE28}YIVo@Q5aN!<`IL4AFZ6Xc-@s9mw zszyPw{7uyJ=IC%)o2#!tnYYrZ2U06CDjnK_CgzF=36nw#EG&Z~UVWUzoj)>+z|R;E z5r)yN0k@qQUP0>6hWk2{Y}V9f0cWXCusNBfwz)aUrkA4c43$(zN*}qt@1}GK%k1x@ ztluYw#XQa?*E`zniGRY{;k4(hZ;g|=%(NH2DH%GnF6=UYs7u5=6`C`+mr4w}_ia>& z`<FmXb*%j1n0Q(E;kfi250A&!ui=d+u$ym7Ut^@3=q$x~`bm(QVUe`1;NaV(k`ZRV z_W0y%Lz6l)t`}DZbeL!q_PS>TC3TplGbt?$KRDytZSx3u!F;|?v$pWA3;0I|e5m<- z68JTEPgg8>{TZ7B>p}a7LdUmG*qk8t8Y1qAsq3qz_;bRF$|Y3(>c?(&<&*fiVpiL~ zbF<P|y}48D(p;jTU2NAZ>zS7Dlf9<@eqRaiYW#fivGuv)pHCfSypoS@fo5!)I-CC~ z3Tk}swjl_|UAk&=Q#C*-*r3Sx{G7oR)`!0B={tXzKSm$5u!+2)MP1IRnbk45>~r(+ zd$7Wv^X3U3vdnG=4nBN<UaFzRhvE-zQPjKE=BFu!2J|-DyZWdL8~;9uuFg;W3Kr|) zR%aI%G+QxTfNL$-%v__^u5WR4mX=yTQiT(j?u#4$kEJsYhw6R*_?eBFF&H~Dmaz}n z2_em9UmE)ovQ_piMVlF82}xtmzGNpMMe?b!CP_#|ktJEnQYuB$&-c21*LD6m|C~Rb z>pIW5@8`Vl*Xura8!q;NRRz*TG{<lu@Ty9B1?rr6ALf0_QRgwcwI=(<B;2NM70%fu ztR>n1Qk9|ld_4apT$21ZZ!%;_&~A)_*8Wp8Suk^cLNGQ0f(fakH8+&UX+SW#)v5A` zpm>3Idte}5-Bo3pf(@ff<g`}=3xJB|`%{n&)wsBv7X@3J*9+q$s5oq|t2k_d<EXU{ zr{~pFC+Mo0>m`bvqqsT4qs3J5;`P|3!15&eH?3s+H+*XAJf(6<I03=n&!*j`$gOX4 z<f--}c^|R8g<Q3CQn(Wnu_HXlaPtx0ymSFLfdI}yko^q47mTIX=vX|gpkG?PXfl2i zcQu(`c$>v973inIt58s?Syf!_^NLi(kz=r{aa$Arp5z$Ou6_Be0QS#<nT*b865UR3 zA$ZwLp@L()-b54JI*G8Irt#tK;>nOpA8nf3b>C8bW$sW0V6WtHx^T^4po#C(?$7oo zLMgIZ^UM1G9u;yJkI7aJeKHeFqrUcFGVfY{UP}2~d^j+8bH3I3gb4pcAm&G%xlMz8 z{_teY#Av#rMx|37p-SQ{his2^&yJ+bXoVWIWXNww&E&OFp3(D0724mS#y!*HT9{;K z%3>YcEacc^`$vWHvQ)AJIqjuD`WxAGBM`nmnXy*^E^-v}4^G!ZbC;HDNJ;mbN!5yH z+Sg`<B&AeFaY*0OqLitsic@{l3~%A1Z<q4HVkJL|rKwfbpx54<lLE^!qibQL<14s} zhAA7<Z|Ygx%@NnFXfunLU!BrBA5O`xVl4%u6Q%{sUCt3WJG)^{b!iFW^Mia}S{xkF zXHr$2=>Ko>qA=nbj~jE;T#k3cywrdR<~;`<*G{Ni{M2GJYqSM*=1zO3foHOup9e{a ze;|nt-_^zE9c_jke$@=oS8bPIhOQ9tB`Rl!Q=Vr&O}>6#r*S5}>hqKLZ^AFK?FR0@ z?bN~Zzm_$#Ey4)3r^;tBDRK(&_=Fx|8BdcQ^0)lwEo#s<aHi`7<(cP_!SCnPjJBLw z>ocVKJn5L-bkgZAtUbz?JKCm)N5J1^oWAlnTy?_?m0KfWeCt27Tk!E8=WhQg0bb@u ze=5E#Mw>6!kH(#brhb?@rqfp`BS;~FoQ@0^Mypn7XV}IQ?8dE-ezkQzFR<pF^8U9% zvSic18{tdIU^VP-=&5Tdo5B<4#wc*PYpUAH9#<GrCzhV-eEXPEvitgU8bSub5t@75 z=8G?Oe`?6~=bZlc0@I!Xy}sUnD<Zw`$6{l2f@nX7M!H{T{%}7N-Wt{DRL)io&YK_6 zJIajjI&r|<90|rnb@p%v;es-vSIS(;3lHaN<^_gaammFg4_&iyznU<$ywhknm&$V> zLs0G>f0>!?Zdm+K-O!WiHm9!h-We)?m^ITe*_@Tsi<tBnypXE0%tzl0kF6a3Q?YDY z4I2E+hl6GPSC2+x)cSIGwzR7}Q!0|~uM4yrg`z4}0$AU-bWTNT6(*<L{Ht{GLE?u} zVr$EZQ`}!ttqXM#i(mX&Aj64^FJ!Cx4V1;LRx+TTs^Y5c7mN+I-_(UG+%z!g(rMGE zwAEUdY}LLd9W~C+<<IhX%I(PcivM?MISfQ&R|N%lhNkRlxfye)#MbDsy?>4t?^s^^ zy&P-%XQGI`TX*tWq*~pt@;$ZlU7!I}0AZiqd&)sPJ}B=P19IU7@Cx!s*R6~vtKHEH zXF~f)@T%U`Y`AuOyY;9!@+tEviGqAG_cstM>G|-~X<T?2k<P8~X=AnSdF`sa+Wv7` zw4;6otLagjJAs(9=EiweI;8W=N!GB~$*NBfA1k3+JAs{Rkoars%N!4U5I=l`+7CP3 zKJ*u7OeI0ZMuZRFV^{Ew?;p&)GT~gvb$^RI@3~%wh8PC^Hbc3Sp^}1>%6AJLmw>xq zb-|FR3rH16LZghd%~_4U{^%*wt5BK_pP3n_@tvz+>2qbE(<;*ZY?R&k<oKiG7mh#8 z!XTYougCMtDjMhkwzquF;kW(TlfjV@xI7K7sA_y{o(#kRo0f(9n;$^|pE`7faqq-P z>t4f0T2^jr%y94_CWz?B<M!2<BA1l&iqii~Ij1tg_!!K)J1176kU{g>I2tAR#6@I` zw=t@k8h7DH<$NqxrkyN4jF%WJGsS4=Olz7-Yo2lp(bp`CB+9yA`JRF8nabH{&Psvn zVSXo~(1>UaSY@_z4MTap2eRjM1KdinsiFuFA-0p0Pkm?mUUNiw!w#Uwhbt*Ila$$b zu>E$rrJ$!1i?WJ`5g4?LRr543F<2=AqECl>!-wyhvu|ytNE)AqMB)$^2(U`oi*-a7 zJPxACviYHa&Su%@5nvH59ELawDhb&-gw~3HNFB|LddHWkpHRDy$`zl&=cM8=cFbYh zP9O!jvYKuWNUCk8zq)<vU>9tl0n-{2#gE}dV_f$|IqySh%rlYLWyqm$jADSh23f`j z5jcYgE?>`KbV+hYy{Y2%1{`<7bjriBbJHfHG&CY0b_Lg;oK1s7il6(H7Eq8E^e8W6 z%>bEuYrGHLIe@Kdx#=bVxpwyYt?%HdBxHuJZLcmme8uUZsSBP+LGhh@z3j#>nD@6T zrt|@tDk@7OzX4B}#b+n+D~;ttGIM$yFGARnoXWXJby~>SX+G_h%$i7~!-|*ML?OSg zWng?DSo1vjjemlMZN$7Qc-oab0M0MK<WkKz{et3dAH_#pt>Z%!T+(p5omBc6Tx@}O zdCA8H%%{1+#{nq}oi6$KyJTLhw09w-tf!EF6-%q!w!I|)=_%0dPvzHS70|@2zvNyl z{gFalxDAs*YWcccK4z;WQlRL4CH_K@lr-m?HE`WgOy-!Ao1ZX_kMm7|LiS+sr*??5 zysGOe-#UbLw>3OYNRYgv@4j$ek(u>y`s72-2&|xnmKJ^6xkSCCyw*n(>mPLgXDNRh zM=DJZQ#oc8^Zd-#FMSmj$2Dh!V=6yei&apua?v>9&Z1bgy+O63d$p}{VyLFK&U?%S z@7qePl^Q~soZ65P{W7fJZIoj9gjwo^NwASYu<$hB%%amxrSc=n<=JZ&?U|KY1fRxn z4&@|pI8v~7jKd)4#8*UIkcOKUvo=q}Yk<~=zVHn5NGX&ELM~+Un`#!-DV0B%D#wE$ z-k)3zm2R)cYG{pJeh`U_)X2Ty7=-gd=;J6V5s*{v7<l1P6^%>?F&G~YR--~3wmD8e z6ZnIG#I5JcP4P)7x;p=98pGV3Xvq5kxl&pYJgq5SOGPkRJafnHh{u~mQ#qIUX!vp} zx}#95N(1r95;4$)nHlB?rLsBK+<h`}oQDb1QcXk@i(^^-Sc?N9294M&z*geY|6nj1 z@0+(SV{5lt;v-u=3>0+OA)*0J=lN_wE3ELwy-)&Ys=-|u!#257ZOucGWjpyI0c|QD z+SK;jG_d!z4DaKJH=Jdp=Pjl08$7;m^x?ko{(XW~$ORU~9!GR;<@huN>Bh8Me`vSe z&oAZYmB@Dc&xOYR@TheEQ8~7&vQeuFfV-o$?tH+|nXp1;SMz>X3-+-T2o46YAT+G) z2C|R|bQb|G^J2+VpmhgOoqUX-KYmoyJ^Z*k(GZ9Q19!2HInh`Uy(>N*cvS==_5iW` z@R1`PbTj~<0gwhTcjZa$V_^L;a5Cb2@^&{s+kWiW2wQIixaR+p{eJieSQ+SPKbK%J z^>GUk;J)!>6bg@(0XVu@w{9pRBF?KND!Nl2Q0a>Ak7&Wgu`mELdPDImR?v>F$i-q= z=JvEyu;hw+?SCTT#(LwJNIO$xY$c%I0mQcT*bO3FTKZhP|Em?~ZH<S?`T?_CGz|MB zlVv=@PZ7t`%X>}F^aAu=Tcd%&ADp5Q1ENfXrcvLqUr<hOfScJr1RJm^HXxv|A|sma zbVWE0V|SRzW&z1)QCHT0Bg%#v@+7AFS<jgP*QNogLSHMfFV||Y`TQV&>z7FQkN5>E zfx@02c{TtYuvdAWm+lyMl{P>}o#6?2lw52eB#sSi(oCW&UY^04iDOX_&-HSiH60AU z&Ur4njW}gARGO}MCfy*#XjtquAbEi0GkVfuP0leI84R&*>wbRn?envz;M`1r2mQP> z9(HK9IZ0(fcAj^oE2ed8_F}OUGgt)u#cPk3@2-x>I*hD#k4D%dX>m9<hYbsQ3deDc zip1F=uP|R-DIek0ME?20*?xe&aY!2{jQP?BMCUo7|Bb;U#-w%-*KizGbf^{K70-W| zDl`lu0Xsz7y0whk(O;HT^x2jJ9NqxeHX!jA%|Kxj(~)lT0FntPs}2U#!l+}w@DgB0 ze<~FT!*Ng0Iu=JbHGo5S4VU+8tiYu8-SI~#LHaxtwLO3s1E}Sbk|4NU`D^$*K;52{ z;DcjlUlvj)IDwZg^utRLq|uYy^It0w7~kiMFNe8%cU7RUr?0)c$_-zb;VWjsPPPD? z<^Ka!(?YSnUxA2pfO{L7`WO9J1ziQeP&6jM#om4cYeKlrLlgfyWdFj>&+-+HP1?=B z1xLaZR1Y~MfD~$~W=7c6`#tWz36%wC>>@P$rXrO7=F1nw^@9(+U$JFq4h(%vEMfqw z!6B82a4iO1ndiGfAG-$dVd-O2C9|ST(A90edK|~IyR$w(U(?RZPlkbD6rfK#oc3gX ze02rz{);a0fG^wpH^jy7eu(nn!g5mKQVSn(vS?k@(>tnK``k|(QG)TTp=~U{Gyee$ zg8#VIXZ(`y4;S|G7hvBL5MuKc;-1u~Ok6nVR{zTP=h{4H^9QLNC@y0j9fm2^nBSiT zV8-Z6B|~)pOjQ!gF+ZmgNn6<e3b4Ts2KWE6>d<fj9w77!pDYhnHbh7<V-fHMN<jlw zVL~=xFZzz-o4Y@IWnc>;X5Zf&u$bp7+n$-7<-5V0aq*btm0tF1o(&v5yoE-_4T!Vg zP4OQpi{CtYi7C|h&z=W3z&2|)A%L)F5=5j{#^S#he76p|<rio#_9dpvec-&zwZbQB z#iMHyUYLZ<B?58DJ`Ol-wr2kkkOVD3=}08*bKT$9`w|<3@zvHIemlwamWoAjJGfQ) zBE<VcZ6++0-3>-hr=-L5*xex9Q=gKJeH)-%4P9lsSjR$SN@86``RZ&}LqT8nZ9cn9 zE`sPU@9{jPotDJ+l(09ylw!(&l~*ORK4W|ZtYuM+6}0B8>laQm-^ZAY**#-)HL&Fp zvgO(Y61j%iY8;lVSePHdd}`V#%Rus=-r>Dg#eH@XGIn_Fz5pzQ8@v0cB!=3w(b}_9 zJw9PyIxpn|H&g?jw|@eti|B>z3ic{*&w8-xXWAkU|5bMPsH7l+-Tj1nGhuW?C3JWH z>!-$@g|3g^vu-N7%<nu5ehq5c08>A?Ma=Vx?`&TIq!xYv8aoP->(n{nr#wL3M?SLD z{MS*%4ff9{b&L&t%p4f2(?HILZXs?VM{f>*PN4sMTt>HY`bF&dQGdatI8x^J4ph)q zH1918i_@Jw(i>3<vSeY%v|%*gXYZ$&Q@0ek0eBU)3&jHzpPUXk{)C4KOJc%!x4&sP zeg!oCRIw25xSt@6Z;;mSEt<$$-orUfR`)-#_V8~XOEGlst`~C$zh7?S#=qY4><SEj zU9HmVPW`jH-)(&Yt$XrG?>}ga1nh8Pcvph&&nv5+lH*?$NBCU;*fuXrmlr^x|NT6% z^IZy{&d(*&VUO6qfq2XLL!T12q<9^`A_3q^QBt+iFpvyLil*CZ0sxo_2z6zZ%g{ME zMI58y<7544NHmY&BWiq2CI}uv*`6Snq^NUofU6Gopb9!#LudZ`nGs}Cd=7tzMjLy< zAwTjCry#8ZObT@V>i#fv_DK@fWz(bU!q<-jMK0mf+@c3jqE2JCPCvbZijzr?=j}B~ z-QPPP>-SYQ-28hM@Mv+&>W>>C)x(F%E7GVVSu)g}w4Q8~iHNvTIkkr*C}yB}yHHv< zfmc~!J2h!#5bS!nQl>g7$F<$Q#Of$_2SDbqjG+zd3<ZAbeZz52J>3_r(+By_Ov}}l zD&3d$)(reKD8R69)u~8*#Qp)*1pEvZWsp{}Jv_lUVS}8Y0Le&JfE;WB8(@^oBUi_Q zDT$|KZvjJF)c}a<ZNvdA_~UHaV=X$8a7ztG0rv2VVH2LaS>aWGe)ejbNyIF*nn`TY ziiXXkugkTW%if}BS;*)6^B*(*N!Q9w`19=uDnaWxU89f3UC!#M<P{~YUi=;9^nTG} z`0V~djT_l%;u@=|X_hL%Cz7Lv!;EL(GH0qbk^C9bdmL@&D`4pN8u~YZ*j`nFE)r*N zp;+xW0h%iet60C<5b&z39e8shK7e14R>2D@KaZOem6^v)Y+fB^Zt<JHX;2Bd4?lu4 zylQEi%$BPgOyZDu0eZtT9MH?i@-(Nr`!uAu#HXKun<Rki0~{R8l;@8&E<=E(AAq@X zV_n>T>(0q)L2aHfb4eYZI9N)D*OjdSz0>S#zdm=E%c=P-4)+Uxn$R5Lm;J6pQ-E77 zRww-pno_9|RavFmzeEb2NE9cO`|11m1<>=gVD!cK=6Qs4ju?M#dAi7-&bbEjw}<u} z5oNkbgNnz{2SzLh>zt!AjMvV&5edC9{m@d43w0NqrPtsQA|x$hqIN^6iF@L(5k<FL z#GO5V96n@<_=6ryFjf(ft`VlWzi%)WtNe9D<inHU)QJ`u7+R$??^r|+=R1+1y9hI* z$N`aa-I34w{)i-?z-n+S^$wk(Hg#Uf`^r3UzeAjmoI~*Eq=WMUp7(dpuDUfWd%<5N z404y_Dud1Hs6dtRP&B|X_9(J2*C3Zo$9vE$NRE7#*DA1f6%Um<#CmDhhCCY!f5@M9 zQL!@dy=yP&YJ6W6{;rTK?a7~nk72xx?O#kSk5qzU*^&EO&rUqM^nK+i?ccw{`sk$= z(llKf<>Lw#V3vb=sTnv|8B~wfJF!s<H6LSX6W{*rtmAUa0<{INrlG!F090K?&3?{F zdBQk>5`Jl{SFASddsaT}(r}!dVa`eVU<1rZIt=au%wCPs&YEhLQJ|QhMY4J&J#Q(8 zU$zidUKDI&svq$azz`!$nwB-!<^3Sy#E-(J4QNe|L)hK><|wsI_}I<x#7_<=5i^6g z;~6pie%U{_ANB9rMe&HI6v_;-Mb&)(YdBx_X|=s9JJc8XYv#1{oRLMDqZvo8^K%tA zd%I8)N45e3zdyg~dzP7>`YLkn*c{OVF9bFMQXRh|n$?t;zoj#8S})m6HcZs#14<!2 z(r-v1@Fz-7pe}7U%uUoxhI2xLQ%~8Ab3N8l>vl6SeLCW&``|EPse?O|v=Kn)F(71k z=bE7mOi(z24x$}a$*4{+e_3zp5j+d{YD5QD;$DURd|mbrTIX)uV|L;X9}~>y?<4Bh zqG5416CSvP;{#jtnzyOghs+X|WmVfWs)O9z7Oad?b-xXv&+0S{@k;4+*LwG)+lv8a zFtC-M{j(I*rBr?p{RLa%*p5;+1<q_+%~j*Muk7bQs~7e;BXg!QN7^Du`q4vQ&AbY` z2Df8ELXa+}W>X>vVNM6zi<z{<<tA}Nf}6dE4bLO(uAhb-d0g5{Z%GzvP?t`Ecww~e zJdD0)<qv%8G;r+|&TA~P7~#mlacHLZ@TSib@)TmKNtP|RLT!JT=Jr?uWm4TQ)?e-& zsehBU-4qt&GaNYkjA{2VTDnYS&1zZJ<?PvARRTlsN1ki;nTJW$C#6k<h0C39wx`#? z?Z$sE=R2$mJ+HL{1x+j4+g6fx(gr9)nh1VtVE65rmmXNMM`dmYx6qNCN#t{YVA}Uk zB;!eTjr|~u-pa0&L9buqQT*^;r8?c_W@|C6*$K(_as@{(gD&)6Ez<_pyWaKiCP(}; zjVaKm>cwRig?vUL-X~}<DpH~YoJ3u#^V6j@IX98mXD<ftXALA3h9J(1^~#h;Hsd^- z<_KQNi!FfC)6wUx?s36FHr^E=C|h#3a6c<;>|%f!Wk|K;6yHOh@fu~TK(`cqt43P- z-JZJJuVOhT{J*{oR9c)(<1!f%3Oaix+vsLQ@z%S6StpabHI#v=I2G%Lk#R-#gY)zl zj%FzVV4xVcdFzbwIa9s&<9nAyIhb_x=-%h@y1m4FE$`|C>nZh8MCeK#X-vM`pDS@1 zIMwo?|MNV1xZB6h>jjjAbbsB2tF5D%AGH`h%?RNI%y+9D9{tLb*t`@z@#vd#&N)BF zy^R0v1<4XUQYa<8k4Q*73+#1Q5RYR4+}`2pcbsy0rC&dIyF47jexYbP)rA}8(uz5C zgDm!MRMDDG+nJuXBsy?%PSaKd1XYW0JMn(r+&(;*uXlD23B4mEMgU`405Hw!q|*NW zd6Ty#p2Q;qX!V<&5YZOtFL;yMz-WeW8#<}uYx_Ls^-CjXG7cj+^w)(JBh?NSf%3RS zM3T`Gkte>TK_y;8yk(mRzZ}?Bhv!QAQ|C^9>*B~%nX5A&FdwQbnc`Vm&^CZ?c<uAg z?TE5f26P{OU)1vdMk>HHs?pvPb806(gCn0C?;HiTt&MWJ4{#Cpw4K6~TpRL2vV^2% z=Z_iao;RzjUq^`X{}&Uk(>Hb3^U*2i<&LurBPSndb6&gUQMZxMJ>qY9CU+0mE&a=} zb_2s3{h*F<+U1GF(~t5)@BTB#%DmOveaacPJ<tYH|1pC*3%)%e?>8P#lZ!g9PDJ_W znhTxu^Zo-{!zFznwR5C+F8D8OuE4;1AH(=53ia^(M_2x!UYZ@um1uhCEF^O3_ppE6 z`}g+;jdr&y=_}oU4j2Ji7?HCd<mNTu_S7TaSxS$uD3sB4yZBTR$Fza@j{MciEpi^S zfvrk*li*Q->;8EVgGJB^7NOewnAQ)+`TbRgj~u&;Hv&43GzMrlrSymumktX&k?6i5 zLDJ+4(R7T}hoGCBz8N~QI^S&=R8t$(v2dZPvIJa`sK4&yr~3(bDC`kIa;aBsm&8bE zM-c=Vq6w%mothgu7JkOY_^Oi*X?%SEw<x(<G^wx;;K9OA(CB3DJ={aOE{Mt}j=GU; zNO!O2-o|KiS_s)Q`C4S*VimdG)96u%V8`RKe^(ywYNwFk+D;8{Xe`Dig_zV>jel&2 zjLtB*f`DNkHfY>YCc`IF)UIpG5@*r`icK7;rGu~U1D$+?6a^@y<@fdggWU=CMd>;2 zF&iJJ{icl*g1_lujwv=$8*%%+!Gc`h9ZVQgXs3}B(r&6ncW2-XOCG8*{T<;k*)tC0 z|F>^I-l!hz8@yEYtf0{t<*EWnYclpVIDwbbrZ5z!U}a5%UU*kRO7V+%K;D&+>;YbW z(PvCzXiOz&nD?PNjUVEU^_}NxzJrCuGB~L;jkA;_kH-bz7R7p|*#(ajkT-yjWxxQD z39dvuoq^YXRFuvrNo2@=5wVs_2~Y+&sTkE*K)YAlt*Qt{e-6`-jir>O)#*hi^ajZ4 zt=wi!iy^?~blA2fZ1u!FECLci$H&t1&bPIW-3K3H9U}mCR<_b$a2~{*PU)j*A2+18 zU8RerlM*@^CF$TSO`sHNEkj1!zh4;8gcPx~sxH?qYkD@+J$%6q`8~Tf);=wNTAyJ~ za@2WNNP3n}CD!Q-yb^@-g;+m#eEBBv7(=;EUjL}oo%VjFiuMSdJLSpBl~ikbpRS`^ z*@mo5ws=ZB*Jn4lr6bp;s~NOn3s%T;!+Q9OYzsp%)Z?}GLDp{`wa3DwD;YRJc>8&t zb>)FW#AG$Wa7aAGsjZ`N47yp>)~}<x?7{WqYQ|u{%mK!V*TQguoRoHjr$2{pCSfpX z{*|lTV3QHNyq@&dpIS!kc_|JrkEb@K)I^R{rE9ZaCIpZa#P!OyHEBziu&yCveDdQz z-Jy#|>f~@qQ~f{<Imx=EuYVZ&YFMRuJ3&<5U|h`hgjOFi`$WCDX&Z|{X-ok#AJ{bT zIEOqBeGUF6cZ*R}CiU3105pt@JZZC=y8lNLl49%L*3ZD7d~#n#=1Tp4-&0lg8k5j= z@v)2}o+%sz>l(XPnY3-&&%fa^4_Hm<_VsoDB}CZQ6Rc-_o_@C<sijKJSxKs>j+^{V z&7>lQtY0?jAA7nn5@mg7>J(fNY7{My;$oD-y=HGJ^v3Sx9Xoh}?h<`1n8D#&#gIdB z2QYYLVC8qx97Q1t^MHOjc@$X{UuDDX4NhT4-{>e9dmTWh&}8XHh2TdnGrUnvqm7+l zG&R0%c;)s)oE_hm3fw*xEaL>6@_!v*V(XM?$vIPh2_v#QgjAia54@I!Cjb%3#IiAH zZ4&}IrP~IFLgz=roq9`C;T(WSU^S9#PR~cup{$-05~=#!cDgU9O6dx_aw*y8UF<z= z1b0&%B5A!1x1|(!@6)dFS;GLuXz8zVuQWdoj<KflE=(K#Nj%{V^?8tHy?qGnOJu=s zIO3D48j;}l5Ytuipmb7UKZB6+nxO%u5~)h4#3R%~+JwMQ>q7hxIPEW@j@zko9!fBG zuby?+JKxc;`W`>Vu-1n?*5_k44!jTLPON=RL)wmk?{nLqDCYGUN&C{C_PfI1S6xHC z{P^$nQyPXQ%~Z*lyOSKLQ{UD)6R7t><=}G*dN*J*!w+U&40v3zlRWcs#^_tgxycHT ztEq4m=jpDo(cBTws|Z&1v!=bSNTHN|PvNOMY20Vp)UP4RrH`K`J5K(Xor8UB!b6Lo zBeWtNuf^jZi*#PUG0LofClbaOmobP4Pa74S*V4epjW^F*{z{1z^emx~1iF`O@U!P3 zDP0336Yh_}=>&a;(w-#D_-E@V#~G`;vxA|NcPfyx^}YEOqd#EtfUx(@?a{k}PX8`s zsLGAsv^L!PA!R@IG<33LC57D;J@S-u$c5(f`Z0*z8=$2ww%}DItsQCT`Ko=cwq^EX z#cZv2XTr95ao{PQyah1@yU*5-k&<@M4DQ`CHXORToTGOT7c)?jH-4x3VDj!~V_k$U zow#-CnBsN~lt8!JrT!_I9eB{2C8YEtNllyFSlH<-C;Uk>!y2orD;`GO!=%E>KT6Wn zynp|wg*#fvNFG88Kh0kei~FROHB#bdV>p)U$pG5-xor~A#I|TU#d*oZc?qASTunhJ z2D~?{S+ZmwCj`)~-!9oKFWF>FzJWrOgb7erfOGZv@HK|5^BJ47bn9e~&<Utg=^~)= zSrP7&uK6+Jf&a0M%3tg&1scuo^k^LZM}(Jzmd8kHDW+Hb4kX}&y+$CGZt?MRV9j#S z!{y+?<q%y=a*C};o5?w^<&!-At(wc{M<$&-mRF`s$q^F(;2D~{5}UVjsb=M}+W7DK zvMpEY9yS$31vn4ibh`U#>@xqu$xQjB^A~HPOI^By=tp2?SMpX<YgW@9(pGO=)F^+{ zWkZ_wmezr}w!>8dyac8vgi-``Q#vAR@2%Zd`dOHFb}fI@+ctvnREDlQxLW*ntz>zv z^k-nqqYq`r@*>1j)dkj+pBM?41_+*APHa(o*a<#R87r$<Z+N)gIJn*<e8XXfSIFA* zpQqO>-?@~Hdr=%V>?GT1|6tk;-3NSkFK%=sZ*=Abm;HQjrp>SH_Pvv)uyV1$cMd_> zYR_woU!F|oB2ycI`GrT$Uk1*88NB#q6xQul$Qx>sq^2xgz2{M-u=cbDnY^zhB<}cd zyY<GkFB7_7Uz>iN{7I5|kC|QYz%BSOsHIQBeAoIHr&NQun?oN&NDn)IrOk0{&I@lY z@ZiNNn61w(=f;EOgNgiM7S(%QV~63>kNwHHT;+kDi*Gl-E^luB3>y$D+8i?KHq<Rk z>1nkMTGI+hq>~gw0-EKQxAL}r*KGZH7%sWcY-5)hGkETqIO4rCa&}>|;l<bdl%6SP zF72)@*tu<vm~BoGHkXhOnzp&_YCiDg-`kL<#_(iAlGJP8@kzL3_Hx<8X}I2wfZ2}V z({R3}#PmlYWmHM1S&}I<0`*NGI~zHa>o@w>7KotpnWexTy@eFN$>@EPy}og;kFlyW zyPC|JF;H6ZI$7zw0i8(+xP0b^vU7Db{OhrndsoiMiG0^o{H|5IqDBj%_n!9-okT?a zMh{D#i>fY)Fig9*PHhX`$VU^`GSZ~y&=b1f2_m~h#b_QiBi@=c(VVcLON`!x?|Wg( znE|tJ#~2-MUh&j>0M$h5luql7(0|7lNg_Y&6o1&CdwKl$yOPXkmQUWvJ!Zz>*B{0y z`Iwq+_Y~)Xdsb{S7?c(VF7XL|y*mesDDk@*<e>M{&+MoFGt+kLH?wr^%1MUlxfF6w z2WswXy#6upHLyx2gOepBh@kdlBSEfoPP7F$n_FqgD#rLdfewcCojQ~M>r(Bn%lX=y ziJr}o4$f{Fk<Y{A5_eG+uQR<x_(pztT0I70kJ@^>*3U;?xlY?l$=^#ADbL%VYhW?1 z@zSfswhm+ctuxxw3m+PAFnJr3XF8WYR_^7V`<)l_dr)&Ucy8MvF!fVP={1hM-M7+u zp4yBjNc_|<DB&btG!_5`^3DEKx%{c_C_Ca!hrsC|QAJNRu0rP{U{^ZzmI;3T1=t*D z;1rCjmSjWdG{qXd{lk27`--x?2DB=a%N7nT9&GG%+3)JufBbB}``!M3EBjA=?LXx_ zV2K>`C?53c9rT$U^t&7koI4ndIe2#cU?~6KdF{b)$H9wd2P5weUalOB{yKQY`FBj@ z@3`XM3BA9s&Hhfh{C#uo@7tKa@2>xy%KtlE`}cjv-w)6J(q`WMon86+@z>uuPWHSA zdqI)CsK@?f#$Iw^e?G@vj$yA{XRqe7*J|189qf%~>@V-wUsu?hzt~%x|F%W`?I`~H zruXl=*}q+ve?QLs`x*1^*Y$sU`Tu^`{`=GMZ~xi9gLnV_uKZ*FIy|$1JAyg+RRXqg zy@^N>t&r72>rQ|EpKV^z{Qq>2V)+^hFiigFTQGta^>zKnk*OBnXIZMjKULnh2fb@M zY8gb8vkzUFxEuUS?PK@lU*EoN{0g@vYWfZ_?E)7uy_#o%L3hQ0Q~?#}(dLlfTFWDa zdgnL4{MMesW}fW49gB=wQYz0)BS{nt)W2yv_qsWBUw3n+E2cx}=pSfNYINMmiK{`J zQIf-#zR+BGf>z7tGH-O0v~_cDeR<z;erxlu;oi2?^ub4+$iV>7BC<vJ$>aFypX}ui zT{Y5dWA?$HU*EU3POG5q%xa7)Jnd=qx-#+K3R;4DBGT1LyIcdq6a8pV)H+w+oHGnN z`b#QBI!#|DRen+AdAPV``(SuwhyoI+IgFP`<b6aF_OPmLBKDy|`gKLP?)dCwi9h{o z{z2*Kb03*(8-w3+Id<>m2Lf7bCVK;pjW|C`d~Fi_DUN8WK(;o?xVRKzk@2u9C$#Ig zLUH8q+G{1{^qN8nKEwH0NDNxUE?=>!RVoONTFWZPeB@eGnAv(vu`1KjK&d)cOJ^p4 z%eb9P%WeOC3?t8%iV&|L<poxSR^bDc8t-=fQEp;ah`6ByG8f&2+TZLbQoPsMiZvCr zrGcmJC>mKh$~i2}`!&5Z*jH&Ef9p6Oz-gJYiZ~iaxh_6C+!NXXwUL2wtF{0TUSy^W zT-<1^B>@|wvQCu<{z6DV8P-+!l5%3Ngb-<2u`lkCJkEBFDP-cCT7vCW4q6_H$M1(H z%qH{O$%mQSC7|@ILC?AsEcnfYj%~Mu_e<S0sFHJDjp)N%NVI0+XQHg!NLkk6-}*9L zcd#DE&9v?lYbpHC1hrSu-_J|GIk+pHh>zx+gi7h8iaSn5K!(w8Mv{3nMsP{kOgzo; zc^~7zG-)ie%7Zy>{)*X$;Z@U#=+M3Kq7S83T+~boI(XZAeF77wznIEC@)3RG4&N*j zbthBF-amdAKc-|Lm!d$7PXB}D0%RS{=!h<~87a75RBQ!e6WN=nq|?3;5H8?25FW1} zT5wH@s9Uj_IlDuZFH}tF6})xDk!H4p*raxv{iu+!{Ql@^<XB*df@7CI^eE<FQ*l0h z45yxc_IJ7TO?M2b3i^JZnCqx6!5gIsy&gO<>-~6Vp`(M`WBjWKtMe82I9o#5Ha-EW zL^=8N*yN%Nz6W97Vy`B8lSjcm)hQKvwMD@EU)5^^>LiP%*ctx~Dx)vpP6J6dVBZqG zM8u$KOAcQ4a3Sj{$-N5{`h=Jl8Nbjo$701vFU0dyb7cKtF0vVq9}_p2`k4CzTY9m* z#XKLhjXNzguWGhPm`1@H#;b>t6hc5ke7>ootLPNif}^k*gq4s&(qUWm{6NJT#j7ym z5j~z)>|J|^{8|dGaDWDY(EvoyUKd7{lerJnuBM;8!Rxkwu=l1gzwp57QpkJmdX3{% zIF8?j@p))Q{dng*hZekal{&8fR+^Gr5R$@uvRo+v_!f&;ls3D%hc(uu2-;qKi3-CJ z;1?<B3jXmpRV`)ANK}lz3|wB83`=A!=miRzi_`op-dWH%VHzz0d_<YlxvEz<PYQ9v zcv@0aTw6=oeBnU(oum+fSLhmQMV$NFNrA3R9GjD3q8C%kM89p$<hfR7)eO*6!Sqb@ zR}=`31T3D^-%u?-`~`ZBpPIoT^qm|(7hr+Tnpi)cJzu(q_BFneu_bsx)afqD{$*^X zFVgdy9E}_xQb1Mm_m9*M5(giJRB7ejmMoyi$w@m|h+4;T2SN;Q>7?47<&v9h@W9Gt zvdklXq)9}+T(66`ZiA}iF0%rSw+M>;5ckjdf*n%2jp5WcP3FFQJP3qXBut=uaYZfh z@r0<6Vod*0F&#MGG#6}eU@qus6mQPeHvB}GcFt30@8uF)CPi;(p$>5q#lyy2kF4~) zkN57Avz0~?ujb_%2@M6Fc{cd{KY}%q-4k?7UD+cw0E|AI0~2U2hmld$Xg7K<q@0;V z3b8lhudXw>UR027pK~WPYA#?>gYSV2pS+3*=s`flb#Q5K)?G1f4S}KKUBVQnJFOU+ za^huh<=6JSs($%<l3ER+4-=1H2^u;P9Kp16dm+oZiHcj{%6e5#Xo5~dt<O6#y)Hg@ z@^n0c)FL#MBrZ@0mOrDTWdD-yj&F;te2Ro@ww84%tM?;W@k<W;(_G8cm8U(nWOM21 zaAbd;B2Gik;!%&l7y&Kio=>7k|1VD6G0d@$C;%<DyD7{<jGTch0(@{nO2LS~q&BV& zn?+FZeu42M;8YmP+C^e7<Kb+|g<lNV&9lE`29AC&;Ht<peCIZD`mED!F3)9yV2096 zNnK2J|Ac_6ugo#;GnOB>iv-JYc^uPCHxZR{IoucXRlQtGPuJNeOl2j*xN>OqLJYtA z4gGp|lmbYmCc*LLHa_0nL%8yvi}B3bD64~;Se`ap2O)p{r;nBiy4a2QlqqSe<Om_& zFPXt*zy<7EFF!Mg@77JrZkTkqe^mtYUMcX@SdyD5#t0+&gkM7*`-*U6f={X+Zi$q( zTu27erhWP)hYO%6+;%SEG0hF&paO#YrF^R5^o3K#01nSEzY**RaJte3Fn9AeY};Q6 z$1{2mOg?*!Vo<ZpG4?ZoL$|FFVa)W>uIZfP2LTQ3p?Jnc3x#V84t4)Lb#wFb<eO=G zGl3>`1}WN}B}_Xr|F>$Of$)f%%-Jl3SDNGDC$twa^#cAYD*ABRuf-21{wVlQ95)_1 zd&&KHd3e=jq}q_?n^1JvvqH;E3wff>>{vp`7mlOm7fESCTS@aDHsF76ev<lEWMnVL ze<AiUOT7W6`mFntD|M*X@abn*O1I2O^na#zG%|1ADXm1d{PrZBw!2yUasGO<xv=}D z@^l9qh*Ut1%5uwxeW#t0X56x#GSLcrsJ=9jDTXF>n#DM-ZgRwQ-nA_YW7fUmd3(BH zrrFNdyHRVYO*Mu5jeRQX#c7xRqZMb4F5TbiWb9c=zd1V-V4Q}2!qG0fXDZOaS3n5K z`*d9Ndj&(g1Te*ylB35x#rnMw^91oZgog97C(dNjYr}35B1eO6h0Y65p-O@?9AE;( z9J-O~4G=(HLtdaU$-dTk6CL{I1LR0<xd2dRikQnj7(w}*COMwGn%Q3^beb6Pic5u) z*F2s-d6GCb70}NT93$%da6$bQAumm|OH;~$V$1Y7M1bc3{TA0MAl@=(MkPtK5QPqX zMUyP+9v<HqlQW`lK55SmH%@h4jO!)5Kj~E_?+p>J}_2@vhGYLh)M&Kc&?q8K=B} z?{OgZPqD{6p%79AT@Lzo*5yMkA4i-oMIY#USq#w!K^%*FJVB(Z^Be{&iX6QM#sX>3 z1$0=Th>xo#6l7jG;v;ONpm<GF9PAAp4a}jvcz`_e@FN&yvi&I4qlEs^Ctb17rQ94x znsg9$G9O>cjvfJ?x=A01of2kq*dbhB3%R~MmWbWE#pOs$^P$M=mmywOP|_{`3H4X~ z_i{AQFVn)7JR?OO@)K8;G0UO)@6L_h#1b7H#3M7%YV)^_QGU$G5~p1J(Gtd&1@N>m ze{zcqWTuo5&<mMgq`(M+Vu@e434$IymZtGm20dVLmYS_2Cn-^&(+w~pT*&N&jIgWL zk5iCp1S>C)m1z&8f5{q5fWJ-p0`lX~@&G7aWKqU|glyw>sen<ubC|p}2Iza_OVzoP zGjgi#c%rtOg{Ad-LnKsp9eskfK8fxbMI}n;3sV|j+R~3D2FLnX(knz|pwjK~t9S`B zN213v&+)i2*^7(wLj5}yl>{SMQyC~ht)Fm)j~GU&EG{94`(A&3TEB!&)+#dbkReC# znjFFzG;1m&s)A)G(qDW*bbq2KSlQl@r&2Co396{WvSxdc1LBJ$X!L%GM1|PTc_2k{ zRXIu~QDLmSNJ;V3fecDZoR<V0elzbBR^VvdV;w|v-SjSMk}xmvb7z<GQX+2YUA7XB zwz|UR3g(6?jrDLB+Y3rkJo)=QIdXpyp&2{!maz&xx?_UyW$sJRhuh*p?L_gh9t_*m zm(*Wp^p?0JD^X38Rn|ZC*#kv(tRW43;_9xwlK1whPJnqa=_rr)<*L!&2V7UW>N@x+ zKf0w%1Yhh*K;PNb5ncT|<okCrXM?*Glmri%*|j9*JVG*&ODj=fW|{JzH#q`q0cL^B z<&`5ypb#;T>l#5rkvz4W$1UqgJ!cwFUL>z%!m7OJK1}0wSGv8aKuwX)VZpm?65~RB z%v%JR3jO#q!bZbAJaB3{4<(KVdirZ1ky=74T(L}-LZSlLns10gEWzw+(2`N7;ij^! z^ugJMbC+<GbkL~Ej~U`_1zBI<W;5j<dg_F#mucD^N;KcOyyg4H5{b^rqzG(PTMiOh ze-GJDvxzFmRHF=3)Q8y%=BOnqSg%>A^+Q73K&T_62$H7S=cpjZ^WV<q1qsHE!U}vT z7j1LEEv3Uw&_@RKPVUI9NF^l{>o6XCa%e4^io0$~Nv~cv_o*OHO`z4v=Ty%Ubr#PF zL*Gd&69X!IB@3)#mrs)@P9}q9BSrP0&WW`5@S3l4;d1@Tk!OF1E)Y6P$l`NN4RZq= zmVdZ~mz5|LzC23Bq!-GRR-7bxcVb9EIkD~RJ$H7Zc;|#*)t7tg9Qj>Pr7tpHOag71 zWs0>Zn}LF^-<H)ZYe_1qCftOv%YkH|H&1NCUFXaN+et8vZkp>wfh(F!S88rb#?US< z<;fF@)6V5YNbH*QE0}V8E?Gel6Ni%flditkkf7k9X+1p9Udz=0$|uW_P|>rAnZKn? zbY!SWvft`a$KHMjaFqGknJm}x!QH-z?Ee~}p=MFsTjvPw$_zT^8$b!kt6js4v<W0E zRmWA<N@SRh+V`KSCmdskT#NuKiqgP}Op@|U|9!1cGnINW6L-kUAVZIsR0orB>VSVR z$u*Q*w?<LA*YVBm9T<SzuHQB8-zH(Y*p+upVXDgX(BJIDZr#*mQ;sUO^Np6oQc{2S zYygj7G78mzd<opDQc%|SVHu4P6UROYk1Ub;@e3OkxUfE+e%uHPHA!Q6crDCchCcc6 zTH&hgfI<JtuK3M?uf*s~OgAx~zD+{qJ^uYQd~c252x2Q&nH?O#PGzx^KitMq#OKxL zxuLJehlwMnuJZJ2URWo!t2YZ%<e_O`uKt}j&6JT3+#8#lnBLnkhV*T9%Lo!OEO1BR z?nK!1A)?uWgWj$jOhfu^k*MlqN>ARnf_p@00me@{K=6ZY|3d|SrSyB;HKAm4)vEe? zAB<B~-+UoQyyE%rRkeEMce(@nXmxtch16B=8>_L)i1sl;3iz~B1b0u^?`xvy<iyj$ z*~UaWqPbXLRKNEcUfB^`9Tq_@=0`5%W<Dq)`Db%Eo<yDwpykf55taz$liO!Mx0&jX zaSaI}UF%u4pcM+~kpv~Z1YKy|y8<lS<tZWO2m!s5``?00MxufbMRGw5;Q$cMKVB*T zEL=qCv~>)NO5EXa!zO&pJ9dwZXXPE;*!A5Y2lVD$*oY1a7uQo)?hLlDg`RMj)L7rS zSQAbjX*H#}9XZ*go{gHKh(@9lpl_pJ7(S{KulnL$LgyKZAGHQqb1x{Y+H$wVe}MNs zJ!}8p=2Unmz{9j+ma|zWGH2yf7WlQKxuL_>8@tbEZbrATxK*C<#D1Z;<_T&n@F%0W zS9KiT3GvwxB^()Y?LFG=hs??0@NO1nh=|q55vPT%dw4RBt+9@*jq>v*@>a7H1)$Z# zbRL!KJVv8e5EkODl0qZA?rD@$g&IFuf+$uz4i3id?*4WxB)T#-+W}ry560*_g4IHV zH~9<xh(a$bEZyR=CW^CqcveSG@g%ZzRx6^~U-2Zm@~Y_9S{|;Lur)*2n<$;rYE@2C zH<^BD(tV!Hl$+#-LT0{Gn4!~NM@+8WBUP0vKOE@rN-XH|h;Ya`aRQ2UaD*$jcYTW_ zhq%2qjmEL{QY%dpRoA2}<;wqct1Guh?{%}RIK9NV@g4GTp^<wplWRVItN)iMWt6<! zz)g{dJ6x&LGNXE5DQ8JqZq9`|GX!aGNw@XP&HBw=aFVF==vF}e98_>Zi%i+uBq)<N zGuAHiR$D&1$-f6Wo}m}hNuI|xJ^UFOKoTCih!+G4`^PJEKd@*iHdSJoZR?U}G=cg1 zM5ce6C3G}5IBMfN8NEx9{^iEfG`+p1HS855b<Y%mx#%+7Wegov_3Mt)qh-%D26iSt z%8d~}sv!W`^QczAil0SJY7krYey_5W4(f=jF2b{VBzo`YgX?jpDOb<g8QC!kPe^4r zP}mCL?h-9UN3@}}e?3or<>4xSL=bJ=x1@+qtps>~v}yg6bdGZM@dGji{7!zzf0mp6 zYzWnKMn1<N^<+sr+w)4c15Mb@VA=bVe^+Nn75HXwyh0U2|Mf+KTa*h9lPi}JZ>d9> zH$sWtsyp_Hc&|&CBag_yCBtx4g4yrsD29k3R4p$!&tW*vF!2YNAn_}al08&iN|-f< zuGAzZY-QX{AeC>9nP7#5+8+p2P01}~b1m^*yMdu?Tq2>t?j7_^8h|%#IYpM~R~qU` zDI2Rj-7hgIfLvwyv=sT4Ipx8j{RyKyBbP~&0@8;4O6^2$7E7u6i_+4*k@Qis9JT?M zw%4gPKpcAa%x@-YW}i4i<YCc)N6IsfAl*tjsyn<}5&nudQC{aHa;dBNo@omw17F3! zL&3s(f2?y10ov-%u$X-kvx=0sCFKC!BJL9FG|9}WYzHV#hX6k0k_!T09oB_mF>7HK zaCN5DCDDBFFEIHxikEW!RALTSVz$;k3EDedN$TWOgvbG)FaLoPJxl`PRr%?C@+?Sa zD+ypg#OcdeU`6CES+Ex(M?YkOgSP*+U@5}Iv_)W~Sm3s?sdoXmDGnq@fLM3D*NP_3 z>jK-cBtZtG|L@EzU*Yb!YbHc%TXvsG{JYxyl%`K8&3~gmHmGbSNp6VfB-Q0(LP{|2 zb@yr;og{7!_P+op;jO`MP~g?D2m8;Qt?48=H0d`lrR?7^N-^W#uM-68N{4g&N{%#6 zJ_W~4rVsf#ue79*Q$0_Kd8Le&oP3LIwS$;!=^r@%8>NgQ^BOs&pb7I_b)UhUW7%hI ziu59vCm&^>dzDay^ck;Qb5yn~Z1-03A3J9W0?NVoF##*bdN~WXl67jl6Hx3Q^{oN$ z1sbX5X%8-ct`Rtl*6^@M_6`gvlE$xZZaxh1sDrk#mfBhB0ECWqzS;F)S)dWcV~~N7 zuNG*Gx08r%`eqs53kV0;2b!N>fW&JBk+!Gl!c12->MGB?oPzMHI0+4t9~96>Xo>|! z#-kHB#dPUj&(LQDB_!L0?F-R`6;9uegXjP+wnH69ctEoQjf8NA?<=(N#>7a*e>}I# zr|#d%E{(gk|7&OEU743)+Mc5F^hp*7p)$sT@L5xPU}8<F*@R~Jl0c^YB{Ua7Khola zO}BEm;y}5tiVPZLK3}m(s#5A|l<eYBUe^NmA9)vmlzaH9lA-dT6Riv#=uMY>ZYB<j zUBoR_YRxM=FQ3pvH`0b=>UHXF7xDuV+A?SK#bJP&EZ*bb3n--$eqVzZ+i=6Y4n<Xy zeGwtfVkSI<;)YV%Gz2={WywBo)D+V4f51M<7ojafc2)@i4&m85hROQB`2bUFQ~MJO zwg6N?chQPSwjy#nP1=bpEj-1T+c>>(atnR)#>FRBNr>D=8|p>dn_GMqv=4Z2G#B(> zdwsOnT#&D_xsnlC(NtcAaH|93H&n8i=|P4C4W0r3LE4^685Eb*u3;&wyi|V_B5P++ zRNfK<N*sj&9?WhS07`7?=a;b$o6Iv!5gik5h{3K~&Ev(8lvl5;<?2D9TpD$wJ`%oB zHi=Th!Zd)4Rqj7B%n$Zo=+($D_lbw#tHxhQUKUnn`rVwaFo<RLF5iCJ;+Cf8zd5~9 zCMH;&r607n1+|H{bziG42z$?7vpl%~WpW*RF7ysr%d_<U<l22vK>dQUaFt3EKmAjJ zQCLO|{jU9Vg+^`?9&|SV`Su8iKfpVlQUQJ}O*?z1Qd=2>_6Fi(v*l8^Ktm3|0HE{y z;_RTVfKdZYT4sDG;TtS4tP!kFkLTdmZ~(?7+YB2(;+@-R9BB0{X|Wd<=aGcw2;9Xm z0j<PiV|)Sh__(|8uTq{;!o8_=)=lTtj22|*-LU?fMbi9wk{=q6UC}un%dz)RK+YzP z_6~V(O4e)I@OtHT+I;Q8t<&t^YuBHz?$y+t{`dFy*4#hX5lUJEH&dW;z8{Yg6;zo~ z7UGZ|Xhy}us;@ExgjBrQFcZzRhDaO5kQ>N#V@gL#0622cFJ&;6Gn+H^^Cj+hthpnn zkWNq4RRG6o(cgJgH*-Yhxt%poUS2FjyF3uieMxk6kt6B+QG%ycgSc{AF6nwK8VGwa zA|R#JFA=qcE7o7+ks_sGWaiyHC#6BdqH2xehYY~!tYXo{Ho!>wCdaASY5v~SsgjzQ zSIYhUJVG^x?E_b<?7JU-a`+bc2-41l8Byjt15fGwmdT(~(x^PG&6afOBzQKhl`Udv zmywkN?K(UrpjtXLXXW1AJw2)8lR|<r^5}K)st^!d)x!tR8;xsb_FA1<%(@+qPn6c_ zNj?3e-*UV%4bJZCG&(GsZ#~{g`{6jzy!arXNX$Y|#E)cH->xa`o|q;iu_$DlQ<H?K zSbWIyIT!H$KZfoys>z291Nf2!wW3D2(Jd|QHo7-TT2cX#20_6w*kFXxjkr-#Dybld zln9Cl2#AOZh=_&Q`QQ8Uapycc`>=DKy6@|E2@#dBq`#Px*nIl!>j9-%@I1bvq61jM z!gF(zGHm^bX^Sa?dtU&I=AsgGdWZ>FfH9Ub5+kjneVECX|G130@%FR^dV%O}n1{p| zyeF=9C{pxx>Rwzr1rWD_n>Q}bWru&@AR`VL&^DDXbiy01>Aj;B*DNu`HK3<9IIdj0 zN1OAqIcb4H7X<~egQN93?ps2yoo`$AjZUiYo*%!O_N6iVg=Lg*E=BM#5}g1dT{%o9 z9w{wH7geY$PHU6!k`W?nw(sK)|9zJCj~8JXWHcGA<kab?-f~zCm`uzb-69=wz4F+| zvPLijzJ<#}xe^G?t*t@+R)1@Alsj95yF+qsi70~T8=tvK%~h28B_~TCg$Crps>2;0 z3qTQ8L`N17_x$ZOb|<?=NaZxus0~$Qp4YzIzn2u!oF(lD6iNhWCXY!5e0D9z*``v! zoGzSSSXU&-lB4X(?SQ>&X9V_dr0WBbRLB-WC?#{HVz3l1GpckK^q!Hm#k8OL-l*H| zOV8Q=Bg@9g(u#&=L;~z@q?tqF5=tX1x@^1`vU5kPSr0-&dLG65Ku?JD+M8%U)4onU zMm+d-46XQ?-S}irN5_me0?E4-c~-C={`Pb5p+#>tDkd8lr($XQN+exDo`2fOc5MWT zzOW!JPf5~Y-jh6`U06LEX7IIop%c?YHzWdKDS*b<@5{eLn@5K3dmJPS@_xyzX5b-A zFscZk6gaIE^yR?gHV~CMynV^Q15r_n3jzT8QP;mZ6sPwzuqUGjgxe~ANoC%i|FJje zJWHD{<3~rR=A^g<OrLuBrU)Ob>zm`8o6U9I`bzC)BZxA2BCblUfj-Uem~i^RON)1w zdrOI)e7O%q(~C;4>B|LJvlYje9_z)_K70P-$IUV6y?T8u6fJxdC@>Gu__xToqI~yS z9wx@*+2C!wRG_H%!I~Rn^%_d{#*7!TZdcyy3{mqh(#c%<J&S1v024AM4r%($$2~PI zNlc_LPo2s}Jz^HzKw5cx6bYo?vAm0jTNsw2AjRI+BzUcdI?Ku0jri!QI`JW#ub0Wx zy}XhCgeg-Z8LWL;cYB%|ccZnR<KQ1j<{w6j0j!-c`Lur>K_#+wozK54|Mp$?|M}<1 zm`rkaq1o#i<(ppwx&Ru}H*sGcme;@jPpxbG$T7SlOR?)<F!#X($pBc<Gm=09wnyDI zs5HQ`h^!Of-!oPGk<`sbN=AMy>}ev49h;kuQVozM>TeInSVg}ZlbZ~K6mAB7ejU#u ztyQCPgWh8s9xm__6qn!RZoaXQLYMdM6FnolEj%X^lqu(Z^kzKowK-Z=ho)b<t@!sV z_fYy<m&<>y>7By?E+wne3${9j-kE!CrtAA%$i(sCtWvLc-AoT5Q(XFIuJ~WTen6zr z(8Y=$!nVq}M@ROdDS#)nvc4JZUr9=Gvno8H2F}V!CZ*6n@)IF;?<<vDBBU}U+VBOZ zd8u=p8XW#V9m+icIWvL=7@f&Ah3$%NJqGL(<PqORgLzcG&$jgODf1|zJmPiW_*!uI zV*7Pi`aX=I1!om`$jF~TjRG(LeiCpm5&B~1!zdDdOf}rI0RTi2fHEW%ohB8CupTHn zNnTlCf;W%AWyF98U!7IYooL`cDMYl+HdH)p=KSf)in5$~i(ta+s!l_8tCNDP0}+P; zctsN%<TxPu`=x<~CLK`RSv6FgmICB3V5CD4A}s9B2Na|H;81==MWLh{zC`XnAh-Y< zPV2cJ{*KaC94^2{!i978MS`?N!{S6EwB-zm$}$J!BMNCbQMsKz_u+kpI$XJK11>g- zhzjF>IH4w0c$L#e1aV6Mqfjx*YMr2b-W>l+KDs@JfaGjQax?PeX(SRA<n$i+^d3hF z^rR(M-tWZrKk9c+%Sn(nSc6LRWNu)Btte`aQPJpSKC`86VrM7-426nNuy#d6o*r5_ zXkV9)1N=r)fW#0V#p#?Ff6#IobE;d;?28;(M}A09xn~sdZ4Xcv=zPuk*xJR6{r7aT z4B+|2&z+w8il}?w(+yYq)RVP7UQ)!!l28B&jcBS`m==AMw0{Vpr8<iSz27(L1j&eG z<~6y#n@5WTbWA5l6Zf=<!&`VPrG}~|sC%8r{P^?imdf#HEV+T7<x*1fg<w00#l8x; zwxRj?3vyLhJ%qAf^Z9Y;{$(#~EM4DDUhu0HT31^nq1|u{)i)}?@DMRNUb*rhvm_U* zN7Mxq6|G=M0PyPKE1Py##YD_~loG)5LqC9^Ma+~2l2mA1W$bv^A1Y5NTmf0f0pbYr zoe+b=2l*P%o82#jS%i|<c%AiE2lvC-qKjdG4z-0Twe{{_p2C_Gi-+`CdEl@3wB#9t zRN#@16b-RC)rM$dN+F>QD;p)S9T598S+*)3dl*HU!C3#U_@tBBqkfWx3g#RQA&>$n zf}te7;6OgnuOze{SwzqMz5_oe5GX_fx?BHKWoPQ>>Iwp@`v8;$ev}??e=fvoRX3`h zW;XT#g#Mxs8;w_>3)Uvj|BgMdJ~!TO1S^X)WP7<8N>g?^<0rx!w%LpK#K*0u0>=6L ziBbf+@<hApvJ^uXeVC#U4X26QP?F5V%4DRNhZqjc+tYd2C4+09s}dc{%kpHjiRa&& zNfXjG#=)lr0QTCl=OO&(C#}g}__ijXfm=9N0A2K(3y`i)h3cE(za22Tz<GP5HWnAG zQgQKZl|cf~v{ZS$Pzm>mzf@5EU8t1qf?CmGna2sHUn4aVt|{q}SJ{)!l^E6gUt9Qe zE`oIA<ZZs$dk~%T8lwvE{n0;g<NCSRJw-BcO~t95iG4^gFz{Q9%!Z)Dh20xD@@$)5 z;eGpaJM@{@%)^jt68^o4(pxs?Lk*9*;&@qtftf<Q5DcHbe@L7xA46zkL-4>YR0pjq zGGHIdVe=mTl{<Sq8^B%V5rJKbt{yhD4JEJ=$h*FQ=;2^UI5U!}vt6$xSKW#h1WVVI zb?-F|(<Q13>!-@13^hF7?#Js;Y$V6+>}2WLCAzY_F1JR?v4?F>e4L)1|E^m4-s@%p z=q4^0Tjb>3NPJP|OC#4X4~G(6CKtac3IzG^H%jPdE4C~XOnL-)A&BF_d|P0?MLA46 z33h@2Yvl;3dXOC{LhT!TO#mSX5$Adrvz7si1e|^ekoyvXJ<w41D^5$w;#7k$^nVo? z<*}H*2C;}IG5@W&+A@R=WXltQuoc4b&lchPqA_+L+#Wzkv~p-KBicp*(-{am0f4oT zqP{m`_C#Zhz7Q;f1pj<1iyn0)0eM0PNNQvTY-2R?GZ?3M6BBzxaaP}achuFH9Ctez z)=9$5O(a6kU;t+@e^z2IKS`z2wulh!sRKZ0eC3%Q5QX!s)^ZCJPOf0Lp_1F~PgN*+ zmgxsI=-pQF)U`hd<>7txoJ^CHzCbj^?;Qxrhp&^c9^VO(tsaGzrXpK5<|6pU5>LCX zUDNL4bBV_o%U2>-PArsJ4{htOx&uJHD0xi)jsvVCAiFj+UxgX^({&a6_#Rj3FIdj{ zoH}?0q5!7lm^M|GHRv}oh6+o_#1v1_Cs}6H*9r!kM>jT1-*KSMxzKHr`)&r*83Ao4 zB>e>A_Lsu{Wx<+O6=iv2M_1*bfHGp|M%m=AqpGZ=S6TTk1U^Egx$|bu(=0zZ3a$lk z;eQs;RYLyP5L5ttqs*1V{$wG@ljEB^LOhUAr+z^)Q^=M;*rXTCu+m(Sak2P};`vIm z%$wv5PSS-bs4Q0{c%$g9VX;_)P~ETdWmV5eV`SjwKm0PS*e)$DqDp>RZts<o@POi~ zSjf>i7QRriNhRmGmOD0hElSs9P#yKZpAJxQ5yuLmrzQQEgc{@fTO3zSwX88fbkW{j z-<JXde*0Ma=5g)!hqW`m0aP8iz(%e4c<CIEWEokS00C*(l9q8AX0&+YhPK`GVBMR9 zx_haY`Jt2Ry6Qan*8r^o;@RI!q?X)qfo_y8hSw+*7%a$pRh*iMBt11#4a0^5%De#) z_)wJIZ+e;EM*hNqB3W%#u}T~lFLQ|~`kaLe-6*1EoP0Ooz9m;K+mLH^tMq|**(pFv zOfZT!k?+yaDC}K^w#2v^=RWymy7uen8b?v}H$*d)-1Vbqvr1`wwfWVnBnb+VlnPt? zfYSl;FY@c^_671YFgl490P@>^08|fw;=XB4UoG0#5s`;u&0sl-D43sca0r&N6yH$N zs)<V1&2Xs5fZk8nwW(225@~*acfRcIznWwGwKlVID1p5?S6S2xM04_z8Yk5w=c`kK zs7QkcZ$-V<i_ch*`H<k>B;jue`~1~K$gT5f7BqMqx+Mpj&1!g5Ww!eZ(!_B+vDQp? z3p^{v#8~?j_>VT!Hsn16%d%_p3w;Y%x6GY^ZDj9;$BpgY8Mnk5FgHwc&mAFejdtk& zX{!CxP6jpfCMWzHA4Y^?YkUg4M+YB)uRH~JMl=ZVEJo1GV*j(|18W1f@ob6A0dh5R zzTns%raJWPc$f-OhVv;j_idGPWeWX3Vt-|mQLPwn)N`bW_@XVx1abb&6C&!K?D28^ zCxbSGb3}0y*&e80v)vTdwTE7o`IL72-Q@j(MA&063S-s9)uyeeqU5~Xp=id{aR)lj z(nnkJhFhIt&%zPxSz>b0T|0fP8W;KBOD@MVN1j>?p98t^LijcUG4BFl1@!EPSV+;M z6hR0V10f4q`|#a*W`1i8+D<~rG7dftEP#c0ub=_%1o`w975w?a35zyo$%KCpDhak5 zh}qsKHG$qqYQR|Io7}E-1d)X5Zl3*L9a(iOJoLbABBN4F%yIur^AydeeH7MA%vXE| z|Ca@A8J*u8EqXOUTCkuC@fx9)W(w_Vqk`Ll1&XjO5~1SRz<-iT$$^WAzC~EyBH3(I zjPg)ldJal~73>Jj72xilW~>@p^b-^j8vrQ+zkp|Dq=HHrsPM^@+OVDi&)GC-q=e|% zHzjHE;H&qz6h)u)!>e=rNJMO?_xFti4Rm9Jghay^Pf=N)WV*NCBnr4{BTVakZzsGk zvC-t&^iGT$@I5A@ZfUwye%$gG)$_sCLB-h_k^GNaZKkR`|8x#WmwjcB)YE<$FTXo{ z^Pyaa{v{ZW^0YUZyk2J(9C+I*sPNUqoN&{Vry;knAY755x#FOT?C%1VO+{N`vxqd= zGN`HF{OwaYI(_cdnhQx#hqCs{VqAoB=YJDT!jQ42U>GiQ^i>uVB(2zLa7y@4<5P=M zR;>MV&+c639bI~EI{)`5d{dF|vVG=8Tg-n1@&DcWnuX$pG-EUOUd!-^13ZY-o!KTn z<lOx#9X*uH5&*gJ<N7?JkAvF9^G7OB@H|DouYFE_!Sw#94Y&F9P|7Nxs4IvUb~^Yc z2MVwY?G7<FlpcZ{=Mm*2ULB%fwP`i$EmG3sw!Jj_giM_0q~W2hC*x(Ihh$M>-%WKh zgM}$ICBGG-O%x+-4-v0Q04dlE2Dq1F%+}(Lvs&RONFd6Cn*$Kl8fI%ZPF;{PIr|T; z({zx@)pf2aBbK-$OO@ISJ}BqD&Xo{oo^JZ8^JeOZI?XXyytG;5lBM>o!0Lv@aa)}@ z+(X-Ut#-JW`UW34w>FOsFYjyKDM)J<ny-Xwv0dpap$cUQ9`cs=j|hco9cK-9x!%Zi zW(oD%5;Fed%xxxZX8#<>s)<#Gy3C=8a|P(t$1kriBva*GD%{1LPYkN)TI1Dy)yuuJ zh{DxLmP6<N(<xU}rvjiz_i1Vc9}Fo)?K<cU0P~4j4qk#fRH%9DJ!M_UbI-_u{s`s@ zEds3y_+*fT@_6Ghu;g7~X2a*v37{3w%&|-R{sbQ$X1X*^<E0e*fnoMrM=khF>E9<U zME%_fWEZKj4bm_FCK<9oXs8T8ctn(aMo!`j6(A7NO3VK1zl|dA#>vlHcm*~|llM<2 zL9I4kPa=}>5uatOMFNW5a-qbf4U#FvCbZZ(nAex<7|WKo@htWrJ`U#3l`R!QddR}0 z<EM#mYoF*`H*2r<?ku6mX(C<0x}&;G)Iy_cX{T7sN%k>Ltk_^V0d}b;tRjB5jVkXG zDY0giSzVUp(bP5S+7N$2zQRrwkVh?5pWzk}&fh1`SaG9_;nruSCqc^6+L5kO;xkK6 z8^!v^@D@#meBKnVA5Yh;jz{Ox+;!US7b_PFn0ydaA0tKe6a#i5DReu7$W}+La-W)X zsJ0%WDp9Lr-a9r=en!%CUF+^;*aE}57g?^iT!6fA-&K+k{ReB&@XOAol5jieEyZox z{W|4QO<&e6J~8V&qL);TFTq8gR0k5`nWCXMA@zAlkWe5RPVfngvm)+|-vC&N`6Nk` zm($AtYyl`@w1_~z`)fWE?~x*Ft%t?YoK=LkN3ESraf#MH(1|*9;o>vsi^6e>#f5-Q zNB1IZfF7C*mtq3QGQqe_(y`<2qZT@M6h|M+Nt+cBk<Esv#}Y=;N31m*R%xQROIN9M zfWW}=Bk%=v*A=iz*TNhiDxG!)vhcHH$*ghf7YP_1PmkTH$zSpaev<j^DdM!qj}|-i zz|g3AL~dsLaiG$+b+Dqx6ji?M!DNfPxYb!ohrsi_@ttEcO`j;cJvc>5&W%ZwvRX9+ z+zgkFDdA_nVTw7d<4wgJc&2`d_rEHw?_YD&v@N{<G0%VUmgAYk#QXR!z1knGnlF>i z?QpMTnA25H)qFE@uiH{q-gl_MP;O&aReaRDU2QPzA$U)dXLXjvEuHUbtbh3mu3cj7 z&hwc7MdtAq?54FUIt$(aP(nDq7;BxxeDUATYBaH>I-W86pONCRLv}&m#lMgr`!(^| zqU+JeDR~sjO=PyRrKl813Zk`vkWyn}x$^)vU4#I1o~95145&t|tcWE>3V=E$I!4oo zGzeyI@{Jo7F;5d%%8xAKlhJQYAs37ol!pe3{r8sNm`l;>)<r=_h;iE&=yLNGQ&XrL z&<tGDYKZj?e1^p<D<Gt$IT57wN&x6kD+GFhBve)mgTv(ny<BX>yN(o89gy-C^y-2{ z$`L?l39%~?ZEf)OvW!`1e0J+Rv5@U3Xa5><5oGt%F|%!abY7lc?*+_d-`HKgD;tKk zLZZOn0xxQ2>Y%NHGC9|-imLN+ZT+KbY_SvbVrs|G&W}VuSAGTsYPRs)ZFr_66LFYf z>JBgSiZ^Ec6Q=VsD((E@i>2rXndZl)41VF2vV8bf4a^dXa6y@|>bA1p3{8i5eaYl$ zPr7c)pN!Nyqm1ix!&!c-x4r)M5i@FD{;u0}0~>}hHdM?^4By-_$3J9sjcF@;v2V7f z;%hT`+f9mt%BmEal7H?e$TNqQV`Ae7lI56zu-s^jjFzWG!4|Gzo^DC#+JNv8IDoqn z9ilyfY^f93rxP7RBx#n#{)(X&0dR=z2}DLn0OX`(#A}Pl-z8iXTe<SOM}*>v%gtey zk*%}rPy}e8-AqUBwmSO-9K$MbcdnH9-1y|1z4$#<SNV3mVv6&*`xnXt`^3jSk_3i| z``TKM74*Nh2z-XVODE5T8{J}`Lb%>5wsj^xl4fH^^8B*|$J1qJULagE{2HRfQUkjY zd!6kgO)}eb^Fg@7xy&I@a=Bb>Y{4g;pJSD-?`vM^);lVv6ctj+h`$P+kmu~muEa0% z*e}Z8Qb^h^0M({+H<hLO3UAkJL-)jFG|M=DoUf_#u}2w|j<FD0!`_w;<woy%mW|$= z{ZSu`saS<Wd{wa$C+2b*68PzZxyTkN2V!E0sztK>BPT~nGaP-FDmM*kjEt^Rd@AE4 zH+>bjqe~nP8DkS!u5T|qk%vAnO+Dwj^WnrXtamI0m*NJ1=mC&E$`GaXa-_33g`buJ zm=cHu!077QsLRSFFYySB@~G#9LuiFZJJ#sCEjhBKj~AqmWUj(?<!!Ad*b<fJ&?AZ; zWzU!DQ9}6vz}V1!wx|Z#cnCG74_Gb=gDdKmOjpH0BCUWYf^0J1H4UD$<cZH5w9dP6 z-$#b7o_H|*{N0WBloyL9AKrz_9iJ@nQ}dO7>_LYI0l7P|l5eRLff?8xv1-F<dG{Mz z(qS#~=7;4hr+X)+Jv#{SefQv001saB=C88rG~_wl=x+7HdnhTteW=CAboQyPTuHVI zp9lQ#Unx22rd^rB)H78F<2+>h4>95;6X5jEZ(~iZj3(ph9UIH~J6XB^8Y<XY?&&r0 zZglCUN%gjtJE4nw<Vk?GY8N9<%r)0g+5as!WNh)WOwP{;&3pXhZpV$mB9_eUxBm@s zcMZ5%Z@2(Hw_gXb{y`19$xUV7{>WY-&G8HNS`WXScciqYf!gSn_Yan(&)KMKMptx^ z*Ec<@z?com+&D+9kvvQBpxI&qd=}_3PtRm=<@5ooopN7tLpuN0j@CWz)Zgu>X+=5L z>kt##|6wL~t1G>DQ3$eBEFYSt_slmh!$eNs__o~V6}3-Yr!U-)(Rgb#h;}`&Jr*9$ zNNJoeb^&o#FmYk0<SwD#9+D(#MBZ4G89F%g5c;{7e>hZ`>0d}oCUhO2j-&~fMAMZl zu_Cg7Z-~PG)wMDeB2hCoE+Zmc<CyDMn9E9nTDb>oEM&8ZrlTDQ?~cnQVkBEas&%!# zB?dB%S-O28t82*-4Kjuv<77@^H0Ir;<6;3%)IY?75Md`Yk}`QPT3~2$;13oW1UJK1 ziARox!in&sUa-@nnM$PCn#O3l`dIXv@#BJ%DA_lp)(j=3q9Fb_#;m2YZft7gIA-jt z#}xurnu#h8Oi(A9jmWAziD#NxVT`6+s1+w#smI0SNl2xfcNm6JAXTF|03H`R3Zg>f zFo(W@#Axxet{L0kGJfYc_7+<mh;J?%R%iG`qLZL;<p9J!;9-z_9vut-YDJ3C96wZA z6lBYeE7%^Pph5F#5;S<rFF7fiAD-q9Alb_mJN%Cp6%iuScN5i6;XSFSb`5@tpXS@) zjw9<7ys$<?79vo=Y2w}I0UHJqL|?(tQ~bry(Pf@m%j#Jq7dmv$uLA6ei@P8|GuQ#r zm#olh%4%u)sDAo1>b4E4rUEUcgM#ko!h@`T=AeIs8+A3OU24^@57SxHcRXlLpJ`?D zS7Rdv0*PpbpSZ+}B#^NU(pbygWJBDl3T3b%ev};cQD4a$1B?DiyYvNJyH8dvVy(+z zv(BL6wcNF+Zi<@$Sdkn>ZJZ!GWB{x#U0iC(cI0Q%Q5i~D<t}QpO^|E2*y!V<a?7RR zW9V&p@HsEC4x@xG$HXZ1s7Mv+!D9tP8S|(TnXeV3nu5xaEuLX|sA~r%&Sx(tm?(8Q z%l<T@r+@;zOlZGL_=)in$6S(D)%AIAGiygfa^qqhK%zh8Vsd0-2%AOGIY^}E(FUz7 zMIs$~ky|McVOax!Q}+SRu~5cnid6B*YyiBR?a9!xww6u5R8@!o!pEmkO|59!MqV3V z`Xd7rNbACXyBF&#&)(=q*HMWdVVH7#`#@d&%ko}`&HS6N0s&e97<iFCsPN)SWbKav zG4zG1B)jJlg(9+bNQT!3Hp&MD7)ed1Kh8xmy6ShI9+_%IbsXI0ZF==srJ29Zd-lX0 zI9i+5i)#IGY8H_uHkSL3jdtxlU9*(i>`{*hsuLyyLLqs-mFdW_+P>*(=^89eTuFu) zo2i7iJt0=o<(SLB9@@t71khzV8>RupSTW`552Xz;t(pNjDq^`Nrm;xRCr9ZC-iSoF ztExUzkqeHc!eYBjUp6O5byGE}jRfu~!q6~ZD0sJwEKp2}B*X*QNTCRf_C|9&3Hmbx zlUI$#Y=e^KvkG0~TU-&tZX}N}6XIHE=0KVG8#k9JkQ)k?)Wv6m4CUumtcD@d+scis zk=+v*mv$;G{)7g=w~`)#F+?S9>9`-%z!|21l;65%zE$N;WF&TZXrd6D`O4_etfVVv zWPs)KS!mm2RB=&*N(Of8D^sT3=<JSmM&L<g4U)5O<%5E!Cdt=rT&$@?AEOchr1Qw2 z+MWhzrvcCRZgnacRhzMK5lp=}kt!p-d1|o=yLghm6yZNdPxa==Uy5x)f4eEObOu$| z<vUV-QI1hS>?yc3fWFyso>6WyRPM_UybRU`+?ly7yuiT_{o1Q+(vl8t&eJckyWnv? zNNT~~Hq<f#fIf%P>jjJ`a$+pdu=jpA;&nuKp(XJgaR2I|bM`&`>8+#P@FEKa0WdIt zk}#%UQ>Ft{9(0f&pdKZHJZI3gL6{<Yabz+wTFYIVBeM0_k)P40F^$pQZ;>E3%AT$I z*=%Ix=}{Wn5ft3;2N&ae;;`;hTIoh~KrY&HsCvBDQGc{iryINhyrHyT%CB8{XuBWD z)2>wFw4CcPRpIpUFSsfbpx(an1UTuKDpre1Km6c82Cz`|ZFQAB12QB~C?3udajnP8 zTh)QEGSY!RQx$jLTpI4a(d(h1RnbbwPDHm!ohjXJHlm4}ojd~$CHHBy;Vb#sM8=te zX?Wi)K3@?qD>IHVWOVTgqC_0iMncx1ZX@wx?69t5`&YdPUDuP*nFpP4q><MSBXoFC zE%GlK>VSr4)U&#{E5Fg*>^xy|;SKSKr6-57_oFVkpW8^S9jHWOP4qv#H$?1P<JB;p zSicACx;>@(F<Uf(+MTg~d%LC!LI!+^fWJI<ZGKSZNh&IP^sLb&;+idhCu>^!>6iEO z6!d}BBSbQM)C`p!LPOL6`{L5{o+sV-VvZ#`PqjC%l~XUYnEq3hyB7|yd)2ve7iC(D zsuSnVIoxdxgxZb`Ajd-fvlhRU1+p=Qp4Ew!K(oAlqsytVs6ePI2Yf`!MPJp`0$x>X z(TC>izb}WCAhsA+qY+F{PCoK4^M(YPp-gE0)62S9<1Xph$R%Z}(96-j`U41ZlX$pm z5*3!%#fO&|%=n<1a;C|IqqOz7K@2^hh#u-U5qGjx#eY6}D%Vj&0el77j{Ff;a|$Ds zOQvs<ubxBcBOV}VXJXUjnGz|HH8)G8ss>&$h@ahh^3a~gcvH9CVi8_<pQOpx?MlOn z0M%D?&W2h4Rh^rqi(_(j^dT83kBq&)cAS+W>bF;5P1OOCjZiAefc+|5SYRBm-U(V) z6HBvphd@V8NPcU>E;k?Gu?N{Ro4FK@1mnEVD?nV>)!Hj4Eim99Uc!on3hj56XCrqC z05s}JuMNPUQ4dTz|CXL7Z6o}DpS}0%(3_@!a28aUK=0ZPn&`M$02u{1Zvb{3&`?x> zngj0T4B*&)^&<nq^DDjL#SZv70DlG`Ey>8_T#-2U5}>PVRlV;J?xr-kZ}K0m-d<I+ zslAS<C?l32PDHwsGSQ*Kh&ZIaQM^sr3I;cIP*uWmDo5MkUB$`8_X|)S4lAjWE48{0 z-GFqk{)s{L&+Yu(_X1Ui`cB<Y=N>1eR=b_jIv0ge;RFPTQzg*Ie|N9&$5jE2%^c50 za^HJ2XpkHJm8aIBD~wqJj5DYITaBne>Ca@4i0y^JZOY$`3+m7VrccCa@d+OX1{y)o zBu4J;@?#CWn(5qD0pM^);gg5YL4d{7#yR@BG(g3P_;DDm)i^-_POPV28`bMwkQm*Y zL9MCHk-u8oN?`>2&f{p^cYn@H1kFA9*u8%5Id1a~e5`xj>@Ga$>H~2=(l@`xN;LoN z>%a|zk%||e2RdJw0!SS_J6EtTh6_G;7w|L-(BkRO8~N_q4PRW+==+}%#^o-^yADhL zbXU}SIzbUQd?wRmM!GakgB*IvJe>T>8uU!(^E&^SN!IE;-!`-g8-4mWRg!C-Q)e`B zl~lIXrfKuUw;9xFc0xcO4_Cm1IX<=S3A#6~A@cnuGN{eE7A0Sf{v?vsdr5pO%`)z^ z2dx!^|4d7+M0-}c1!_;h$1?BSKA1l!ZChrB0<BaK?r)%HoKyl|iyz3<5@7u1Q$0>! zs@h>qp?B3>grNBxc;q>Bq(J}bbD1ExtmYh;aJeh|1)f+q{{!P)G$IZ1`!je=^h^GY zk*LAwf?noJ0{7*x4cg^2C-@bbisHR^P&E(V{LnfA=#W`_6uq%>9>oI8H`Cu7nZGyj z*I3@<Hd?yi-G@Q6wG)o9@vbl%DJZ*nmG#m4DoU*$HKMP-D*4VvFN@7X$EB_@i*LG( zpbqIjiI^+HFNhVZL8GW8)l%zl+Ke9OlXd(pC1UfT$*1P!4T|WeNHoJM2Yqq#268hA zc*jWL49HHVJ+uma;XEjzla7-8`Po<j+nJ6|y7}szE6aNXl{$2jW~KT)0e!K%<7iB< z_~u$b*ggNdCVq}j@bEXVxLC&<j`}!O%K3vMcjsySFT?sCew=}Ezv!YdIPb4%X!5Pw zLB%7VVy<Hk7~tnJ5id2aw(^7yHbG97|HL(IK*pU>Upqg(cB+%^rgJT%Fg2(<AAZ)} zResDpaqhF=2Rse_aSotM`Ecjn2h;St(jPC0l%Krf&1lPae5ZaQg5b>ZJd>AdkanF7 zWkZ>3sF!vq@Vu_LX2Z2Z6It|k5ZdQd++JMcg_keT8S{H|xp8>VC!}Ck>}9&Mbpw$Y z?>8bQ7inC4Ef8RXq=!d_igi1x1LDQ1)*rZut$NHX-v0i{pd$+DE7*dTzm8V_b?>-B zyw+LtaO3xWd*>;WmBWXze}oR~TLIH<@G_Z+5YY@>o#$HMz%)+l<08Q^Y>8C;Sw=DE zVvaWaMT$5gq%Ow<ev6l~y7=0m3VtPUJ1&o?T;L|t{@IX9XDR2zYJrkgGdTs!Bk-PB zFPPk=Dq6Fqo*l}%Ia?Rrl47e8>|#W-YBqf5inA8Y#LvkOM7;AIh<iQP?EB=}k~)G9 zu<@*tltnoMJu)0mA{`$A3Xq8UtKIJEf<h4S*bGL+z3Ogpk|_YVGt1RI<sCb49RP80 zwG&(lyiR`!aW=dg^<T}W42UDi4!R9s0Dyd=e%&22jMD%<{H%2qKzp~UrVdAv;*4gF zHZ(^@WDqg{4<<kE2vYqSDIec1UqAW3{fF~6?P0QE!Xa%IVn3z75LRVjQ?^pZ`Ghjj zn(elnrcpK@uc1X2$|oL>fl~dr4(KA*!(BUwbV~fVZC;DkcstkLJk7SKZleZ7fhX7= z#$hE?iwQCY_hUHt50b5{Dg2*z5H*>Spbq9nAUY=pf^SnG%Z4s!eC)$3Lu<wH@%L3F z?(aiH-DO)FvVTdk+c;XFUgBYw6yh~;FDCHfw{5Ln?oW6_5!dc~-Ik5KBz}85n~yF9 zmuI$S6cV`~672+!MA&}9nS<}L<#R0Y;n`|~>w=0F`e}CeuwIe7)|&n`lTPA_5iuT~ zzRTB88hu)m9z(V&^7*8y#-w8bL5uQF0<yxUS4d~e@^Kb<m(;vNSRU*$(upv3??}%% zHJ-Oq-RbgD5^~1VH+JImVK@6`4E-DP$lB1f8#p8se)q6lP*AhFNah(1S|krVmTfGp zoXvN|7$xV?|BTs^O|lxZ&Ma~-dd@l_)r!nn*|^Ddq`?hUU0pa7GyIKqF(Ut+#MZp4 zmTi$7y!MUAP^P>&*U!C9HvARyfOfr5p}yiWlrG{AzmhGDPvIomg#q8tvoO-iq)LTg zJXg=^lKl?W0OvHr2zOQv&8_j6Uc^dSJq^vCJ6+8+E_PPlW$d}z-XHM4|BcyiHL*!$ zZOhMd4d4`RiT(L+Yeee#rWjfQUr_jKY+_{FM=UkN+izC)Nm|03$<KcY^A<;WY`|oq z$bX4TZlCmBxXle|?`G+t*+E>lQJLwuY-eJ*tFczYug^vz#?U3~oclDgATZ-Ug#nih z``ZQlnwZV=&@&EYsj&FXc=w(|wttvjmt8+Fqhxkp-5ikF75ZLhzWI}>O5}f#ebF4~ z>^>=Fdy2J+x4qCRD6bATs?3i+bEMTMGzOy0NuKM!&6>UvjZmZWtM0LG{t1F)^2c3n zbfpyO-@cnxF84AdG6T(%o{aHNn7*Z&Bl27$EK-``MKRF6!(hr1#X^CzXU}M}14A>` zeiI*vVvwIA3M`NMOpyO2fd-8x>E2nnv!XdgZlUT7q14r8_n%f;*|dTXo_vVJLpEx= zj&|WxXygB;^+f1Y{US5t(P^P~<t;sS3uoa*MDnN&sbG@h-QX4Y9<xPp;%?zQe43o_ zPfJu}G<DC+2aZH$7mw*f;(u9Kq0LrME(dQ7Vce{r&Qt=@UQqLg$=H{@c%)kcMx<d^ zToSKi+JTxsC+QCV5x%JIFt1UF9IO@M;Cjs$KM|!%>CNFS?5qs4xMXpR-^hLyg}M6) z(q=!cGN*`k(6OX@mLg@ZE931r(6r)T3kaULZo$F+n3&%5(0s`?=K5Hf(}xz7!CaJK zA2v_JNZk5j+og-21@h07)|Hc{Z5s<_$}7C6?mUaev;Ir@$rC)b#?xQ4qHOmjIfV#u zv|I+gq{Y2??TgHxrr@JdEhn)b(-`<|0*j3a%||fmY=m70{B)Qp>a7&1^--`?!^hKR zLG3mT1E`>Q9kX#$25xIKd&p|9f>WbNVGg=6aq$GLB8p@RX&Ae-L99=F>+YG7nUL3# z8kS%ol~}YS<NCPJLBZBSM2DienIY&=MJJokV&^Z{V4(U{<M<TPGPdgz@yfofp@ke$ zB)kh5Uq!hm`wV6OOOsgDd~7Y=XHbI55H!+yjllgOe;l)FR4Tf1cGtG_NZ(j;)~&FX zl-#_hQ#cWSDK+6W0;_XML?mW8K<I?lQH0PpV$v@($Ru3$PtF!^DpfaI1roky!A zd|wwvHiDMQSKX0U)0HgN5G&<V$40(3$E3gMKuqFBNB+J(>~C$Gdo%I#g$_`ZTl1Qe zYmx}j{O_Utnp;Pu%#&^iCr3Km`fK)MzGVEXk%YA#=BU*8M*PUSR%PNY3UB<VT)0~H z-%{hlmKM(K)~?IPg?oH|?OdM(MbT{;hh`t;G<`k!4$UN0`#fX)@{D@et4+xp4iUc5 z6dC(gd~eAD*<;tFlo@3^vvLJR-O#$;_chARJMd{%sP_Xfmz*OogW?M*GJBb(g@i8@ zRbM=kDPG)Jprw=5meSLvJgP+2etO(e$!8(|MB;VcwG45Hp3h=I1t;D=9!ZyyP4$S^ zinlT8bmJn0M)?tbZmHQ8ucSlAP0mMB*gK^j9-yl-)niK^U=6IO+#7;KXk7LEtk<`f z@4BH+Tz&!$DQs$Xbs%2;FrbvfuPef5q!?DMJp($Tb^Rj5InpINeR>0prSfwvJ)v)g z!6u>ig~sK7>VWgSPl|PG=hK%c!+y)Y=EZHs8JCnBI>wv^4%ReqTkYRIqD7jFiHW{z z^Rd&7*|QaE!nqb#6uzug6i~00?xfr^<9#kv1855ZQfE9=^A71_73(c^&#A_N<sJo2 zwPyIeNUnPRht|(W{aegD;}?_@c!rQ3S$M>kcP>-3$%M!WCL=;@i|906CQ3(3M_|v? z+qF6HuCQGsqTemY`wC!H19H&8-uZT6kMqp$%iGY+*u*zi$DaRZg6J?P2FpDdy^q%Q z<2!^edu$JZef7L)*~yRn3#{=tWoXQwF^js@9O%YBqtma@?c1STcN%FihRbN^Wfb1$ zbYhr;G)~sc;igoUC*8IUmU)ULZ?0KxyL0*ENRi>q=i5VX(m$nNAB-7mGEJWu|8(KF z^%J!?)tQ1X*DT2}gH}%=rr1LjMIzfS%1rm#oy#50aWF%7vS3VAN_eLWOn*KIlR%&C z*tGAkp9~Uoj|EE)Uz4UTF$819nLkb&^4NydEJGCJT>?BPl0Nt?WyGL0Q@;r85H8}% zhWzdTLj*3|JUi@xW*(ttsitIggp}KJvh>+m-)oWfD5ibj9p6R5uhOjFr@+ShM^C4Y z?D~R@ZEsf=4ZM0rmia(FBvp7YHK_tXCIK0L|B~ee#HhsUt+7YT9VjYt;>w|zg_`l4 z{d!>UI4h-re*5wG!5<*^g_3Qn{QzyDYigmleOMN9kdYe6ApvY1EQ~^htIqO^HIx{+ z!&@F$>|r%E)LR*W6uqWeowA9Wk@|<-FJE|IVI5^@<9>-GejrEyh-q+TWy)@frBhkH zaS=#mgQ1v}tG{ol5_sFRNu7^(-@?>&On#U{qfF5G-As+@8bE!NzheVVvsV7=R>y)e z4t`&0|CW+61-xMuVmkG$>yVqN1+`o6uw@gh%;M+7sBYh-3EhdEL9@_x>*x<t6&Vw< zH~?%uGpf5>nR8JV0*UdnNiH~86}NDY>N0XH6`h{oSG}Y1O=i`>f}UER{Ldz1+uD^= zah$GhJIT(>aGcJNg6N0a_UT&CVr|u0Nor|ewGEQxw{hE8Tm3*Qc~j`ce_9sqS@~%c zmZ@EtrG@LhRhFJD%+{`|z^=N^uBOwjcG#{iZBm_du>uEBpSI%&*mI@q8`SL^P3@Zm zL|q3!vFg*n6u=QjdtO_eeS4>U$FO}TefGZ75>qWDlkb30O#vuRTV7Rn=rwidb9CtU zbGQ-Za5K$epul0U&f!+4!_ct9@T|k_b%&7;4tM@Jj0!l8NjZ+IJ5HE7PC7c?^>dtx za=e%3I9=d4Q|EZU)A7Nuqq6#K@zvSZe58I6P=XEgo^)JPcY18<wB+byS;{#zOxKe_ zS}hkiJ*{(E>vVedK}4Jgf9`9fGVJuyl<mZ38mD9#vcX0i@WX><3qR)_cc;Bl@^xhU zH#So>_L>wY(|CXSUMs|&P=_l+Qa9%IOfNZUb>IgWDk<PyoPYzNZqKy4vI>G;2TFIT z6#tWQ<z%Uh@)!~u4E_13Tdj1ao%p;RY981Ou{WFtU1CD+j%CALewtpg?aGv{0!me7 zeuye}V`rsEvRNqTC!EWk6z#Lrqq(OL!wrUHD^Ml_3=0#6E7XZ4A%1?C`@UZ8Ht+Ig z4X8HoXw{AimYyeAQ9&B>J~-%pZKh-q$Z#M_^0c$^1=l7>xm5v@PWmu%oqt$6_3n4V zwS{55^v837Ko-5RSZ-Dzc@3Fo%C;Ld?a;dM&^xRDnIfQ^f8d!`?E~pgan`dEOxy%q zglhaz>qwz^wV|4}_GuBCS3fz`b#Ol~E<g83>owhFQNt=Xu~C~rYOi$1B9m}%m370l zf^2x@u5M-?HINDVR%*VX+H$3#VPTQncX+dpJKOfxV}|XLKbmRepQ|q-fO(}|IojCL z0QC14aV5AHpq6e8xFNBYH{Ke}8!gqhGD2AVksoteRSlSqCI4#3$=4;u=?Yt8cYpmu z<HVl?GSmxK9}ewOk)`rv_%Y4T7Vfu?rS;nZO;(;ST#TZB%uUx5ck6i)z2%uX;OSWn zk?JuNi(PJIYlgFWFXwxm4ti2QJw3=d*3z)bB$TgA)(u7;40VO2>={Q4Tdc;bpZzgn zmaAL{WB7;&n3gnE5Lg$3R$|c|FkQP_8NmE=S}s;Br}<SZm2v#xu_mXr<jKB~v-v#! z%*SJa3V3>KmR)OBxiot_v0x~oBZmMv^}yp1v0k(_lgx$~*s3->7P^ntt{fl?b4T0% zJ5u*r#NPxcO+9Kft#kEUfh54`&UartU|s!{mx!w2qcOZhc$VD&`1mXDu_6i0hk4~B z5%E>WBN0!@R{1I@rfoRb?a$&oy!rd^THkZ2`$lwzR1x@hQ+ri<zVt6&3Ao>Ung9GG zn{!)IoDH_?Vv>v8MBRNh1Ycx)Ynm%S{5M0nhf=KlDi7rsG=Al#{zYGuAT#S<xD(-Z z%tYf*y1?hQx-CHh4$!f~2=E~f_DsmFx(k2hvMX%0x0malmMo+3x(ldV*ec!v3n1cj zmtObVOquq}tu;yDcdq-355hVA!d~q|%&LasFcF4{0&Bm?bXkjv4d5RM3~j0vx4nEQ zb$STZlM8shscLd>fP)M7w=@Py!C5Np0pF*MA7s`oCJDG2UJaYQbe*85hn5mcE?94r zW*KeV44*3SU3t_kTeZ+HDI?(WWo3`ZrZ<X+X~^C@6fttokfq*ejrU*uPf+y!=33T3 z?Mk}9sr8l0xGqMOuRuVEf#`&qM@V)`hw^!T<E-lm5rOWl%vWV#qkRkWomT|{D<0_x zv0xxFB4}=~Kijs2V#;;{gqrWv+j77pO_FI%kkeKze9tNNsYUjFlQItjvE{v>X8~Ad z6<L~T2$%b7S^;@7p2B;NO>K#AwUrRkoR2-<c5yBwU?<G~)p~%?4r@Mie$dsl1z(Wi z;`-;6c;_Kf3mB3ni;hP4EjrB;Co#7;;C!arix*iamRU;{poNmT;Yy8rlC@tS5*?Bp z{YE8J>vbve8S&-dblXoeID#Iz?R~$V9e()d!d4cl<(oe{=_!LRwc(i11w*VR)e~-t zEaCn}-}o<7Fn-I<3tSKo><+k%t$OvnsM^#F?z%gaw#a!f^F}jyyDswuKjq{sQPLEr z<aGYl74B|JQvYSOrG;_!5?9J{m~*10A>+RjpCTA-o80eBx(AwET>_o^RB5N{uw_1G zu_aElq&yIAK+V#pf+3J{M)Junq4zK3%9C1X6Aud#BqCjPnvZ^I8bGcHMze3006&I; zMQ!z&J9TMOy+aZ=0w2n=2G%4jWXC?A801LBd57J`m$K#+Bl}*)B;@W8SEmz#gMOpE zlXTqH+W2e2)z_Mfjp&tip77kkH**V@Q)I5L^$tQ5*&i>-ZkC9BEkRC43_Oan$|pV1 za76ny*SCrj3r^=AVuW;SM!!1I$1l5j*BSWWJpXiRyPMYPmAq@m97_`gai6q(tZJB5 z4@aJxd(C~8u~StjG^~@QFb?15Oq;{I$CdUHHyu?@-BRG4aPOi+5}sAvF;}kPU9B`^ zl}95yz6Z`CG;#-m(jN!0=3Am1;F_ilbvtjFsDW#1Ok*n800jv<{}$O(xss<g9TD&s z@ir^GJFAO{8P?l+S_Jwi^|QN^n$a2C@b==0#itVFwOgJ8WZ*xuXqiu+dBy<)`!eV| z`8#hZ-nu%GQu%cJmBAF%;ds8G=2phWoPL4r?mg<El^^}9Yq}P<K4%Yb@T*M8s>?Vw zP<3F%ZB(u>K)Bn7ZCvHng(ueJ_LiBm&&hcq)}B2AMzdBSl+!v->q}-ztEubrTk6iI z*REMqW?B4C&8MYX=daRibs3AJD;p725O~{>`|<_PJdf@)pq9x7J~{`tY|pgi+)}9q zCM=6?tyQIlsj^<}s>NS!Pi9*%^OYpo*MGzXeEMD{%W^!&|M%+GwvCaw&Vd%>-J6lh z)ZA01WAc}z5&x6Bwi7M#GeO&1vafH9(!lPmmXjF{Q5B=^d1D|6m07C$^|-*-{wnHI z7hk~m1H0)U?6*JiZQ&oWRVSE)SpWak+(B2~Tr)A=T~3nW7Jt|9OzT)-)k<@+E{ntl z<k}di#W_Piog|iDHe}BjjN0YiXts6!Dt-O_TZDwy*Y8yttgb|i%qIQV7g8F(D}r0e zW}2Xw#<5vz36aNNrq;t$jLzqm|F=3c-|s|Z@jB=l>_g}{$zN!XxXaZhXOV6U?Unw> zlOpHOXfR319j#`AqE}68#dBhx2|f;IqV#fCfk|N^J#SU*2{O3(7EgXpxV_?|iwMg< zquE~G(k^VrxOIQ+WSbxQ(!0m92YmYXo80*n3fNQiMmGhYC0Sh^cg`~qV{5iZaPe`e zX{YFL4-M@zSA7e$)Ps)|hMsM7n(mo<@NJ!j=h&9E)FLlmL=0pBdp@N;yYrv+{j%os zxy3h5d?bb1?TX_vke|jvxgK>|a_|h%wfaDYN>P@vS5_x-O{?w8L)vne*4e_Y#^Dp} zv};UC``^L0xl$Qf#u-_SmBX@o2x;4Mo<ts9<Zgae(^(+IW8>gduP;svh9zgtpV|0! zI)lWrpUTaQfyg?x#u6v8g$^P8+`0(L?&X1wri?AZRHiOIFIXFGJ)P@DP%JBr!`i#M z>D1fCf#>AOrvpaomg1FM$|`hjk(2UZvyx5gp`Fu3yOXxAiZ=+asjykB;TrtxgfZC4 z8dolwH(N!quQQH{9A(C}D?PgbM~E_sMb3EznzE<wPq%P61+KDT!;gQsuVUj<MeC<C zFS_5XM2EtN^pnj6@#`aY@2c&m+)fWT7kn1+c%Eq_HRWmgB}l5u)KVqw@eq%2slr9c zAmDjy$*BX~$l#3k5V7@jZc^r?^pTQrJ8AwG8Mas2w>~Ulx758XaLbv>)cqpWnf?h$ zEUi@wEfQ@PdMH)c?AUyCj1%tOIb?Tnv2q;yOeTLBoSt~eM(C=NA6c{W;IR?f&2&wN zHWP9wSL9PN1%#1HYnHKoOCnO}nJKCrR6&t#aYg;)CIRUIIz~RM2=TJkQ)W@6bFTvB zRP_q<aE^uqr4aII!=>OL(*dZBb<(#oaYtiIrRJJbJx^O|V-AXh>Jk>cuUtB_Rb7q8 zHlt+ezSfKT-VB*BJ=SFj#@l&;4~!>8bZqlIYHVD8-y6&G*V<kq+<7PDCo+}lNmA!L zP2FvdDX2p1Gq6FsROO^myp2emvplQD`WA<qejSl$W4)&#Z(npM_*Q8b7WxOJy!EyV zbrsg8vSXPqi+>((XvzeigY7jfT2}NWS|I7Kdgfax*7aSS#D+wlP5uju2IzRfY9Eh= zw6P{liizm99K|E_8>JhhVpLof{y8Opd<1Fv+;aY1_zpsS_8B&4;(H>jGqG#TqDXVM z_R6$esb9~GQe$1ueYM{8o>11)HBp5-=U4d7VM}vS$`XRR^NJ$%sMi)6|DH7U{!frT zOwG4DI`H*jwxVSR5=HZUZBd~qAob7;(eNH&bkz2g&%3kFuD9~E;-0w;Lz^GYuPIfj zp{@$GdmA{a0M6N4o0uj>Su1_l+d{P3d+tBcdYArHsA{hWZOQSO?jtRVHu2?1XsgdR zMwv{yldq1zep`N0+<tF4s_7mR7;R-pN3UMY-TI9<H0U?<@#d@gp}nE6FNQv~eP1r~ zJ=IGX3`=&A2XD5{nl1zgpT4&6ULZFo)Z!}rB4$OYsqMs;R=1X!s<z{H=Gl{!rQm7f zlkTk9t!m+rS03a`sMoPaAx&N)U;8@K`%ETdl-NsyGB*?-H$(jpaX#d;1|n7ad32>@ zUzt#6V*MMla4+p#!a<vS@dlA!7Eo)uj-ene6}C-Pl$Tdt@V=I`f8d<U{Cdnn^T#1% zgC(vb9vx<o0~-6M$)-rjqVvNi<z%&UD~%R{)?CF$Q>TJHhQQ&%Z%~km>*o-^Um$|B zuRrF7MojrSrIqANjQ^V=HtqY6=^3j<Qu_#57BSEz^km<%K%Px2cKTVt&+*&+%~q;s z;XgVT`3$5m#is~0F)uczF%61`wTj0_n^HhRnxRKG_^mcPgR8&p3tI0QGor=g>qD2R zLC~=#O2rS9zqhc+EsBDLyf=z_`=qOKu!1Tw)rPfAGe7;bUQ#Z^?x%`2z52eNqHgWm z*^`t6y@mmfuY1m&N3k@hp8NE(6(y9bR(#3zy6M~E!91tW8cl^Uiz}8zgD8is5+c1X zUlg6Gk0XT|C2rfrDfT>E_Hs)VG;;Ze4<1<lJXry@oH31=lEH;K8*kYGjn7pVlXbRn zVY9Zq@>OW4Ym1gpBKJ7GWNH*kDkeUwWg~xGK{ZXEs<W}5-U%K=Io(ar&(2~T>9|43 zp@PCYKI8&U<0aCqb=&Oy+ryCnz(J=Vz(?x>s2=a3tR-UY3<vz5q<al#`u`s|{@Ltg zn3-XYZOm!T=VRH4keFjg&ZLk-gif28Gd0JAm_yFVDe3Sn$3iNnB&iURC{!wye*V}0 z-fry1c4ODB_viI~J)SOnEvzQCfx+FFkM@QVd}HWI!d?F!n)ypG<5qUfojaaZ3&qdY zzj3hI)1L%<TMmwN=QB?Wwo<KjuW~7Wo@$|5Ym79uZgWQPFzvJ+ACd9rY!@uSY5J4* z#GvHvnHLR&V$z3<nAoJRExa<J99g2+I3v|fQ3WLe*=s}hJ^7h`!it)>h<H-<%WtYm z^v(_bAYU&@7jZG3EQxOX`eoY5N2kPI1Vt+o%2d<fM`1S_rI;qg=y&3a1a?&kZF2PG zf8$Pi;-zV4k_vJzh>t2*`Gb_>wha3;>8MhuFRefCt=*J3?1qq9qQI;j*!+9FhxTDG zMi6L{!WjrhZX8hv^LvKlf1trXz{GD~r7pb8Rdux%`$W#@Wz`X0^S#M%F}7Ow%Frmh zuXG%1>&YpFGs_Jo#X3DXK94&m2ni5zv*RzPWa?ux%5<E{aTs^CyV(vE+Oye~zuy+_ z-WTsII%h5SYW3=qvbmee;a|-3qPe$nZxKYphGM(?U7iF7cI&W*E^D;UChKzCR2b_& zsm8r?tJbYTW7kumS6;0cxZzhCbb~X_v-MwR-xuhSLo(IJ%)hPmGxaR_3A*Fchsu4c zb61BmwZc}N-=li?y(3RZmCh;i&g$FqBAY^mBo8V5AQ-kg6dP65<FKEw{_TwnJ2MGI zt?G;jtATA(q)6;GWW?gw7E?Qe`#WK?dE1Zwq0<QWi*|pms`bQQ5{Z8^{@1~n-I2eu z>0Dd&TIP`8Sl|=`G%G5|uNX=6J0wp?H6EOQ2ZqPXEU+Fi9}~uYYo@hZgkDLs+|_FT zKyeb2{14qDVnk@m`}P2%XBAq;o6Jow^INa+OJwY*)sj!s42vU@!~9KDw2P^#kM{1@ zju9veiouY$_Y5oy`d>3Ap0nNQr4U#a`?fNk`LmHLnWo$h&Y@0(hktLpZTA8h+>+#% z9sA7AxJPW)^p!N#{BddRJP-6@0Rtx0DlcAEA&d1Q$7fa&PG)L2^=MVeye}L1x>(dB zKZx-^d^0T03L#QjCs8gU?wgBB-_+)=^QHRR$R!I`#8J*(kdzjukB3ekBIUi@+{zwf z=Cb1!=w1E6dP%|ID%!TQdby{Q!y+g@yiKW7S(u({ETN(d&P(kTE_L_Fu3n1TkzCTG z=V1?fysO|675zkc*g{po#B!iqW3rPv-bFyl%7olsKATtyKBi!gXr{(wM9%ynAP+yN zdfTXV$XE*cJr;2{%V+x^-&|k_7$3=G2ZzW4Em9}CW}GSRfZL;{^lN-Dp7ot%#ZB*E zclN!yL>arptLTz>+`H$#BUBdEzq(t{rAKO!b#*N#Is}5udeYK8ccB^(wA#z1Jmn`# z9ACs=><39_jqg;vOV~SgVoItcVZt$4q!+BbL<f|6qSOi?eFrG#hZJcXWd^fe)pUVm z=Ez*E18p(q4(lp<SnOeP{z64Re}YuV3d5?S8)grZ7IUV$AKB%uKS3qDrcDc3???Td zCGRn;q#!@4@r=+}*y09Rri+3qW6cogI~Cqk^;!Nu?wO_C0xI*^tnrd-V1g4!+Kyn? zCH-I8K>-d-{0>68Kaq)A8}0u#^Eb>{R$G8R_zWr!8SUxcdoU<v2b%1GjBmo?Y<zX3 z6zJSuFwvdQ^ASjCE<_y<#J|y@!XO7;OgmQH@DR=1q_eAEhp=X!uHkn+4hyK$<p};% zpq!Ra_&4O$)9Nbf{mRl~DJm@@=SF~unDSd5{n2%n{r45rnTDK|Svw@Lm^|XFdIqM{ zb`aT7m?oROK`e`KxAH4}x4geB1i@ywTAJ%3E@O8ON$!>@-|AO}5s{GrPsH3pR$iDr zVx8RYA)CUEBR(C5RwLsl?mz<x@^m>5ui%(>Pk8_#tvsHwk4krtRpQii%hF}A2gNy( znn6bb16-NG0n>^&yze8By=!CaHCI!Z8yGNTU#}OFbeI~A=4PB21i6TF{wdOb3>4VR z9JEDph;^8sk+Zj;fd@_dZ4PILOs3Js$Ty?P(5EgRBuUVuQa@Y+i*+sKY$%|bt3$MF z{3l-}&<Cij84F!HYGx^blNUyT6v-|fpG<@in6Im|`Dr|X*6(sQo&8F5;RC@k)Ru}1 zX)-}9s`r`Ua1q&aI{nRJ^v-aRz}`aCZoC{RjQZwH)<*InfdRR&dU7yD_DBboU-NOW zE?u#AS?t#`vl{R!&WqRg^QiprkDry4z2s&(t(Re?uN!c-l4H=Re8F@2nqyg7$NUKw zCN=zIzn~zlz<~2TeCE4#7IKaCVZVn@8Oy(tZII&;;-1*w)or{`<X?UD@YHqMUNsw0 zAb7v@&(NiHn`_j;Qn8a(vWr1TnN;pAC0b1RK{pYim6acNnRfrF_t{5Ei{!LRDmiJ7 zhdgq-H|7tv4&YfKu3ao`d5+?k&+(>2W`9ffHbuPr+p%(+z^-g3uhNx;Hwwt<Zi*7; z<!o>;f_kNrg$h(9*$rFiL!!#ay9FLj&Yw9w`(4D;k5d;#5*9v`d*aURX{}u!8lv7b zf=IS$iXKWNXORzOcLtWH>-D1q#hMajN>2o*QHl3K(vy@L??-ulb;nED_-+tW%mpNK z{zGtSFLAWzx_$4dN*~2pkW3Ru)~>g##<uq7@x9k#U7&ysdsJ?Ha2i;)gQ7A_X|+vP zv1ZFOQDm&y%_Pnna^3O3WGR;(X>`yDm)^!<N>e9P)tY^C9Mo=AdF-chhZ9A56m-k5 z@!^dgX#}`Vo)c%dS|8LS#`L0Ky%LpJOF)Zql`ZUu+^X~8fCrlWl_Yid#N4AQ`FY-N z{u>Lp;hICueS@l~<a@At_%;~-;cxYef}BeRVI0}+bL{IEz+^mjbt+*=w{VR*t=#iS zUC#sm2`^+&SqK^ac;(TI&9&fHOND$h+5Kgnr^>n$rqmO!HC3>K_?YH<oDwD2_<fJ< z`*C?lpZ~hvi$tt7NZ4AD9wR8c(Op+4D{<@nzc(dK-tJ<XGE?iL)!x@;Up3ZyI9)om z?qqP|30qMW*Bgvmdm<n9_F33lsn1Rx;}>(^^lz%?!scv_HNF_LrGR*E?3U*bOuUuH zFK^LbAU`LGXx@nWyrRj>o8vXs-#D^ljgJfu1Kh?MW@fHf^Ja5SIi1ivKlPa!-weLE zG<7okGgwPRh%JSVSlpc{R>9sBD{Zd-kFqJXUT;I)YyiFXoL04t7?>)Sp;t(4gls5{ zt)JDRt!e6SYfg!u`dJyV)9_`dE#mjxn>3cz?@JNqO{dR4TKn>V8L_+iWp^v$-;NgW z=*!Nth!A=}@09xPZUk6u1FRRxXSVSf(y{~7{35?PRrZB1AQBe30XwbD^9J$B?B!5d zAUsPH%MQZzimH=Ab{h1^UQrd+-UT8M9^i{n45n+B0#rUC8MGI7QQ3PZPsH#4NN9u> zOY~1TRZyF0yXQvtZwM-r`9gvm25ZqlAU+%m!PhDZG#w3Li_)V&c2Qy$Rs>`6Ug!Ws zWbt(??}FnZWu9!xOhn0Q6)0%~NBCErWxM&m(8Y-?Fp&)QqEN|+a(rZh8AnOwz1-f0 z0=*~Dyc-YSI;&I!g6JwLcS~gID5`DI^jS>2fbJ72M+M%t&jKQDT%e%VjX4BU7Hk6} zw$NsDLSQsl8?X(bs5|J;aJ?E6VKlEEkdixKPL9!!(l}C}APsyrrGvB}>hLyviH@y0 zOSMY(Xb4zKt=rxlq;*@{7Sc=l5(VyxK7{Ml{h}jqZ$QgT7tGs&zTPySIK7|w`s@C7 zJFI(~g7UO74T3dx=fiVMEeb5uAow*six1I(A(|G-Mf=QHD-9y&q&BEH@VW6_T^biW zX{rw(SbF!M@_gMwMi8=@yOkct{mj=rb}R`BIM6$2qTOf*ZCl?&YqKrBHHf|zr(3DW zzDm!^%!<(R!5-Zq+QD&WZngh4>^~f*4*&)ZAr$HtoyH-(0|Bvaq2Jw3$DYvcb~eM= znDvXLox&nc8mn<Uk_`3+l(d`Qoqy?gD7%Bm5PZuATQj=2F%CrLfbPdy-h+ZCwdnfM z?DX%{jSgx@jLsLjpP7C|B~|yy+EMsvs@Ep<{CCAK950IkP${$ZkaX-XQ;zRV11B11 z*fb_cjpJ=`3n<l=iHi+;vK=;YCR~|rXXXx4Axr)4ND^XYRD#8KjoraKw$j`;Ydy}f z_7A|?Hd5fE%RNh4T*p42j-<a|qsu$#dYk|YSCBdoA+YLq8+wYbn`#Czu_!oUMvqW1 zI+SE+TW4@?iW$il(#%IU9Ik{Me;#|f{fD!qE}eLWinyHwG9pEObAI)M@zBUt#(>@* z7iU2h520WKJCiEDQw8Hs85!yDbu(!kCB}CJW*m4;55(<teSIdQ@n=SR7fke45`k<` zMa84_d~X_NRe>p5dnc_P69Gt?SrHK5MGm1bpTsjA=skQYzxZV4PHElAortF9MbjdU zfb&r_w7#<d$3__kGJl`mUJH2L2?#U>;<xGT%28&JUFDYJ`!&u?R&oe)`sT_UGYc{0 z$ru`zZ7tlL8~}3tZS0?ENNq8>_~TZ^?SV{X_YmcxvwEB;XZIhGY@e?><?DAMq`#H7 zA7}EkASaZkfuCQ~Kj~n*&t&pB2=dOV-WrhVX9@PRW{b}@J=tmccgbK}T{+$q5M*hZ zO@p{>xqaP50fy%?ZY#<79(AzNXLpbn?^4ttsan4;91o&JQuo%!TLkD=ufzqq{HQeJ zh$B{;%{b9<akTp;E*@Wx1(@{O8d5_}0n9)>DwawuiKBUKQ$w1`3IQcd!+_fm%IhvN zx}*4DyR#Tzt443;Bi|S3zaMHuW8I55y~C2;CD%{vgoIr(K|PA*tPh;~^Em1LkV@49 z=X=%;2{i6+9_pu^1*g(NEJlsquRJ|u0izr=OHekZVNK8Nkq?{aY}=Ll6gb1o=(7&Q zn6au}(KVe;1<v?EJgxNiA&dTJSIqu^$)J|Fjw<%Z?;q~>^d}VPEM?AxvR|~w{efy- zvH$KRncSr^{`THXXerr$4t0mRa=XBSt`F|cG5YIlS#>h?ervAxQ3PrmwmW|aF2mIj zhG;BIn5r88rpg!t9siy4iB_0k{-L7v+b(w|z4#rVa*p&qo;LXB!087|M=t1R#yq$9 z-FMrv*(aV__w~Tz15_8|73u{pjpLMQMBOdDH(?67?xR4L!GB8q%lrL+VZpf|_0PWR z{-mDq>vI>_*Dl7~dqCyIeZBXm(}J^M@!xwUF84eA#q8T)L8{nFx8Ncm_LJFk(-Exb z!tN?u#19S&ZIGqUpS%`EmEIr=&30pferd-#gt&e@+K-wnVC2~FEpo0mDQD4TC@N`K zno>(V^X;d|BE>1DX0E6w;Au5ijgoQpXIs_vD+Mx6(LcAAl?u%gNcn+5kF#W)S0mRF zI`D_DS92@xMuAt;Yn&-;HnZ=&m5^K{*>Ro!WUxwM?J2j66|wNg&cr?L%g@rulbb)a z!Hc40$keDoUB?Ld!?Jgh_$3U_<8*dOGyum(9@Sw401yZeKc15p2&9-&bIe%{;2{s9 z<|%dGio8d{_F7r;R}*{Ha{1Pd8Q+TvuWmY`MeH^vCp|)mOL3Wk)_#k#vP`3kvr&n` zK(&N;W%$twz9BeKi7Oc7xAe%}^lU^Ev_5tSZ)x<PiSa$Mx<>l+>R?H0;$*Qw?1=n@ z#D0hjw;L>E&Q-=$HYC;_t~3Q*>i--v-&5z#<)f&|m4d2`-0QR(WYsAxJ+)->Jpu`q z1xc=B)Gby~n1RNd5b?M8oLU1XV;xw5pt)sF-SmozwUk;v=rI?T&@)iyl(x}r;FZ-= zR}~qrJ#?9VXNxZTOg?fqSG+3Ykd1^~n8K55bJHSp33<sDjFde+F@vPokVHj$@D!dN z`1@y~aTx#(%YQ%c6><BI`8d6uTBCbeXSFx4=^<x^x!0Wmq~5C&=A|;J1ZxnYMZrm5 zR#;V?c!*pvf-@t#J}Nu3;_^t`3Dq^Of3H`8T%D(1@e{W<$?=kG*K!$p+wRf^GsOtA zfMQ*J&u!vqe}aP~-xn1>kgu5TQ?BI-Fce%60z9>b=D#`f=E9X)Yq_Q*Wkb0?x!R;G z4v7ip`xwuKo)>MXwpOU%NEA?}tH+=?eypNHowm!9{tMDpI5EdyeN3{nz~Veb%G}BC zoq|qb^gF3FyWKD@+!5ERs#!sG&lS!N?0F1IG}j|K={KPdX9*QoED}VjXm(P5=%0Ai z+|N!cb=NgpW*@njr+Gdq)o^%qx#8{h7;~)afI~$Lh%A)&DE{zDC;+w@bZOo1Pi~7% z@bA!}itJq0fv@Bl5_W)5Et4U}>GivpN0iQ0fQd)%RSnc0wVn(TvBk2$NP{@fr%mC4 zuh;G#7&g9Tfx!Y>=;#+Qmp1}NKGz48UpsT>VslgwcZ7o+>RZ$J1yM!J_6OHNn42LV zOw_6+-r9&?+@VMmX*Q+6V}FLg(T=QLh(t6zKV<Hg%!ZFZtr6lU{2bHh(zl!Y82Jkh zIE!HQce{#m@!~O3=*7BI2phD>Ij(e#Qu~F0d2RNbTv}ZRI=>(bc`I)Y5*J<nG|XOa z@MBuAaqPY!bggP7*p2Fa{0@7L`BbNF)cze7tkF%N3oPsmhI%GpLqNV>FcI+t-jWKZ z-!}AiWj1|f3itVZby~J$1%-jT(Wpo?&7OCo(hV#*`XZ@mryV{_eH9T%(In^x+J&8E z56EZ|(+h2^1r;YK=`F1~tyOa}AFUrda|KDxbLn_FBCgM_lB&<@BQjTcNlQW@0gQCs z!Ba;Rj0AfzIq`j;d2IIIJB_{?b-j4`o|NQkz8BIG`;xpj`jfK8EnOnrRTl6TIsbjy zO=OILWR(c1ICB-~heL-H4<y{b#9E+evnYZb54(WX&0_`e#e%ci>1O&{5V=Ek-z$6h zZo1f!zSst4*WlBvyP2TNjCn3=5zsy+PRIUjTujPR>M(LqfkziXWP2qF4h<(`w~`X2 z<Ov7^bD^t<oGY2Z+JjWL!OO8ODzZlgi*CCf)JyHd2k8G0dEOsI68Bo5u#6ix8$y6E z8H&Cf&sD;p2o793%l-1kfJ=jN<@g*0KXA1}2Nn%Wkga1PZ<i*|<|pe-j#%-7$FUcy zD+t$TSFj6RQxr#C;r+;4-qRui#iRJhky*!%vzqBdF%G<^^sVjn=HxQ58@o<w`&^<s zbJr-z(6oBx3{=~c=zTKTHJ&SYV1ZXR2>8@?*XX}`@u1H7Ii82cUqy*3Ntk3=U!Ys7 zEWRu_lg?bo`=&5>^s5RlykTB}#mNv*3F&53R-%C4WnMFAJLk{+tS`1Vl0T~=l`Iu2 zQXH3)V4EV8!99_H$Q!jMSU{u#_dsGhb?Kt~4{zG>ud!tmK>;ybwb;G3uTyrSxdytn zkkfNp)(8I^7R^3Wov!{uwW0XuSg<NFJKD?o22&|6|D{JOK3D;JvD3<V=%+T}Q3Huu zn&HgF2>>gJ&(B#@I%O$^W(wGxWQxeEq}#tZ?R|fW>i!s4_PM`@vKtophCN`y#ZFhf za^1|xb9s*2Sj5`!-SC5vo^kY@+Bx%8dAvq$G*uB=xZnCu!!J$S8lVkYucIPDL)uy~ zoevEkwvPSqq1nB&9Y16SLOwGQyI>hqD)%ZXQrSHnZtxP{YW{iOvBJe2OUn{}YEKD@ znqK|imiB9}zJvCT1o6op3}4oaSykI$Qds+AXOn?mcYNX911db|iC1h)<ug(3%L7+; zozq0k9a|Dwbl$C}xxJ8fzEjbdxf^76ohc5VW5<8$gR5Rkb9n4hhI5^SPzYV*45uXZ zQ{8Z#sbrC8TBUbX-5vrH&^;}pb1}5uDL?I|6piI}<0Q%D@2*U{BHJINQl$6<MsDv3 zT}UFjK0uy0de`91sW_v7n+%g_+lzu?Mo%nnI#zt8Pzg(H1{DRWP0|u+D`Y)k5+1_{ z(JtC=a$aAX!iy<{-=hl@e3a)DAMKn_MQd)nuwtX&4*C>zp{V4nUl386^?e855VDvm z6xkYj2}+1GVNeMbD_t^Y8@XnH-Jq<;r+>tsW_62(PXzk(C?t_BuF?Hwcx~TFhs{NU zR5~`!mxhY*O)jgF?_Bp!c*w-`z7jRQizi6@{B|-u(scG7-lsDvztIF;2p0<YPVW(Q zJP_f+ps#1iwsn7GeJdBRAy{U7qAXrycZzeCrq2J^T@)5YsFUYGg4W&3j_}W)Pg=!d ze#u+cS%#IRjVe?|8&LYIjI0NW@#0<=D5tDXrH@DfcY=p(m<ZEjwamNt>gh{#h<c77 zoBp%b3i0_gNu+AW^F>zADrH5$ISD8B(0r^jMWG3OV|zVIu4n(6M5XJBD18>&NlI6J zckxH+Vxrfwjr^~(I9tsF1hLFJy&l|-$D)t|p8q3^f3y4zg#}-sX<wmjA;M(+?zCbd z;`3Og{Ns^kBnFJlWiH<h)I94QD!*(=u%4&DHXKHp2IrJcq&4GF5giX|{g>?s;-6Qj z@_^#aGp9~GVffxM4*epyfQ77l66|dj9L109e!j4>p2w4i#ehp@6@f-|0^{>4gK(#E zVd1A1$<y~NL(`XB`TQhj?z4ReeV*ciCS-g7@l!Fta=JQG=%c#OXGYJ8JqzSm5x*f! zScH&V=Kk)WRolp*l|!cagA)Mj9u{0D(+3jI5s_{cnLq%#w!g&J>JjV%X~}qw<qxF# zG?J><rZtmtU6mz7*q}LyA8bIdXV?w3(Uydk!E96Z1M@F<#zBybh=io$>>z1p()ycR zDrZ-X`C4~G!Rm{Ifr7Dr>uchB@zWv_15dv(2zx>cap8&ZO%Z9w#N11figpZtRFa?r zny@;TC-=O0oQn_K7&sqx)9usVO{gIlXbCFjFWUJL+}e`+`6-w5@!z;kDTBOWDlY?N z5DL}j$NQUk&G<>cS89W@y@q$+fb6lS(Q{0S*E0nihNO~vCO1V|XyLXT2aN(R8IHm; zAD_eecY1Oaw>RlvrM2l~_*E;c?xkk?EebdnxsMJOk}r>MJI;oi^`iqA_Dd+XP%aFL zuG~zE99qc1X9O;w*}igtZ+A3EX<YmYzSJI%Y8O#=1fgew(Ro6ZGuD5GoivzFbpN=6 zzyEokWIX&Mqd~`3<5!>}grY_4zj1#Sqag&Yd$i=V@u^bKF72esp8h~2ewZd6*Vw0r z1p!#0O6}8^!?#j)Nu4)wMt1W0pn=ukZA`DuK4%S4aIBIZZlAjP5$6e|r}6Pr1qVFT zJdz~XHrKF0!JtYmVZ_vL>|^TH#Jd1i_I?<vONug~u-Dh)N3_>jnI?{YHyHR41bE4K z3$LzAVy7q_sPw;!CXlS4A)*xjuMo&1Oea5S!xE-31Xop66s5`su@vZjn7eCd*eS+p z@+kQp*}whL6>E5V!aF%mi}j`Bf|Z->Q8?6EF>S(Fh&`IcK^8Mxjzw}u(DK9|wmkMn zJn6HNDA-6j7jNi?*%1}9r%)UdRYaEgzi42Whu?zt5;1n05Tz3xTSB}K$YWo}k<Z3? zRD#E@sI*$1zQT3%fM{$+hk8Md;xhrgk!-vaa@JJPEK9KoRoN$~L(FZcKHGbgdigu9 zZ^rwu0l$295wioI;XueDVQAnVmk!(5=;_uz$3s#j_$%F}!xh_tU!QlBH>S8uUe^$! zqTlD^gceeY9pp*Q4#|^_AJW=AdCD1Z5<F=b+d-m0<b~w1y+dZA%LIwuwM8BZdlQDj z5J`!-qhk(qh7A7#mbdrOwT#-ca(#VoF`mH;=b12ZE7)ov;fw$&1V3cmGme~e2n<#g zX3IEKqZ}Irh1llhVs4r6p-Dh7cFxEVWaf+#E7PXm6+GzHc2KBN&SB5s#tiOq)+}!2 z?nU2(AOu)H5gOu)yx?@vi6sQ-!9aSDo{J}D6+MOh$x-#=h)Fyq9qJY;^zWo-42yY~ z0l;d=UW6}Xk(!(hMVjzOe7wF;Ir<}G-omH=Z{5S%MN;#uD5@2{=r4}#I`vY0fcPAU zH-~Hn1jbjU85BLmg%rVpBx(re2}}<(aZ-@V==$`kyTe{uk$C_5<eA>Ox-rZX>?Paq zsmd|@q<)s*aYc-XePXBjhe-t{Ls>jK`A<hgTG!>*QftQ>HT3s8hQW0RBU=jEwT?b+ z5w$5;@e~Ls?KZmVRweiYQXZA7ttMLe)*jEx=qHNw(j4ak{~p}+Ql_9ae+Z3e!bnqO zmMY0u*ZGz*LFEZ`yH`jq@TdR`E}jN;av9of-TS&i(d3I8myWIS3o`>=SX0H<hyr5j zgcI81c-YIko}IaqbLTMWD6h7|XSW>c?7(+&t<K;HgWnONANL<=rWVD~FySbl?x!lC zu9+nPjc0fgX#YN9T&X(A1uxHwBP_4N?v7L0E(EZKS#r(M_If<BlZtA~xg^j|B@zm= zTIA=4j63lDszYy?K$KB*#9#F3%IhGfR(x5uc<VAlf*QRCCZpzn12_;po<lR{SQ>NS z2E@{szpF_M)m6OaKy=5_b??oeWcm7MmlaLz?lX1?j!kK{J~*xP=b>ViRWn%Pj8f8) zTd>VE=Wsmd&~&<jsDS`G#qXx>Sia)V{P4%&ij{MEiA;sClAq}|xa8|UIXA7eC~QZC z>1@TcVc!}>VKtqmIf{BFc3Z+ScaO&am$)qO-!3@!!xAc&k5{^FHAObJ;b1fkQDrb# zSgx#vgc#Y+uW15L#KeCV+iC*3<T&t7gTt61qQ_K_`Z_*HTk(6#xw_AJ*@314@`;D6 z@}oG+cn4mj!~DT0R&H4yzUW8%+HmYUgA3amZ(D{E9Q~qx{cvc(uy41i9Ro^=QoL@Q zU_HH!&y*y!*vY$Ly>(Il411`z)#*9k>APPd@Wz?YpUrOk@~Y3(bBMQ?U#<s!pB``C z$bRz_y?3;0`hqVDKYpi6fnnzeU(_(`J=*=0$?#Y1*UrJSY(pLAHM2XUDms)QL3ULg zIw(g*_u<I8PO-+I!v+C4{NUJ2;o?h`(dNB%{vVuli!;5V^gcu@w&597L5zry^m7X- z4L|Ys6(hcS)cxfY1l&=~O)245pquz(%G9CS)$w-rmKVMkJFo(U*-LXLk=C(7qj?mj zDY&Fk9>u<NOln)&Ch=U{99AmgR#>;CN`-%<!9@xYKF34NvCcWNnuID{PAu9O{~(_^ zXv)73X)~lG$H}WW4H+u%<S$8_<n5vsSx5+iik9a;Mn;CDqw0X%8*7vp`Iy^lRvG<u z6Rq)uHSx0s0l8dg=UvnkVC8YknmMIISgbv^5m(}XEk4D<+8dF!XUN~z&v?$=f=R+> z$mq8$c-gY$&Z_@>a{leDyjjjtZn5b;IuZd=X_Qb2ZKG;(+kdv;srh&`?#j>V_yf^( z9_saA{3(9+1o&*YS!H<Gb6)Dye|Nv63j2%sNqL^d5%d+p30XS8?0q7$&+vhjWns97 z>B-}ciJ>C?Vv@AXOreMTdp`jwRks-h)Y41pQ#Hul<m)$;+q!ioH2TJ<(Q8KuA;xtt zr5_0|S|qg74w&go?_8_em50d$`weOm<U6clyyWZlnwSHLuM-HpXKy~xwJ~==5qs(% zAFmhd&D9_(OHi@+Uz<wI3f~9C9zJ)d3?T3CVy8U|HacU;*xPyNY5LEV;N23>F<Kz? zf3fdbV~@bq0%2}S9e<l0mKj*28OgW%ph|tmZHzDKiR?Nuf5Q@Ww~hQOzIi_DSfn&n zrDEi^pshcDSK`EQmHbt|?|Ghp^X+t3(cY4G$puldSKtd4;kWnv7+F%?5ygb)fKX0C zAWV43>~RGZ=BsofWd9=%yIM-N&Y5C7{ZH)zhJxC0cqJ^>F|a4(coe4%Y)($CNYC6` zGDa@ARCa31?!@l?ktC$7YfJaBv%mB@&g;AGm>rN8F{?}0Kd+qspRsYCvUQ^R72Lo| zzA|IYwj$tl>NVzER3O>8n=U4wQ}|5VpWmvMXG`{w_l<c%mn=CiDaQH}B}&Dt@=z-P zs+xS!9Y2}3XyNhdB_T5*^$-1#`Ff=4SVL)~Lp}A(+>mM_YH}`5`@o@=A43fC5)tEi zM4Il+v#=O?F8qsPJf7=JhPwMchg;EJE%E!sz{3LknDK8_OI_vF*C!p-PAp!<n@f<I zrS7c388F?hntPFs6`Rjey?n%Iuhj{G8<3P&Ugf`!b>9gRenflvs^j(Ic?N39!55~P zUQmk>LvHWRw+r4A@E*u&I5Z#nCgIEjMe3}~4B5TNB(M`7tU*9#nP#0l4mv<&D9<HO z8@mP=%t;6JOmQ*ICHp6Tw^}DpjeXh{t_*kb3AyJWZycUsYMXq!Yug0(E`cq2%K8Vx z@5h+Dh>w>PTyCqDNzQ<mJBtkozc0*NevbJhuLzD;>t7R=_y2a5;O+rGvVdKVy!I-2 zjRIK^ViydY8;Ad=FsS!YwgfEXKjby{j}F40VwU3K{e>Em5TYcn!IlbIsvg4D9JIGc zY=VLA&(hnZSEm*bha(XrXpfYztUaMf{`!+E+FED!_Im7loiTCd*dV8c{CpjvXP63? zr?Si85j!1Kb!sN|z>jC<t?ylWWe@LLEn4Yqpc!L?467A3v!5Kct!Oxw8Tn~MA`ioS zn-enOckNQFoPDt;V_tx*gK4`uEU!iFfHbxo8|i9&|Cp<w76az#0xFuK?lA6>U&T|9 zw^L^pIoj@Nq1i*17D+$WFbt>LvbKi_KP{DO>m0$?u$~@~Iz2Nx=Zk&fD4sjh^brqw zg7kuc|8Cq~n$xm~aML*V6+Bd@X2BeKV6sDj7YdLKJ0yXT?e`J^uVl{o@qOWbIckq? z2QE$kFqJtLL_CD&%(ng};^KntXCHz1Pv!`gsL<2tVbyzrSc(Y;Oi?h=$5HZk$+uGI zCuMMXE}~+c3<lpFF2)1%k(-O9<`8rI5kq7&Qc*VsDQLm2l(%z_)n`IE@I*_77wX#h z1eqkWG>Z4zPftoZIc7Y{I9QYKdr(Z3m_c``UKFQ9SNDS{x~Bailq7sI!5NawKan4! z(V<x2Z%?P$x>^%$@-dr{Zk}fk+;Tc-#;xRDQ4YZ_l~}l~p#3#4ZRi^15$<TI=u_W7 z>N$}`tE#5XRZ;-6-J>S?5IpRI$2qO1$0b2cpWP(mRNn-95bErXctq{VdG9C!?uKOB zD%YB~ht|Ta!UCT6oZ(&syc)Tn`ieH0@bPe^ZrUx+Wx($7s~K+FZgt{q$zUxZ-&c3w ziRaV<`@)q@*uKcU=l-xDxo|BQPKHGU{k*H+9Q5u#(q=!Fd8BEfSi1?j>Hw>`t3V4t zO%iCQqXw#}>Sg!=8ljx=(s>^WTRFf?udb)^mN(F<nlUktX(lcC<M~E-EQVrgLRXa$ zuhOkd(o&wpQ<T-dh1d(fu^fFKj|#l*ELYwgJ5Y-0Sfu*h{>UK8wxWk=I_17qG{2Hq zh7%-cnmPJHS^om}GG+h>rqWURA^FKaUVZ0xRd)HxuNN^~_m2NR9Y^FzwQt|}YYk)k z>s1H#j|%xH<VP1HTK9`wMi!WJujfD3G-J)jmS9wG4xMe>4TA0EhzZ$Ks5P1=kZOAm z@U7*x0&|~yf|gCH8-t$S>4*%vY;ZL4!Rxpqub6ywK-;S(RUKjSm$!!moYw*FbH?Vb zmD{=VnggDat-`0pJ<h!l72elb0xF}<9lttjoWd&Lr#H`tw!SjiNJIy|xQb}Q)`f)Q z86>nSu@^k8TFrn+$_#sI=M|V#ALnz-KStDTE20PD)i<P32Oe=-(ytSYSFHth2haw8 zm?0q$)ftLrJh;YWF+?>?N<?*%+doiGXy|()B6iy-eM4Kx(VPNP6Tgk^Kod<xco! zd3OvTk;-U!tRe=^3FG4H0tSnBmW>{4@}lCU5xbA2{FAR%^J0)uxi96Y)T<g9Y~d0A ztGKOR(T;vXK3cX!j{QiqDT6={Q(#h+5Hw*WPJ~e=Pvzi8Zp<4k#fjf9KCAQP&AQeY zp4}?g_0D}5`^teO;Ag+P@)FH<P4QN(Kh`Uw&@_x&@aywJY}uaP&v&5z{L0Zmv5OzH zk2JJhS$8Z8Scd1h_*<Qa&iVkKUdp*^)|^4QSnmQ{na6Xd^p?-3ZR4$m&(1KvmN61& zvu|MqLYB?s^h`e*BOaV+$bmyn^vFo`bA_Of2<6fUnz9HVt{V?yxeN+8ve>UZurMta zWfHsygBtXwLN)`bZN|3}i@1dRnM&#|w@#PSQK62{8Ju_7a>T7<krSF!X(0_%g2*>m z`s<2Rgg?|4DMX0jCNf=ux*bxu8BzYL9|fqAJgXXBR2^9X*`1MbpjX>Q{xpK>_Y+OY z&>--f-cvCLALqO4S8Hi6u!#9?Dejl>3YM<3HR#*r?2&4r`9=Q7$iYOHQPq<x^>v7t zj4qu*LPo)-OoT3<ejD$!z<dcpq-{z|wLe{X5p&>(GzHSdd_vg17fkEu8@@6k3QR=X z{F6~Q6kbC-3d}wKD%FX0_U}3W`E*+7l~}XTt!SOOKVo0^Sg+-4PcGgkz5GwEGJPAE zAb5m4SC{r5o*UoFK-IsA+qb*$WQE>%fZKW{sD+EMcNYaVy$&T@yUJa1tI<c%v}k_> zSb=V-iA{%FnCvg<R!@70SYy|*WtWVMmj7Z18jVRR<QD~bwnS@3o7p2qsyQP%#8Y|K zU(*ATyf(4#9TqYQ6v>jl#K{wNDr^-o)q;*z-*p0HKSc)qtyVOvfS|a<rIA;x8G)Mv zNQ#1Bx2^LX+ulLGF`@#0Zfichg9p2N($`UB^2rnvT?+}KSe0<xQ(W3&%8q?iqJO{? zyV)jTqBbZQSzwR?#7Y^5wf%h;J>cz5V9KU>E2a+Cx?qMu#TAaY-j|{w2?Qfq1d`;K z-u3Yp-s3*uS=aqtF6G?fNbu2?h7zSGXH4l2=A#ke&tE>>j(<X6Ai7UWh`v5%7Ffm? zk7KeVdo|#86S^1O2ESJh?Zpf}==?g@-MjJ{eMG7^U+BD2tX$>I;SFWQ)&dP$GaT48 z><57(W6v7B58c{AiOqw20?TgSOvO9+X13aYefvW0v>xQmYOuAA+WRk{45QbL_FcV- zX9$Wk#fc;rk;C`S=gGf&RYx<u&+G7XD?55^4<B-pzFcyJ-J{G=&bj?(@L6woTvQ zT3H`*WK;<C@i+0t<r_})(u%<+vSR)Vq`mDj;Jah61h4PUx4QpTUaq=BLOA@=8!!Ll z{%ok%e(US!*3i2)(yy}koWfGYocP2|iBW`;9wTb%IjwM~T4dsmoG7NFDe$oTK}`np zmGfP$Epz6CMcbh2xYrimIbPJcG9kcWW4g$$zaLzQt)_uU*!=qw5RpTNjxBSkrn;X> zBx1)cF$K1|G4pj6n6v6hO(}L0#eL3$O>bz2LOUN2iU(yu{x=KZVJUaDB)i%{_=psl zd)<wX*ALw_yXh;huG{U}Z64Q%cJ^jc-mQDT?Ucpba5g3WSXkOmEsD6hwvUqlvp!Di z;un2)R0+Lf-yG0&{rsu-XY>Y+TVv}UqJ5-{35!2$mjWbV00JeV4X%@hUpXr{&4P_P z!M<bD6{2_Hx(8jO#3GMa7N5~Omr9`%FiEG824}z|z_ZTxq;}-lIy_Q24$L&_G-fJG zHlGG-Y8%r#PK46YXKzIvSjKY?!cF2%_$i8LX?s>`A5>wu9*zSmDofU)Is83(aq`4; zT9l!LLiXuo)fmgdQR~D`v@}(utOFL6l%z^wsQ4N|dyR}DElUnY32X-WvfUhO(J=_V zqcKS3<0%N8B<0A1B`$Gin9A~!?)W3i_@h|<%0B<9gJ{)gwBBH>tg;A+m%=SNeKrph zG!d`mcick)Pnn9ZW!RjS2!d>ay`zw2wZTF;Ay|-S^Us5V^RX^H#85U^b(wV+f$xjk zJpfHbrff(L!GTG`qpv?;KG&KJyUJaPir84fjEQ-*K0<eh0lUoPNEC$$-pH&Q&3wOv z`$`A;zN3eZn8E6f2|D{seG3;FQwNiMw{D|vLxHY-^fwrA`!;%2OmtcF=+GnaxAB+$ z!2mvPR{sa|1Ra=7Lw<WHEhKUj6d5Wo7XGu2b-#~^m=9~?WZ#?4k^6|{^+sun7-FsP zr>!_A@o=X(W&)-li7zL;E;5%-CrA*4G`RxSV?aZ>d?t?*RGe+NeSD$XP@`^T6-LI< znk3RfGD#F32IN~OpldgbBh!%L%2vL{BHDOpI35}k3s%u_-ao__qs?Ei%YdKcfkkzK zbwTnZrxS_Gut*l)`7ONMHnD0!RER={Ci8_cm{2{uX+|yDu)e^Y0W})U(>93_)$s)N ziekpVu6VdJIxylzjH)v7WO}k71!<C+>Cz1|HxVg~N89n6n4<ai^@0l)G3<Eo<q-Vo zZ>bTZFmYw00FKq3(c0mjt6(i+K3YKj6;;>msKNz5QY}*9frlg$1t@d}7yLyPK4usi zZrXBH+a>zc5+xRG<O>f_r$D29p{!+hp~QsRqFlA~xU8Q!pMPP$^h<w+0n6`?w#8+w zc1iN#a}ZJI-#*6G2by&dy$cd^nkl?b-!DvYfQxR39T>3td<D0-94<UxzL|8XqY(2g z)#p#j<=*#ZB@_TQa{<)CU4x4<g{8D|Mam0w04Q9`e)K|jExPXr@Gy-vbegqJ0lpWZ ziFdhUh>DBiSx?`W%ls;{&Zy2`DAJ5F(C8+eHxbJ`BkFPoT_ReN*DE1PNJmf-JV_#V zR?yS+r{VI*LKD&c1awUed&Ne?V>*vh!9gS{`q<Khd-j^u_=g`4t}`VKtxrUetUY5* z(cDzDM%8t*@95M)H&SI<Y{vDPy+8ibu8!%*IJ}KsVy4ho<oQjQ!V2cHb1H<2TuKiT z72z8y4CK=>go_}LyfhAUsU^)7#T(UGZKF%tch7*v*;iLp1qpdBIR%zRE|D`L!7%68 z;uM>^O$<No&v?sfCR%N^RT30eenUj`P22&{L8Nr?<*@lf0KQT?>as>L1`;d@PS09T z1ojt0Tihf!2XT~QmQZ5V>Q~HY_0b;%djVpN#ElB6896>i7QBc5Ymv{+;3<2Z%ip9V zKMY?&B$}6MN4`a7O$7q`J=MSLFt-UUkW3`(sQuM3IXIblfra;Zw7qZSZri?(4ksNw zE=`l7S@q6?Xl04I){}vDBz~V)^3)JQZ9VaDJT4!nR504^>lrQn2<@YE_7o&muZQn& zJly)VynRW2qm&ZkwY*|FlJy7-HjMJ!RfGrFDkT=9V<T(g<8HYrieTOGv5cm4N*YR{ zUSkNI4>0pB7Ob5c&^g_?25e;c-q<I}l>|n*s_B)dAq#yy1n1pSgH20}M2%a5lS3P2 zm(ZvC3&FZ~L@U5P9CUVn2FFCv_cb~ff159dFEADzMQ$&4D^@qVw+itZUx0Y-Ri1#* zp?O>WVs!hXuw|0>|3jJl+)5<BWLwMu=3W8@sST_uUtSQ~|G|pq5Y-Iu0DCl4nBn~{ zK<X3mlweLJFvrE&dZD5sG<JX^ET}Nxbsf}VM#~xZzmH-8swaVe@#x<;QE^Ynk4VY2 zLtOif2lnKMTT%OWR~pgMNI)PG%3>gnY;;RD+HYqb{n_|%z31WGpa+5gl({zunim0z zeXBc4dIeRGQ32^Xt<}v={6?&Lz0tC|mOAD%I_9LcJh)b+g)e#r&1N)Mw|5EXBt1Th zKZ~f<7`@GTk1v!C#CM`|c(<|hje1VE)VpDSOV9x`1Ar5Je+k&>&~3h+LS=Y8KLKgh zt*qTq6fg-3GDGWiR|_(Gj4Y1gOURk{Ew;c|O}V&X-A^%AXrQrge@Q=|CfZ1gXOr{^ zZCqMMYJ)`%gTq3L)kXT@lp`0L(7BN%dXje$evPuAKuqEwNEdN76Kv|sPOw31hB;$I z?wr!!g`Ua+YcuLTNT!qq^^wf)y|w0{&!cxzTDmjU?0fh-nQ9}?qI-a$k@cj|g`kUd zXdZe8J1qEg9n|_&$y*>DIdk-eP|i)Qo&&x2vp2Rqg(=lDrE>2|pDlgBf~NNaxjm4b z@E>QYH)fv|=v2Ks{$S+(-bKCVLpioPf1V)19nz<cpBzifRj0&s!zxtab$^O-Heg{4 zxY)6fTrxa#jtPtNeJnHvi+bM=i$=x)a918IBC-=2jm#s%PcjN`WP0S_CtT6+Bwv1m zYv`c78kiG*R13^y4i*DE0>H@FZdjx?g7z9+f=5KQz+&;^$B80^z*smhFWUD7XqSr2 z(Vlb_600O5a$3g1rQ4h25fMC?>jum{tV2$g3C|myu%AA2!-+qdJQ+@gI|$)x8F13m z@du^uB8Q=&WO&H6QJdAK1y|r7ICMAc#x2F?bLXB-{Kh@KC%LZ#z07x0Rp<E!0kLA= z=L-XX^$qd)!eheo(^uEgi}$70o20&#V3Ntrz2*R{0j+G>{E385-e`u9M*kapikzQj z_IkCpC%=Z60?*dYu7}B~j7(2vJBZeaQwkox(7>N|nST8gr;%6tPF9k)Q2Jh0^1SHF z4?>cDRgItizU3D}JZaK2pA3h~-VfEuf(!#+?u*Z-$Osd>eM>7B{$PZ|G<Tu9xWzN0 z@cHasvuDc-*ugiIpPgUd{`zix6R3alnyEG4G&zDx(SCP--fqk|OsE1n@}C;tnl|nd zv;G>|6F<AbLBoXJ8G7pw>%|@VVvIB;K`-8421QjO7pMOQ&>!H=2fsY1sqE6RXkS*n z=XDA&01z2?{(BZ)$?rgJhP42HR3+U<0XP}}k1j17)G0+jl$C*MeP*SM0y|7`06GVR zqqI*xGlO*l?wXR6otYXD=nrFnAAQpSgb>)^L3w}!;{(DEVefk{y7@yU2-;}|AUBpA z%05Ou;d2`O7}^TErU`9r`e>h{8*yk=m6B?EX|--t_wLB55NMa=hy0Y;KHYKglS4Cq zV#{mQFvLCkH`Qpwxwp8x%x9m#3x`$@;UBzxx8Z@f_yG6d)EdJNk=(t~b#Z<At$u9Y z`r*aG*-Izf|E?n)4I}@oXJfA|lzm=(@OkYL5)nANF85{Yz?aLQzE7xjzKTchF1a}j zf7W<E{t89<eE18*X9IS#x9{gY_`?lBhc8Jy82aXySxux!1l0S&r*I+WW@+YnE_(B1 z%WB<4q}-P`LOxqc%&jKNoT5ux>hHER|7~gS`>Jd4Rp009r)w6^{lA(%{A&L0>w$k? z$@{)hwZ8o~I7efCvo8N;`|z9HyKnaYzWvb8;zxaV@%iq?{O(@<-E;ThcY}y~<IleP z?%Vda*bemB4rXo(8HdVbZil^NZlC(M9l7sEw8amUA9tVqkNEN*XCMAJ|L(^{tuJ%O zCHr=NaD0BIFn^|%|I8>qdrPz;^WRVIzF)Z(zw&*4os5FsYvy<NeW-ToSJ}T`ynQ>B z7CZjJPpuqw>dJQ-9_}=~+xdFx=8xXBW{ck)KEFGezq_6{^{8v8mH&S5?|1jUKZIV3 zKjL~7=&<$v@;}25|BSr*)Bl`*k6aeu0m59U&zC<}uI(4t4@<P2BeQp}yxT8u<Vv76 zpWKxTk*KpO$9|vr{N_I<e4qE9_^qX<yX6PVz5kxwUVrm2b)V1f`JM0U?;e-?{JVH1 zaR(;K3~Zsm_i?nT{L0lWQ~|AiZJLnLVhc^!0-{3~IY?}!i#pJCEX9rlZtB9o2!I91 z6*aJMej}BZvT=*82lw%N0ssNTb0mRNAo$1ot^~H(C~E}*Ht-tLXlupte%(VFx7W0W z37J_9wuGCDZFYLk>8H)Ll1rT$z+9pp^RUT>>h@=gQ^Z_b<MqXM2aA8z8iRz_f~OtG z!j}4umIi&Ic6I%B(T+CC*E^hgq+U$e9x__$aJIL(BcGvWr6J%z-DfcA?0O{Vmc2a} z!c(Ut$LxMnwSFIFaO7Cr-%VHIp#t3rodm^B_W;L9h@0=jCY=`n<=L6}*75|XCo`1t z)pZaE6q>R=epASSi+hw^k()lrrKI43i<(j5_Qr`&O80f6_ON8HLN`B!8%Fn~=l1s` zr`y|r=2WXiuluq*jIaBoD&8}4YqNVJ@iMhl6gnq5U6h8(R!&&UmyO4nTq=W%;k<1$ zgRiy*GOu;LrW%BM+%wdN1yxD{%oI?Yv;K00vaQnr!iVC^nrm;vhl&jxB2HM%nBstD zzske<DSgLz5)DbHn@_{jVcAh>ch|b*pGmNs!~agLeUKmPx|BXO>W&@Mg&Bt=y8!V* zSL}B^XfUa%km>NgA#i^p9|Ff?L1a{_2^|XZPyra)_dWnAMO0U*%ULs702u8Ha5KRt zfYV?(qicA(eY%Svs34lf;uG(xoXKus`~gy0+~-)2BqDpc?6;g^0<Db913>!6yBGR` z^8EcWynv#xLF-p%BUmP72hI=b+W>Avq0wHv6UNskaVy8J`@%12>$E(WzrN2PpM0E( zz>oKr!4&;O)*lda4tSJ@z@r#sXox=^8;TGYcP9hJlsF*|)*nn{4+v!gAbY^oDf(3c zZ-)uOyg8r@|KJsR#8)&?x_hy6fA+dB;e67SckW$%{d5o$3nBAqre*A=fkXfZc~A`E zOD8~E2##b7A1pd~-*N=-=Nv-3A>;uNgA%*xoW@kbcGCeYOB9uu&*vzTrieNL@JF#k z_<2^Mnnd&<-vTIMMd~t0Fc9-9@w@z2J=Uwya~t4ya$=G=Y_15vkGB>{Ors~wrKf-V zEt`wQbID;kObBj)${Xwl8MmAW)w3qdSX)7iA(w#_FOqixo#Wodx<R*;6$K*>f|<Sm z!i#wF3`|SXj<YvEqlgjv{-bI_uBHnH>wm={-1)mfM}U4YnHF0^A$l%WokfvKuLi4h zgZOc*Ul8<gQXt6Y1~IwFO~Txv5<^Jd2n2~oK6Blbn#;6qaHZ(y*b||w7$I$z^0iSk zAO0h%4)=lEdxGoOn-OzGppdC4jB#++0FbP~UeRC^#}m2BCxIu$^hKUdOCkpq9bYdK zxN5+*^GE7Mf&_edMjRJ5Dr~Svum(t_wB+F{)9PiYiQL2e`KU7r2t|KWnoC-xkXaE3 zHAPPC)d<AI)b$F*cc&aiaJU-_^<+aGjZXPIcvw&)(bJS`9nTD}(Jn|DYZy+EzR!Yc zcJ=IoFHBZH>u3@Xfp~vV<k~hR!cE-!WD7l=hKm;q;Eea=y{AYZAP<X*@8%;5G>&E% zcBm1p3BIv_9jY2FPrpI!U=iOX?4|>O^81<!A8|b}yj%3F_eI_D+!|;%|8b)A-i!%Y zBn7eqbRkR=X*?+j$1VZLfViVy+7A#*^k#k;nXN_y{c*z|A&-lZ%%tx22tXOxX@Y>8 zT~4(i6wqr#rJZ3n%NcNg2Z3ZU^8DEvQ~0=1cOr89EsMV&`8zq$S6E)RvVx3sz2Qfx zYk7y{%Q^<Fe|zybE;a7DT{lEkCw1RlE^dS=Ay)nK%7uzM-ck|7N*;X>2jv}0!gdhs zapPcgZ~AA=D}?(pxgcYaDxZdk!W+)kmdSM1G6sUA+5(VNuj@cj9NweOKTOnVk&EI- zB3l<>>1x%=AsxH;NqVk?DydrUB~E`j=?F^6i9dVDk0|p$lFq~*%J2REvvS+FA$w!r zw~$?f8OCnLE(#%pB&5RZ+}6gvMA^5HBuU#4lI$TwNl3J)DD|%C>+}2l2lu%j=RD4J zuIu%BzHBL&IM!P>H<n**V~51M>mUe&M-6ha=c!QTj(>4JeFsf69^+)HOvN4|0ymgu z6!2C+gw82ld|bvjd6j}L55MAq&w7iaxes4@tgqWrnZPH6Z@w^kLL2Oq6ju5@do$C` z7RYCKkTouRz2?c=WOYK~Kw+lXg9s_M-nn;*0lA3p@xbRPsn#)+No%3P37>_QEBqC? zOypd_AMHB&Ku+Ipxk!i)cih9g|GdOS&&|hIpEBO^JzO`nb0pSEkhh~qh~B5|w%2ru zEch!|GW4PbUKDWYA_^!DU~ky;8%G^MU0Hn1<}6!mUBK+np1oS{u$ku6k^iW2B;<jM zBT&(pT(?tG16}h6NoIK-F?1%i>WCvK){??hQfMCGl&CFZAY$mMhvwVIP9~kq_*inK zVOpySpJ`>0Zv@et6y+>E`F8e=d$?qvo*;c$c`7aSN!D6+yOFhg`w{#5KLd2hG_<@N zXV;UgS@?q4gJ5*J{eBmR3P!n+M?S;Y<Iy+O&7Zul(VWk{N$fR5kn)4AowWacygJzb zU)~b*wCuZ12xt6Dwj%QX`fnV<e}M@X-AaX_d}_8IyP8JpS%1&2kh;%9&}zkJ3Tm>p zJ|O$tAwRSP)wVShjvbz!<rGekGwdqlVP9056`Jk}l0$fvAuYpmxpWPk)>e0VyX?KT zPB^m8a8M_=NovBm+{vdNpbPQ0P-Gp7agPZ2@TVCiO$y+!xncd{=AnFxDm4RReAz7x zK-xh$gC&)83;rvZVpK(Mk9@$G$DpcO=&BDyddw&t^o4>4yR^RVk$2xpRp$y87)>Aj zE~MW;6E!gdYvB+zKY%zdf4Lmo(7(+<AA>aArh}yRUDG4q^JIxTx5N>AWO(VlOQ03) z5XCB^^SKeqr_Tp2E-KEVRAD5_AHZxt2JH}+4a2bM{vl()t?7QQ4bt@t#aaY>`u#DT zg;8gMle7n}W;W>n<H2#@5W9<IKPj%$WxZl^Q*NQIj8>MDr2T~ms>GY7kx`%CVddVE zdcP`Y<+ydDiPqn(9@Cm0eUJi#%KO!`2gU`Z{?k{^Dbvd@JysY8p0)<vo6KY+L0Gnh zkrV3??a(nZpliFVd|KQH16=yghR$LY(*SF8=<jk68-GCQH_kE9q_LnmWw;f`N1?TS zav#8kx3{PO4$?Hh2yc?>qte3%Nh(xPg+kCR+m2{{IE^LpM&hUsmk!#$H?E7<5-uK^ z4d~KKa2grLP4~k>z~Amq&e9KklCV8$4xIA9Py#W=(jX`O0d-S>ZUeXtci5Oht+GMB z<R_Ucwn-TlY$}<O>PVpnVzjV$v)X>4I9wX~QFf2XVJ9UYIa3C!o22XjoZYrePkNek z6};epQ(Wky`8eD;2X67)Y;ApdZ6KSIR)Si2lGb4;>Bgn$WSfpRcff-VwKfmVcO9K6 zy^?K{qvq&Q3X4+&4d{oiNdtF#<$iV!rSBMYwF0HB&nO*+(FS0FIpr_>xg^|Lt`)2v z097#g1V!+|?i~h6weyBF@KHqgc?hUJZI|JrL~#PXow1{p+BHN0l^Ty}XlK82r|0-v zJOu#5z`Q7S_*4`yOvh6N?<A>#lq{#-5aW<F9lG&&g(6@Cc}f>_D%NyL-|6~M@T@0@ z4IF=BL&cjv8yy?ztW&NSahw6hoUUzAML)rX$qvA0(hCQJeAk@K#+I4lw3UWyB50}; zpjbChrRn+v!`i2T??S|j<_ATLv2^q}ecmw%YId*Ao{quX4`Ds1n9Q#j-@*d7&MTA8 z*@I;J@Q>s7Li7Y2LDMF)Z<=lq({wEdGA$k$O$IT;Fx4aoN8t61h^sSHQ7J>P!G44~ zOu|lK!TDBKa0Q{&LsbbU|9dvFe*Csvbsd8&I$og*aRys=mG-lz`qB28bkH4t>!ShJ z9bSWU@@T99$lo@ZgAf;YHs@<I;~%?A-FYrTenAx^Ffa|mhE89coN#OpaDm5l;N7rZ zfKFqSk+vrw9RO&#k+;>Wu3ffE*CkEU$taabP`<!{wt`RzB*yxI<PhK;oct0Cs&Cyp zZ+?9ue&&fFqxTFg18<&}J#3KxM9?48!CO)OPqLCnd*jC+WRFwbo{Ox^ntzntRwVEl zcx1ZSi+TcKPQWmB(yypt@1Bw#-_bquPN$F>pZXd3hZD4>nwtaYI!Ay+jD@*cdosey zQ?bAzg6x_ECTIXZ3=YG{FxZ~g17LhL3JgkcDs*%F5CxQaSX@Pjzm^8<5TysFF6Vn~ z2*c&141mb?8S=A_U>q_G1zc$aZ0j7o=h-bMAcs-H=G2<U_1>F}o0V1YX7qHPXc?o; z&!kmND9pBMrGTWXQl69*x_hX+hUZH;wWAC{(}ZL|dC%1YavLTIxlp<Am`O>!Pst$L zX9r}YF+h~QBF$JW$-bFFwzpOS`?u%#a3Fv50bTW#$Rw2BQx--9m!+}TWm^^wIMnr= zg1O(jyqMol^_8q{!6AM9!SYX!Qm9nIJ?g8OnfL=#T|>s*3lDs0<e8ZzZS+hrA{?S3 zD5}{*tv$6k7Vwf@iv30fj+_Clt0t12{2zDtOkD*YC+ifWU#0InDK!A{{l}?IW@5$z z9HQgMf#>)3<|+8Hn6{Q-v*UDe<=`AP;CkFC&CMxI^#MZ^7)HHW;%m^<eJLm8S5dUc zAPKrf2SIA<EET5~Ye#)aibnK6Py0LFFD*cKLo&qz(2H2!A3Z8K?N1xVJ{1LQI_jGh ze7=YBAnU<}=f_uaPNZQlhdQ3WGpA(e1BV_^pz*ZjGbfnIuW41sX-x*hW)JYJ+YtxU zPI#&M@bi;VGps?c;$;gNad}e~D<_Y%vd2y5+<5c!;YmtM%@@ZSv<!GX6d2bs)sY#t zB7o)2&M+6xf6)i7lR%OuNF4N-k_qm{yoe|Qmn~iwlp@OV;gTB`Mv15Bdp(8EC`X4a z4q>5p4ZxM`L)E<$;WI(T?84)s<AEOY2$3*~BoLA$G3R<5*a(H*T7~8Zk?`FK?<^}} zCdD)>JV0Pl9r#0Kbze&~t+~tIUpNI7cmOq=haSo<k<xx=p-y+#TA`5r={+W=9l^>^ zzCWFUX}}_#Eb51J)}Cus@Asw!2K*hk7a%#EzB!Sxf;j$r$=55Zy8^s&^+mx>V1YY8 zh&ALFv8BbD@oO9kN$4S&fAT3Y1WK26PynO%Hj6s^`Y+MlQ1%YbP#58ed5xMu*SkRK z{g5c_=2xv%_Iw)@h_zmhYJ5OAyxTJI&Pe(&Hf1*yF6<D0+dD)X@MS1{ste8l{r>8O z-*cO%^kF_@GuUTecYPK`8gq0o>u;P(J0w1j$XYW?cYJGX5kf-Q8hSL{-*$fHH*lKf zHlE@F-e2yyqX8VReNvS5o@yBp5j=g|cJ=RpE7Bhr9qR*SK^Gk8ZR$rQqf-1=7(Itt zZINnT+j;z_dU63glI+>K)z#xkmas7jRV#}9ko3crx1KU=MiDEeR-usZETE!Qu=`)f zL>@Vkr`#`)EJ1uJWtc~kQg!-((<{TIh|OEv#UWE(8>AiupT=yxR|J~GKvUHRIF8Z# zCltLrH-F#&JZ?hz{3?gb$|tE_J)8W-P#`9M<nW@F3ZggHGLW&Ne98r2hON-6{1(Ep z9<H-3$^yW*xY4?KgjE#{&s^vFujLE>*}Toq_9Sp64bAwL$~D*h%BqQWtp0O8weYI* z$}7~%F58$6G2pHx2!3l!OR`h=^Q_SybPqZ6&&5b%=;?AI_{#syFWIaGg~;@txjS@$ zpT)5k&y@dG0uc?azqA1P_*mw~%o|&9tM(m9YmmnD#QOnw=h!Q0mWt1&89mFJF{|iT zq@CMt?+QJE<_(J<$^v{}&Y3-l4sP#59?CzX9g%7Us3wLrC)>Gsj))n7?(}oYI<;CS zV&-!;<d)=RE}UyIkLzrL%O23sbr;fnXol}8cTxltj(y+jKdW>&|HE^Kf7s2@^|Kyq z@i5oQzPm%qv?}NB+){~u-{fdTOP_=9<&wY!N#Pf*=hLgdJLojaD-b=JYMjrWQ9QRx zMF)W0(d*+UjYrmL;4<$0Cne7BYcbA}I)L)>H##O<wGmKrCpz6Nc6`6rIYm_%uV<tx z2^|Knip0>uA0;jiy#9RF_ZSY+@$H}C;S}>@2Q|;(-me;!o8sw36Vax4yG1vhgZlg5 zUg|AFy!p@04~kITM2WR<`tS&F2+Ze)+!q6!eQI9q?u^GLVoDM`0;i$#cL_DFUHqTv z;fm8sKN>#$&~2ChdOm;_7fcLq3b12H;DlXIUI=~`;n;-u^*O2dmiD(JiMerpZ1<;Q zH8<ohxCavG{qNZqZt=VM5cFxAb)+M(`P14!Z>qDs9fUmC=W{xNj@bm>EO1l>v^w?s zb$-oD|K0RP5HCa~%+M($OR7%-B=*<8G*LO2#YdZ(!{vz=DlVd)Ci)N{sY>9DP-}dV zgUd<-bfp)AZc^Pt>yY+!7i-9{d5q8RxOCAeZ1}mN-%sq4;R~1GnJ_JqD&qA$?f0@@ zwdBc2d}XxV#f&(Z)-X)PxL5x_x$KfSM%6?oM}$O~wq_Fby(GkC{@0BEA0!CFfK*?( zq?490G4C%Dj$DT(kqH+edJ*+3*S2k9wWccK;5~51_0PryHj<#Na6rm4sI6MEL)sh3 zUpTIG$qp&P>DT2AR+2btb{BrtB45C^q}8r|1ACTX!VpgRR4N2<NvrBIiT&Txf6!|A zBM#(NBam{?0EBV!V?%e)>MDps+?tpXG=;)1NW_MQ2MuO7i3uiG-C7k%<5f{s#DA-; zhRJhT>m9hE8m~y1jf~<Q`W&b}yvpd(^;2?1CY-_$kMF7_eRD7|Slp))mn^PBq`3Ff zZCS#7Zcy*yNa2y4ARI;rX9`A4vRKF?I>JsP=c+{Ny<x4qlhc926xlQRaUGrHVwxWy z#?Jrcvl7;D&6^(>d(r4b<Wqeg51H5gywrQ)`{z&p8SSj}r;F&s{4xHvHd3O0*77cs z21RfwCRH`7si^XB9|StBSXEsi)peb3{LEs;5M4QV6gwafXD|YSfM8&t73xm8B!CWQ zC3;ktQ|2)+^dy-uuGWL5@tN+U=|T?1atu+wB)K$+$Z#>WG(_C1v<gw8B&`ksdvgF} zj|%{`diUkCW6#wv#Lz=MK4Nc|dlarXN93Qnaxgwu%)?1uRLr+mC*3<x6mcn%&)BXi zPC}0!xfn_p;PrrH_*}AARN+?C-3UDyS3g*KYAam%YIN@}<%*M$)~^ce!j8JZ+2^+G zm%<Tp9V%6#E^30A6l)y!WrR<JYHg0`Z`HcEhh1(Z2cgiDz7>dkB+3;7#i6`Wne}2k zrM;~3Jo!2$+bfafBpm7*RbBlmrJ@B>IE1q*pr)0!uwci8N|08W&6hMgpQ+!EawqE! z$mj8D?yC5bce{wGVV_MWU7lOtnuO#omb-_9xv0B!4~ZU;p^aOIE!AJvGt+svw|GXC z0#l0(LGy5F%-yxA-(K&ACEU<d`TOwsrl<|n?Q_Whzk%*KQWD?p&GVnR5np4^izVp{ z%Vn7#$*YuzC5tqoB|sR5B2&X>+tlf65fUET(fLS{3>mv5Y5m^8wd0~T8)5-h(Qo)9 zJn%Jkn%_hD8Nt!QaMsgiv+L1eSuD3omUe{xxEJYOIfe@oEUxZ<xlM7(_Ftmk6kp_@ zopXPMm5#o?NZNjA^d@@!GNvl<XUh5=2uiSNU{kV@%L>|BxwPaYaDnVXJDzH?QFi89 zUVl7XvI8T2R$KA%Mc88ZId1#4z_nqaO4jDB=ay!lz6&cFR8e1EdnL-FO1|t~XIu?| z*Qm^1jJ%{Qd*PfIPhktSjZ_zRHlAZ;Mr7dmeY2m-m*0>SR0!ZP%U|!j{oKV|G-Jt7 zZsV11XFp6I1jc0?i`*5B&`T|xREs6UWCgohAvMVysO#PbNx&G*4p%lT0t1KkVK}Ux z%X4O1Q+b6M#aw|9j#w!*2$aDw^Cd-M6yGEWavzrogi0t5CbxX=X+g<z^WzU(HM?{I z0egY8P<<F)7299_2cH6ohl!~l4Ey|by&vjhIQbyvYvQZab@v*l_7!sR@>A$g0hdbW z4t)<P$YWkNEIN8Y5MzLb{=C>Pc!p>U5f4mr3=x1hsfZw5+<4;sFmMF`<UaD1?6OwH z*(hErBoBcqkFM^^5&;f~u0#Kskf29I5}>7A1pxwCBI9;>>!DdFLLdevwu3085VAv1 zD-r_2kKn<YJUrx82she<?jxYaK%JBp%D4R*eO4ol-O~?8xsl<zEUsTR;4c0g<0!k` zcIL*j>}!~3TmDvsfZjUvoL38+7Xv{~);g&gF;Az`MN*-xM~_q{E>7RJCMBLPl{cg^ zE(l{G_gew6It5|GfUqcow(QK|H`&aLRt<lV`CZzUNilR%<kbZO#f4q}zRg2(?kKBE zx)Wlmtwmtb0%C3bTs>NKPyrmcQUmEqBgcE{7lALOdj#jJ<yCp16>(9;1%X}&Zj}H4 zn)xeFWoeh9gB!NDs3Bz}i*7edKxM9#9(g)BORpE+tFVf95WL1gy$-4J3LI4zgbVJ~ z1^MGsm+YBPO%L_XXU|~7OzxSWw+)Cuwu*IWuW(5uB7#Tn!0T@{TNjFL4A03Sxe+zn zS-L9RVCZ&NtOtdcC196f{a&mSa-%q2384!r%lkFfb~vC(zYO?n3jHP)rn|cb^`cy= z8iZQg2Ye)_2D~JM$uA}2(Ol@kU@33!CWDn5b#0lEj~%9p{5?dfWrl6<Zg{3CenH2t z4mcs*mWpGPcwUBrknwPRmvu!*XTT{tiRtp8c0^*ud@DxQOjOgn>M{GT4jEb@THQ`B z5?%Og4W1z}traiG!S?0VYa)R^uRp0y@x3HsSC8kQlT@WeG!hBt-cY>O+WBqXTe(Co zGmQDqWGrNc$%sMDcISj^&S|l&lT8buys-=osI=P5CF7i?m{ay;3K3rr5V*TiEx&&3 z8s>pPVUxbfrDwo9Y@DBm$Gz+LDK*!ExEH#wx<^T2mbU{wo1l>CqW-{UXP%+(Qqk^y zRokaeUXtYn?}<vi!j<hf!c<_A*TA4n-`8m@acwAK@RTqv3Kx~g_<nS}<)E^Jbf|_x zSTW-eNTet4Ur)+>o*F`oiy%-F@+2W&PSAG7`*cNKfob2wT{DMdXa{P@>4tKN<Q}TT zh&1>02=;N)<aw7~si0wS4eG3A=&r3rz<GvTbQ?Cb8VAl~jFihq{!mrNj?KfLaHuss z#}^IW7mcEAH|I(1V%XG++(|l$xxQh;5qS^&qB=Fy>IAv!rZjgbB7ZdHD$wXZx}03E zO)KGCtUi1mqo75qiU%t2vU74BYM$Um;x>bz!guLoa|Y^Z%qsMq*wdC@e!6S_EO>s3 zpHaS%1?>@qKvfF@JU~$^e;fCAh4VeCsNh*npFphdXH*XtntL;7l~5F|KO%?$uP$xj zc$QrokMA^vj1OCx^sQE0-&0>@Z>e_FaB<a0uOD^1W3_2OHe_6JIe83kqvcMLv<ZY> zsY=_zAX><(Q6md~E8gDZds=w)8dl+3mPsXst>&A;-NA5YJwysaI=6qm(q5B9r=~nA z*s8o+#bpuE$(~+HpYR{>W}TW7vNjmuWo<n?K0MBs|8ws9@)yHCKN(8*#SvbKj|iwH z4j=S08%#;?^WBYge3FsEe^s7zzBU`;<qK$v|NhbvQz7C|%e8g3SvkZkIy_x~ocVI# zxkJX;k38D{e!V!X$@dSaR5ZH#Cr`fXoc~|A=YW?UpNgAkZo(iQN}dit-qgg6-O7YR zV5-ssiv)zM#6)F^OyvQCtj}&k?z;OX3aUDldB?8q?X{epV&M-SP*nm6>NRfXe<Dnm zg(jd2EO6;2*{XC#`EsCZk(4z#_niklXv*^&4mB3#H7`#6H#=~5nb%!Y5`rL~NWs1z zc#|jblFfT9hmVNxoZ|KR@Y22#v9vk-IDpp+_4ZdR>~hC-D?keNzyk(@?23y)v$@sK za!~|(+*|Ih(P2BcSyG$~J<Hb~MqP0?UPM{DGA$}{M)_pgR;*d06R6=|iZlJ;*fT<y z>koJ{=~G_~(ujgS&t|WyU6WT=9{d|h584xlPk{|(bmt0Gn%sc&vW&W>>$?;jOuNd{ zpo+N06DkgoZ&^r_qo4E_u$F%FvuwqxgLBCQXY;UREIV_I1du()2=fMolx7Jr;(&DY z2?OF_6oPC*95QLBH7!@@a%PnG1;D-us!akpJ{kEBy_Jfcao7M`&Be<E>`6Yv)f6^j zVf2u@e~>%2&{!6?@m9X14`CheQi$UH&r^bK#mIjsHien^hG0qD6Cd0^WxFHU_>7*F z@Dvw`kR|<+pXftd^Ntkrm1=Tu2nM6-Lk24Ka>gErCGlZdq1e}4m@5wtW7Tna7C!3A z^+fG;yVhWw!SzQ5jQl(?uZJ_zLY{jJoK7xMR~c7=#3-Y2Fe+-wW8{e(c6H!QRd%gc z3h#GAqC#Kx*vD0?rZRbx30G>Z>&SptQ7}!MR4kx9aqN>EWI*xWxj9Qyd5y$++tE{E z9c#itP;{4q4&Q*0Ebe5ggq2{C%YguAdB`G9VvbkIBXCTx*hfJI0;BUyvHcrxqia?b zX+cDKRC&llL*%6HpuLQO`ea6@C(b6%3&v6!9L=%0R*eaiTj-IqX677;q+iQx@NOW< zo(!?d(N#(eJ54kV#nI=WfmUY0&RSa&VOybAO>3B>>)uiIKDrwOx7k1<_Kby!P;bcD z&&Rd>HXMhfygJft=IC{X%2t7I?eA^estn~7Mr0C(%|@^reJ>J}agY8q<}VD}i=O<Z z79N8RIUXi@@Y=M+C_yk|_HqLjp@&G2hB|i--xJEnDe1r^hWL?@a9gr!y0e!%y*RR` zK0M@=7w<@t`ry)^2CIs~pC(r>$zsig>#jR7(2**Iw#|jIhzmpn`>Y`Xj<ph%#1=_N zAv@_8VHl=7A}bepIgN374qIY%{B2-(T39gtZ6mx{iFBkY_2}TMlmUASF;X0iO!YiP z<sU#F!3(fuS<4f=ePMU>6jpHcwv*4OBe?h27HOe@VtIPf2%^q*?V{vBMzFel0Pg*o zEKzd;_ZxRYeM?m@(zZujJ`5on&~jG@+YSlL@?)G-{6HAZd1dU%{Jdc|I)*!1m?=N# z;G)*4yq(Bh$KYe2kn%aC;!=09@u>U{Co%`i7O#gH;2vdvutPUD#Ap;n%KE)-wrXAX z1Xc53syCFwQswAiud^@57Ag`9!YN4cBVm6|RSfysj<T&T9#yZ7pr@^Jq-!(2PoDPn zEVV^7vC6}{8dSYdn(l&QxQ(o<E@if(V|@L5p|aQ#zAdYL+&j{(rx@G8Cey*CoilF{ z5$`A0t-9n3xVJpk8aiKVj*IyhQL*mP8AiX5&63#b>cV$Yv1P$$2sO>$O;#{T&9-C> zwpR4x&Xazh8!;XAL@+!#l|BZUyC#p_c&3pc`KHGgPmAM#v?E~2*0$kMw)@aF;($H! zQ;PEYwDKE76luKeb@;-F*6ZT%0Nd?wm)7(ngWr|{AJwT>5a}+<feogEp0;vNB#T?E zaqoAOiLD>+a>(MG)ZOM)aK<X0JtxPD+doXtjkAmAMHMj<#H)vFx3Bhkm3nCmpSa<r z+}2&gad$P^8S|+&^M)0AQ)*SK*AI8S|KsU9H{LwjE^#4^+Kt|*kSOsf-9SZN+w;=- zk*euYp=DzYh3&SM^lCZJMP&BHgmP5%ebXlTUn9;mTw_N!{w}SR99UUwUOtMPLbre7 z__8XGJ)JrbvAIR)DUHunOb{!3;WcRgx6vs)W>;RhvF1x~n!4K&O^=XkSFg2moYnnQ zr|qyio}ea0I+6Mrqv|;oIWYD5GX}HaQP=D=Q$aM>{!VGW@J#J%{#nmD&1-XtxXEYZ z_jWv{HI~B$7wijvSRw<D;?NlAw)Ox-CJL9m&i=+9Wg8Xw`}G%M$5|qzs-K9^P2?XK z*HMQALXD7@6+4^+`5sF~yl=UgpW8M^c;>Du@y*nqRN*P{#|c*y8oSXD^Jr9gGIiiv zo#evKxk2Fp!SfyRI^SMTcDTpe7NoWBXm4RECb(*kUn*DooXX&lihe80$jQBlS>uj& z`^0xr%j-{05)-Cz9eq2vtc9b~7E*OU5fP)|`1uEg%#c5WpGr^Fe^=Z|?$r?WMpTNc zTF)$!NFBP7hOBW`xU=+m>vEl!el504#c@b`Be%BX3Eb88IE|a?J44!#z@U=U0bO{k z^7kV>ddN-4_``#dybf|s_x)T)obk;mvMsyK(ywjxlbBWO*e_??qP2d!FvR-3pn{Hp zjZPM)!l1q9w%mB9>S7Jj9m`F_b;otiI5bI-&d{49YYeY!|Niww4Gx*>{(^U>kM?^g z9-74x5X?(s65o{!&*Fs4MzuB0Em<?b4cS8lbFw1(%fzTtMA4^uI61l){0sthx?0>U z$myi0^cj8iaNe>!JuiboBZd~n*2`9q?*#;XG!nbI*dToj7oO4zrcF2>AFPp>pY$WW ziPy|@sh+PHBt9R(%9*K2D<D0CVr&GC25o0>n)N{yyKR0mZZ-Sn=ZA2djKhT(=)`n- z$9MXYjtB`M4*yh4{h^WK^~nl#)03_0Ti4K*1I$9~U#Yqe)O?!uUyS#-fD<z(i!A+! zeswhFOSi~ow@96}kK$K5H)60|<aGy9WlJw2m%BCaWwh)p9R<UjuZ@k8S+jedsCRzI ze=Ha$g%Ia#7k_!vbDnoYyIgp|XF}R@K2UU2cr5-DpQQH|W`6~K$oXyIK}z<Ol0>b5 ztS`f+opJYXo%^<j<D5v;NBWC)Q+13hl44=%R|CVaSUm`cfXN=H)lco3-sm7<M)f@c z6K&Uc>c2%Vn0q)FhpLrmh}FU(ypd;UMOJ}Dm$-{UF(R@#YG+>d==x4rFMng~#^LJP zzG{|#W%d*FaxVVe>l{03UvisWUh|T;`yoq<@jfv;@g;Uq9wL{ppzXKUC`%tWG1$#D zpe^ithg&MU#Is)M4MB~V?|p<6#Jxi}AoQIXz)N7%zH|{EywLkCbY<(iwZSzxmW0^D z7urMf$s$Q_dcVi1AY(E#X?DGJUqH^wM~locVybS7({J%GJ}83l1Cmn`)^n%5NcpC& zckXQ`rod%s42nFmPbP%(L7H?h;deH#XZ^Uh8tVznnpjZan#Et|vj<5C7Ia0>W;feS zhV`E@Ir8D0E)Lq#-@7l~MFoBieJ&J%^#2HO@OAHWeKe8mztsBhjwlJ+{*{3@NVssq z2-9!c;&r(->nVYY1&e2Aw*7qdgnB_Q>#pa#50sn_XO%?>Io~>bIr(96hXe+W?d!R( z(h9m331NO=pj~R$LrLd{oM$h3V&vP7^*wof#Nb!P#vRw>zsic&+)>8RxlrtY9pz@e zKoe%etUjJ>_O9;zgK>dpHWNWHTAr=-sOFdL%?esAcN<&2-_D+;Pu!%d{{2<)`}UXy zvZ8I^?4wG*qLV3R8kbUwuJLd(y$34!a4qX`Hku<#>VH8gy7wnin`m4~!p$Bhw^F?M zc!M57BjxAOpSP{T6TFfZt^GH?1yb7H{s}V8mV5Ea;V{l7I@&f#H03zX#a;jAMinF} z=g~9oqq&PWx);(ka5n67f5xv^e()Z)sqHW7Pmz3)vap#z5wVb|yp-P9`&k}0(K$~D zhu*I&GFty_@A~j@DCtqy;el78uw@m<b%_(5Q@c$mDY5hvrrBuGGX!cWRW{FSQRL&! z?Oi8as(^_&kK^rIM@h~Q>$#h=`WG(_B%b%mwy*)Z2PI+M5%-(`FBb#yOI0?;LpxGt zp9n}{crk{|Kr0%jkh12!A_S5yAg7FG2nu3VE4VTAa28YA+Jk@ypXnjH_ao#9Fko$J z<ypF~k9_=x9S5h94nMd|$@Op^B&h{=wOp2tTEG-I6ZwH~UUncP>uDJRC7TqEjzobX z)z-<ew}Tu&XpALr;}!<R5cn!Q`i*I2g%p6Q@zJZa4{ScDUR<_=2yF<$i@6n{N|{TC z31Yl@UVgUe@gRusBJ|FUS{LKEW8)TUm67lPd7oy%yEaH}DI<_8oOF}iX;wXBh&F9} z-+yq{I55ZG7Hsl!nZNzp5r}((lrT5X?Q%Pv*DD%K@hNtvJx6vu?fSG3M26oNkz}$v z6vlT13}0kea@HNeLVrt}RvBit{?4?7ZDeMMa9o0aglLT}PRRZ7@%vN_OKK4$w-Ys{ z21E!>gh5f?sHwq2q@ZlVki>O$gnVi2G=iy717Xv#m3S^iZq3qKy=qQN{plw3O*GM- zZZIXEsrma|Mxk{lKsUW=oJY($d_C$bH^>UfK-qNlta4)<7BfUJ4VvyP)|qQ+O!X%o z&SR!evf~^q&-EU8uBAlR=P{{X9ngm^^4@-ajO$^upcaIbF;i>QI3S|_SNTPT2sk<7 zK0~nAnw@bcID5`|`tCJDK}fWrnu~gf<J|FcV+ksEwqDG>JV{Y<-~q*eL{C+89JMis zOMh<Rbajr`VnlOWaf>|^s>sCDVKEA4qNl0EXy~(kE}<;vCZ=i?NL{}0D*EU0#WS$G zRhp{_7f2^AeorZ}x$L=q^c7}=Azv#1WxI$sYc7qw3`%+%;P#d-9q6ov*^f?oow7F= z8%#x|0F-M?(J$``2rj<sMZPg*N{aPaZtL4_nW9DchKPh<m-DH3-;yU4&)UC|wJ)Ko zFN^UXz>!nQ;k9C$3%3fP=T@N&LU+`*(mRhXZj)~I@gM(qt1`~I7pCd#gDniP1x`2H zIG3JoCMn;?)!}}ReJ=Vs=l0=Y`ft}r$S%hp^ffC3|F44*XP3^AgKX6x?S2iv<Y0fk zZGO7;j-&Kt-*#$6%Ojb5t>~%iN&&r(2|v%qrcWoB_sm7yT>kOuoYB`zgrM;X1TGx7 zLdhb#g+VB<Q@pF7D%TFid>mC*PW=ABu0CBw>Hd^L{r#!=sosT#3gg#5;le)b%omR* zM7cjNq(Az#%hg+x@<ab@1u7{z?c~3|zrMWr_YW$Lf%2C~oq)%cWOYErO6pF)rAu(O zFj*+O<diK;-o(MPJ-?_eeqAF-!qIm;zxYnqy4JZe$AHiIB@cJkbtn=}LHq@!g9aOV zd1X$a+684}@f-Tp63!7ND|KA<B%yLQhIU~!U&5x1oFpN`rLacy&L&Q;oRAY!SSz!) zX=f!#%*!pTQ!@NuPbeoAwHMZFC46uUl5{T{FKjTp^TGLCxqId3!bXd|53UqRk81v+ zCY<3GA+Mb6QLkOp?3}RWUM=a_>{8U?d1uS>R=H<eOwo;iy)ExPNv~VEC4YkiGE2Z< z0k?zo%m)h)Ne#=NC50h~ndeV&wrXN9!Rs{f)$;>Kz7^QF$fgf-3FgSLaNK!$5UaB1 z(nXy%=E|i*(p7|0<t`;t*;6`Zb$Ho0Jd8JZL$|SPT+mQIkh_L!LY!>+PcE(!`p}Jt z1~G`QVu_N5f;Q%BCn<@$RxkaPo<Ra3<?_fz*!OUf^Woh<NYXgwQY{%P5ON0M_N{>+ zGik;NaV^LfQRAmodQ6yB)u|acmhzUGuwRtF+#isr4bHFF+by5pSHv-_)0vv1&JbaZ zAGhEAqNf9ja?Py%C3B0&@UvGdX{p24xnRINW)1S|-H&_E)uPiCwZ~P3SidG^&L&)v z8s#DhRoEh`)GmIJs@URS4Wsh8Fq72^b>s!;er0Uzv=n5+67;HQi_JJLa{5*+FX}<M zAn`%Ss?6gsMrkc0ElNTzCiVJL!lO|$lAlPA1ZL5p?MvZ=bXjHlbhZ7XwL6m)??<Gw zZG6~*(TCP18$SP<%JJPjte3S6d^LhjrpJ?-U&c-G2g%&ljA0snxwI89QNJKfZES)6 zL7xe$d^wfs=pvenj;!vsVtp30Yy>MmcQ5Uy@%OiKR4DUQ4vkK3%O-hw$-D*hZZosk zOe8j7C+BeJtbUB3R-l<x-i1Hwo+jjm8{5#S%hV@&hkv_;QMPN0{(c}_zchRE+Fsky z3xBtR4qslFxc1}D-M^pCUBA5i<=W4OKmUHA98P{KaD9K!i2XJ1dh)u?^<QHb*x#!U zr+jcFUAap+B(Nk2^)ESbL_khhG}e4l3?g#n)MJj}Iw7rvCaIFVBLX%shkGS+M+D?a z53hct<rF_AE|l7n{YMW)n4R#~OL}!TwfVF;J3#(zP15oI??7Px{rito7X#%~?7+-b zptn_v#xG|IWJ!)h3S41twLx+ql(vpG^$|q>Ysf;=t!@@i1O;Jc?biNAms{~kH)?Ho zuo2-Sq_FhJ;fs9hqZ*;wuZyev3ZyTOMzm`&sfsrqW|b;9S~Fk=)!YJaU8jS_&Hv{| zSnG7ud5kDfeAXFBR^lic(UVthcK9yO%edNEv%i+l)|PiP|JY`mRdt4kk~dTr`6S1$ z&`~RAL($PSyZt|hyV;9J3~Es-Pd2$(s7gFm_N}@mIXfi8UCwdNKo#Oh>c<*-{?Cx$ z>3x!6=;e#!S!+M)xSFHxdiYOEErB7WUF&byy6F-KoflQ$ekQpxm$T#1ax+J8tYtj2 zc#}^)_ryCP_e@On4BoAI>uZhN?MUldsoSQ33YNF-s}^+g3W_dLrz;Ilru<yLdy@1I zX&gwo;CH13?QQx}E?UEnbXOJHUEkfdrd{5po2;~|Fe1_HH!rU-6wRzl%Q7{t)ju~n z%>8zAJ^X3o$crYg&X#v0Ct9>OiZreCrj3v0c(BD>>@)X)mpzS(GR6`0C1Jf0jn~sm zBd7cmhfRt*>ND3f4LnEsKjb2(<SjAdEvFdVUh3qB(?h^!cPxJf=}i4fHxM0`gY9(7 zeXaCzA!GBu5v%MqZ8L?7uWA;a-u=pP|MMYx=s*}1QPLatT<59z`7xvS$)25D)Qd{@ zWxl<rDd4j<Rp{q2yCbhk;j^d?y56ZCOx2FNs#6elbL;e5;(NEaL?b`58~OU3g{^a1 z{eIfLDh_Oo6+QW)7I~6J`Ib+$lIgPCr5pR^^W#rd9w&dFusfEr=kDOt9Os*PqWP1O zU-x!4rrLBO_{Lf7hnOfGypQ^ZptwDq5dGE9o^AV{x$PMu@U}qM+jg$F(szwpP#R1z zp0;cW3?VO%;J<es(Myoa)gVVo<LKT@CB;#6sNYH6P-7d(xk*x*QM~8h%+;o%;g4$P zI^Ex{8uq=`)RC7lEr!c?rau^qmiwasEMxlax1v~}!rMSXtKnhZ6GQS<=$cc^mpF*( zly~$!{8w_FkchpjS;*UJ>|)QYR;;?b<tR6bC)iH<$J7-PA_R>z!B_6IMZUJS-yaPZ zvJgh(C5NwJ<Vp6-j^%R<-v}91e?Tmw=@$CM{eHzeakzYgDY;t(!^kUp=EM;BYzUgQ z#cge!*(7Xn_`_;je3N)i)s7n9fjm=z?UQHXkP)6!4$56gfMA8E%O>by2K6S+dkJUJ z=lt#20CfxmJ5*Utpivf;yq;X|;;mcn|GP8Y5f(^-6lQ@sJm1Jp<bLjNqY7&F*0>py z&pr^0lG+hlQH`*#3^5b5FS%4GT9RJOO=z&bzE^}$Z`6{^22^)0GU?bEIYkG&@-SW$ zX;4tEf{SqQ>?Ic0w3KpOyzVH5XKKmnCD&)+MHeHA>FP=e#Ve<SAl3Gr=oPP<|D7fP zq$=0^6@psbC|z@%`hrdl=6b6^4y-$%2cmTAj%zt6nN7b4vTUyQ723v~FcD<Nt<@hJ zm{$rt??p9+90_#V!UWE<iI0BF-XtNT0v&JLLpq2`QPlyqfSDktPrtCY4^<V8k^Y*D zgz{rp_@aDBVt#0zC=_dYB^2^F2SIA}Kq5u3j!Z~Y7kU<o5V^GRVo-2Pjl+kaEL-IZ zal50ilrONBcv<t!mg*JsIdxC54o)|Jxh7=BJ3lUY2V?HJ-j{<hiFfWVGe_eg%D898 zxxP)Fg~o=S5DhzVcDr;SBj>Kef`+5!twjndkju#jlA`o1eN8MB5@0T?mPqndN9wX5 zUyzu~W~+pB1m>}SJ@-YeZ%Y($F$G@BIY@<~katUoCK9i40cRd8Trxi}j{RsCL0qU| zy^y#27K^dB3StW!;uw&=7)V4`trXQA^5NO%^Q9<3xC;8q<J4GDjb`~Dn}0&S-#KiT zJnFgQhiGNkli%cid<(fgPkMfm<9z9$ze$Uyhw_KLmifXZDULc5`Bi6O>fht;M)ofo zV;+@X;+#Cun_3S|eG+@nl18{;3$IF3I&+^KaW^GxpHH6yPJDNO9FRP@1vtE}K7A13 za$)hs^{`nz9+*q%&g~JoJGX7b1cNgXi*m>w>(6WnGG|4(yvt-1bdjW9ATXi?Inwae z9mVp<*fl+xWi@lk;oD=<5wwMZ{#9G^mZ<!m-)ddm3Cdy`6-Ys;nKv94dIl|GUc^RM z>wRc0BZa-DvQaD0B#yQ-KT9h$o({c|x`l<$ePqHtOqIRE8?87n6IpJQUbqk$zT%vR znYns{7r%WKb3xcS(u)KUK(F7d(kM!~Afb4fd6#%K@Qj%W<b|shS;WCHrugpCx=y-@ zWA@yu%AG#7NS<f1#moib!DP+R$Jlm%2NKDJfjW~3nHk%w`Nk!XDs>Dz(_cgde-v8x z$Z+ER5QKD^F2E-kePCNki07~CQGA9F(T<2$K~D>RCEWGFkd(-mUoxQoX#-G6@?Ng7 z(MrBQMr2F&eE*@>JL$*%$Wkpu+<0dd%K*gT{f=)}d|-l^PYaD3P4@~yR=-iu_nd;W z$gn?bJjC)O?7S5$)549yB@hb{X$nM+oTUr2UtkG0b)@$lr*a3_-52%iAtMy4paS8r z7eeKb(^+&<#?9!AFC~+ZRgEfW@5w(~H&+nKT}<fgX_jyW=JG(vb;oO)v;!<|>W{l` z{@Oe-yN6<@miQcWS<$R^ljU@YQ8I@C8NtNB|6Qd>RXxTK;i7m7ib;W(vpDIPI5<)z z@NSJRxjT!+TL((}uux<uQ;>0x-k~~)k&2^}`2AUus(qp%Rw6uzg6$lLPrI1El`E#t z0K#RAv9hh|6Ay-?{8_T7ez}h~EH?H3wOGg-JTSmmxj-_cHZc;Va)cxVK8a0Ne_)ND zwAPrhb{z)n$TWjZsH`!~D4d=v$gpI>4j*WcK$!7Pzs_{O`T(evOqZOtLU}+*N^4In zlN&H({Z6LdG0kHVn;2<Gh9k!6Xl#)q2scg|xVle6dSK89Yoi{(R2S<Qf-xBe2pG6f z7glr=s!|7<9Ax5j08$@Wd+wqHkY<-nGale_BSTSGxb@6nK%HFl^Ban5xVTdY)b79) z42|Cd>gQi%gt79j%djV{VI2psnL7y8>>>U-sCylN?-@Mf1Qm4~%)kt)`VWTri{d`A zVn?}LK$s+pVgw8&6+ZnMLES%-b^fYd$z>{k2!#O2h+#WHWs*e0qHtHqwrBlW5fuRc z%#&~fOlA*4tZCqE1>Qn)2xJ~)GucHN*m>TgXVlS>QP1*7A<e^Ib-fhq<3x~R;#SNZ zIEvTaTW%N`KU5Y@7f*tUPd*c8QVubp#UC+@Y`_p=Efo$o-Gm!WLeYh=OdkhS2t^tL zKMX=GLMY{mjB_7Z0&Bz6-C+->XB{X<>wZH4v-`Jr@0$B#>>yl+SL}Sso}qw;C7W;* zYJ@IGVq|7N1H%yne@v(%!xqx7&jd`H@P<sF?IY{x<_Owf)P-!{RXF;rP|hvZxO2s9 zWX<5<|48~g%upPqe8gX`g5R$IMLx3F{&m0|Cuo8bFzy5$G9SwbfrfgFB153KAY8fm z)8U!XHwc$8N}VLFeg$C^?~hs71$*L2n6ef6QIINKN|6Ss2H`F_WV$g1F55v-38x(k zSJtJ|jKp1ybtg7Z48uvvbvjgfhXw}H_p>MTF@2Uy*I!WxRz*fH??^^092N3B6EcDd zcVLJQwRHh^>#))u2g*|nM-I5`1a0-_Iz}FsVnSt9ZAeR?OBLL3heDECff`o9qg%mm zblS!)ZSw*2a3Bp*58CxiWPijM_PG9fK+oQ!9c98~b|?m9n)E|}fSxc?B`O%Y8dptb zpeMf044DKHzC2*NWcMIUFmRb3ifSxeybUl>byd(J@+%?nAXSPC6=OmV`%Kf55QgCR zhiur<N!NFE?xbU=PVfKBcy74snAtj1yvVMi@OxO5?a)=5@TfJ4TK$kLXe&mBXH~g6 zV67G^;8hj)0S|z_Ht?`DWBQ|O1_(oWc)%-ZCQO>X2l($J#<mr}V`jif2hpYh(Mb`m z0QUki9kY%V>v^7ur`gmG==aQK3=H7su??sfAc^ek><ks|0*#El(8*L6)u(9{c)7MY zB(J?)5`{o_%MxUytYINtAk>rP5RXG5twlTme3FBsKSg!_g+={K(XOM&O`Y_z=a<-n z+T=ATGj^7L317NHkBP=NWz)0BG-v`o(HXQX8e$>l4lWs@ATkWuZ^`0vbso+j`M^=h z9#@z!)PPqe1V0hw7L`4N0-PBgv&9%%2Cgr?6|@7rT<B2QIv|*VNJI8p6@j6%9;cTv zbPoza3CXoSkpEY#Gz9Uu3rpz&9rkQReQ24wK92s6-PW;@MSxxDa7Ga&W&LHR(gUsg z%EXTDBS((wnGK^R=dbvXeEo8`2xRAjghH7eU-6w{IMO<>egX7ZaP)r`{>LkO&-v=g zL~ao{=zQQ6^~p|piDCicOHT>|Fp_|k!|ozIX`v`~GF)>q1A=5<kDf76@{(jOAbEX5 zaZ5-=zl^|{$9J$2KGQB3d_yI`l>;Yd4;>4iwb`?GT=QVWk|^N_hH;NAYZvh*6e=|g zy^b5`u0Qdc2TK(sf9!Zl6@RexP&*-o!W{NH%;b8y2lb;P&IPcHs{jJ%CAkTYOrW1M z9Lqv`Nq%Bgc(5{+kVZQv|9QSd;c5Sr0++Sk{LTSgnubN0?zzTZVk{8SfNR@zs_|#3 zfRj^LE)roUV1KXQ5nPa|1NJ<jVo5amLxl10BDoGg8O*DY;dWIt{U&^SHeiYlRQ`xL zj9&RS>zg6yl$uP)`U?+8nal(yYy;`G;q=2F*{tClFzXZRohL;VgxiscXzW6UZZIsz zh7e23$cARK-f)HD9kQVrPEgj&TO<}vIvtOY67>91|L)0?!?Ijg)il6g&F?<J7#SYU zS7QBFa=1XoO2&%Qw@LtXhT?L;YwJ%hDlsymX!ZUSL$}9?I6orjsQTImkqfBI1siPA zjynS=#A0SC427L-9k9(ZoUcvr<+J3nEnWmS4?bd<zVixIN*Ql!k;MBmNKJUL{kQak z+!BL82HA<S4z&Lr>Pc957r>I92c8CO_}W?>S|JiQ*SRXeqma-OkNUDy-(A^VH|ZHC z7K8fTVHv7RYaicTOuc6*LUv$tn^5O<FTK{@Kyb-o+{%pKu|mUsecYhyt}fL91Q+O! zJ79)CRCE$*-vGLBaOaYoDJN3K&J>0l?-Z8}0=B6Wbk@m2&so&I_e6bYfo`xU<e-}p zz)=BuerBEW0%rU%s-<A&%x2yvOhg(UB|V>AO8c4&ukr%I6DenueY2UX{11jf@B_+i z=0YVUGwG#P1F*hsCmJ}LEj}4w8}@4{B=zXFp3SSvUI49=#Jatq9prLw@z68=%$2x# z`~Cnh?I2<2Ii>+<VnE&7!Jg5LtFit$sXn#Q3n1h}mSDu_CnrYJ$Q_S}n@$-S@oPha zl(BATtNE$6nD=b&Vqg)wdaf7@JHe_}&M4qGEfc+!#hkqHdh2%uKt2G}JzC0K+2Z$) z%GM2jlt9{E2{SpR0YU|D1fJ4(JJe1N4PXks=hysL7#J?r;gTEp83jgW=&l}r?YqbZ z`X7bA*l;{d_H(R*HsIEowtabt>!Y5)o#giuIIg9DQBu^iO!B<w{0Ey>U=6jBwR3h> zmTRtIlOF5u+OCcoje3NNJUFSrtw4nfB})4piM0VXr$LP{vFjT<BJhecw8kgDGP$>6 zACH{vYX=lkPnSWEk+!yClN5vS^-R{Lb8duMa(EnqYlofjgpD=Xfxf|6Nk4tQoA_}r zEvoGrn^NwwSfreBB5^DyX$!T#l@aKiIJ=%%`t4ON2od1Y#nM!hU@|P|o3<lSLjZ|u zZ(I9pEXNm?^bW<i<hwEFCV$A64AoQYF>w3!h-@IOQ~N9CaXYp)GvN3uTaoxe$w}lJ z&<<mj{(9nD+K38fars(omRsb1pD>?416gdYY}=0q<&2T>JN`djj|-!-b|OYxfHtQD zqL065;g^DrU5PgUmuT#;3xyu~@jucvQ0p-;<3jO&4A>1*W<Rm?Nzt)5D~q!)j~Y$B z3}C4~9S)iUuROFBXTmz2cVp5U+V?ZxL6J`XX`g+s@$}Az9G|_^t_=S+ztbv6$DbkL zZ2mXWCs|Vg<Dp-;4*vt}HdpJtK&5{}Hr-(J2_f!cpeJU`*C^wN<z_Z(ubEW&4lKnd zUs;Xo26Wy7d$TjJ^n{eNi~JA#G6fT7*<oSzi44_Km`1=>Fb*9;DKz?7W~Vl$4_L}G z%+?jlPd1yDL@<HviX^%|6IvD>!06bGYPjHhdg)7yb=AtxE8(xFDwam-vDC9)hSMfg zL-zCCM&r|y!k?aJPJH_@NZMzMUCs`FcXoiH>H{|-(=5pwhI4>H`lm3v|6FqtUvs=L ziiIouz04xPxi7@!_)Lk;JuzGRHQ1=^NUn;TX!?`_47oPnYbP*cldeIKwip^)J9Q~z zGql4MoOlF0=1s^B9NTQ?8dOZoDZMOS{{gAF-8vgd7x=`fm7Et#+T}ODlsmbd85nM% z_TR~4|5YW1<?MX<9yY!7G?b~res08`DF*(DrR1ufLb;wdWm2yyg^&DXV|rgx&^nby zfW_Zb%%#uB<PSN<@4UZo*}0usC;^_I{hVp+W!t#_?!s@CYg|XGpfChLgmH3*6s!hv z+al}(MksJQeg+TMsdlSU`DvDs*o2ex{?lLqYMkJ7>HcsHjv(XR>90CcBUxM%*5a=U z4;n5a2tFze*Bcor0bX=H2>I&lNR8FJv{kAcN~EM{#yM<pZ8+2ddD<TATZWNDlM@2D zurpqo)}mo0W?Hbrq|$X+Nai7ZuhBqxRcMZihAd=DcVo2N==|r8zw|dB=nHNny^4s+ zJX*b6bxl7HX)Wuk)ftho$hTAv$Z^f3OcLx4JE^o|_Ul3g=o)~v!}FRAtc;kaK!r`` zsklP5syB=jx1o_tPS04CB8$PSPMNc^n#-bcleyLc!l4&MNpgElW&*uF_f92wxXZ=c z6TjCBy4&SR8w&C5j2Q}BZ!PT6afr0U|M?Pn<kDp>?aP63nSdX(P%mr&>r`s&E28i} zUxMC<@hSgYAJo(1?A7`zYj;{e9Gq!1IhAL7-<eLsv785JxRfrBC99r?p$gWqK%%g< zvD1vSHAyqRkQV0<bFd<w$`b2jp1~j?Ug7-UWh*6T6jvlr<b9|VFfkFjtTwNkCn?r8 zl_w=;uO}24(HlZY(X=X~3WPaBXRWW8ms?-4|3AjgGpMOA?Di)W5(p%L&`Uz^(xn@E z@4bhBROuj9lF+0GhNggkfQYDobWqWMKv2L22&mXX5fDY`_IP<`?%a7l-tTA5>~r=$ z`^@v~^;-*(O3zcGWxHGYh>qcm?Mh$D8=s%<Qb5%>KndPaKjTeN#9i%~EdALb#as7& z{Zi~2K~nTjg}S#7dEw~Rr`yR;^lzoU85`j*SqiB?Judg)*8Gv`LpDWnD6yn1ldP`S z6DBTRQnI#fWs3`E^n37Yfp1$GrtaXMAc&PHtccEGs<O|<`fsJFds;eqjecy%QP~Pz zC*O4!ohSFs`r>W>U&eH~(URkBwr@M}ABph>cPQWo5NRRaE7m24?ru?fR&+_2WRf=( zcNFYd$IUZVV17LFbKwwn5E_My@i|$R0Zkr_u6beeKU{+E8Lfp`8O9fos3GGE*)7CS z`}N67_xJ{jI_Iq_@;?^6=ZPgQPYA0w@<qh)U2n`0iZz>AHy%v*17C`L>;FSI<_m(4 zNx|+hA*%+NQ5R#`N8)ns$#<#VCTcZGJ>ZFG!<f&+pWZ(-R$ZM=9lRx>`M{>Z@6Nk` zuvRKWDB3LO+nT6*!zjvSn3j)9UdWd-IXm?-!M5!|BMY)>wBMyRdimOpg;1K0L7AkH z0q7@>BVN#VpPp#uG%T;_WB7#Q-cztp0!4Kc&V5*JFfEz)-xhp1VbJXkXEU13O49^& zjQDitS?dwD(?#RTY@AaE4Jg`;VL^Z}a0fnuO6bawtc661?OgCHD^^{a<wAzVsku-` zVRCcNMr1|{`6Fc`NljRka~{9z%r^dKO@XZ6s|S4~Xu&bz<zX3Ycj48jjPxCf+1f)_ z*}}|-0=Dj@46fz@nn3s&QBdAfryrfP#-%)kE{`$Qk9vx&(r}KSye8O*`_7ZHMG-Zx zO+-S+)g+#jF3wzFgUC-9V|(cN(Bh)fJZh;b3&;UpJs?QRPg*}S&#==hmK(Zi@E|oi zS+0r3#lMU=e~%8+*__~fT`*2*8yYz;&wkaPIAY3sgHinUE)5q!ymh?ve7-7rNvMQR zKcj=LQa3Gz^dw!q&^Dr&Y{MbsG1T*sAeFBikt_S@6-KzS9CONaVwL{TVjB%DWiy^O zGphm{AzOHQ&6Z^NT`aVFDndI?IjYHDe|~1S_cH4(9aIgQ%mYTtkUuE0COmppj&IkL z)j8@y*QmBz(?pW<jw!0)XSN)#M%C?8#c~TIh@hVhtZSG<(x4`%!l8xxYHtCj9}iA< zcprbvDQEUZqUeP`pYcCiI7C9XpWy01tT1bu*<Yv8Y!UWO$rp76wDy`xomDDaiCBW% zv_|UW#>0%-rjB!y=P0y-7e%WgR==ioA0-crT@9P_<@LJph!9zYPc{wWI(>cm-fsV` ztiOu3$n<t-5)@S02PN^`d=+s}X&F27UO`Q=$Z~%Pb%r|T*gMOnqa)Fq4ay7qwv4bC z0-<6z+I<a{3Ut~CsQ5VOy3c5#PS+A=<PqQDpM=n3&@kQo6r^PO?>D2<V@eI-X5wO) zMU+3eH;Z&V&|rsMZ+Pi;@jaE(y*J;Xgg$%m`dOuntWmeh2Ztp#T^$yipWUe)y!Z9Y zvCI|4BZ^bKOeSGLn2l--3dz3DV*ULV5LXS}>^DEJD4<B?X=lPThDNxu;z&Yq?QC{q zpi(=&Tn)}3if-z2HYX~F(CGJE@yMYu86&kK*Y@T6LZ{6Oq}jze?<@<x7<#CEU#&E; zeMR(n0ifu!YGMN&0EVj{Ss1C8SG2E6YuujXTDVo{V@AIfG>ve$uYRGo{iAZ??Z*KP z3m^|Dd$trjN9d1w?Thv`t=`*DW3u+lcuCCwdJO9nO7Q@|pmoE&+t0ID8b<|x0Ea95 zKQJP(3f8e<u5o9kG)uGPN-~TGN5UsOWClxge6mlx^P+*J*|y%({t$}isd*&?M^Twh zy?5q2v$WcSJ3d;tSOEO2x3Og>J3jmG-FbPRm7EFtY{hei|J6gIqqW%a<)rEM?1Pvm z*lOi1N`&j(#fAHaXLJ9a8aESu^Pa0;?vRwn;!{U^Fiq3O?Z3wM-hG$XbTDvt>uXwy zAQ~~00#<#(NBrTXW`|z|^CeP~#UCPnI54U!5+XBg(=0MKjsvV{D>(Bmh!hXLkE4I? z*KAzgXQc*es6|@Zh^)$_^w2@n<^gD>+6EV;g-593(*rN^T$n>qF8^MFV87pbUP}+T z9pK|oflovuV#gdi_p>BKPoV<!=01$(!sMu%9M5i(_wVr`v|CrxC&$2T_W{Lk3e0nA zeL?7s>Re0n)nWpRal?Ep`C;n2$RO^!!xb)}<LCt?+s5C%P94?tmiM-EPl4f(#$?I^ z4I}wyaB6l3L*UBb$AzHJ#nJ-7JN`lbYR6@teBjr3-#?bA#!+4N5hpp&ZZD?PIHXbb zx;z0uzgME^WV{u=l>wJvdBLamzFxP_TXLmsC1VU$fBL|dg+C~x*@$~DO*W=h@2k`V zK3R)^7R((BP)+nqJMf&{vz!Y51yCu!U-^jR_SQv}GM+PipExctU;IaNPi2vz+xx#1 zg?Z1t{^y4e4D^2g=N=5F`p|gXoCi+@sWKjZ9N$uY_+*A%T#g8mqE3s#f8U199{8VA zB0-Eu^KF5)ENb@0s#@Q3ABf%NGF}ZpuK2%k{JfJfSbz%f0uUV#=M?_dPs#@}(CBCI z9#F9Wwc>-@nfZQ~$sw1eYVg76w?1zL0pN0B8Q%64KcKqgBf=!7;(e>@$pC@7lpuJ4 zkpF`uungPXVoG7~es+sw0mfN50$@jy3ThJVG~dvL7kMw)SOx9Zj88Z(`Ha1KQ$vuD zX_kn2`0qL)n6rt@yF}qvhrdp?f~qtbJq_53eup>=;+M%=#rgYvAplm*-ff})?;D9u z3B>`jlGd_6JIM{24UwWkpb}nwpmAjouT8P={XE{Dps?v6F}~UFP4&L`%L<{@;vNDl z>4$j(lTE&)CV2~(_}nrC-K-cRdHjwrUI_%jAN|(=o&qL?2#n&s80(ELVQ;MH-H=p4 z=1O}VC6`mdIz)K+sF2J!u8z6c4V%91XV7VeGhiIOKG55h6WQi6ejpxI21tql;SEIS z(aZx{%p>37lo%jR21-2$-*&~y=RLS!RX;|;SS?>O8-^pb*aobsuff!~%y3C{V5O0v z4j7)|WUMSkJem!x3{2d~_-I^U1K^D}$j)Qhmb_}xnJZ0_dPdFWQ3AktB1Ds>>j357 z4f1oka<(tTl^kOCYurGE1{MKy1B`!wM$K8lGIsuEdH}9#$w7}rbq-x2YOa_ZtpSVi z354W1wTJ8G=AK|8P<isWicGMKFrH!{77V3AI-vqnuWWRTH{~rr8#PMlQxk+WkJDqn z)86wfe;{*G1yrE8%r$cOTbs-eh3sZBeO@70v-KKpmr5}iq{J(yh5$b@U-{?*`+Q(k z($)(c!dI{DU?w9a3rG=<{5JWKW^&KG-G(nWbjZYekZqI1QtpiZ{u!FzMOh263k#&0 z5E}}}<=JOu1m)?=5uLIe?^?-H_&~0)?+7BGo*&<7zKM{TsV^XD%h34b+IEaX9V|fm z67o9hq>kL28+Fo2Yc^ey!3HN?sy~ob+ceZ4Z*-X9S&ih5GuKYlP5>f49k160aBC)R zq2IfqY1;W|%P_T=4@KdWB@@zGHxwx38WXb$3g!jmtk%ukWKRx-*?NWJ_Zte`R!j^& zBn+5`aLI*Ag{Q$EiailK$tx+ZD!)1-8$2v056!+X@cxX8Ech9WFH6o>PV$p;ex^`c z-Lp@vuLXnIiDscP#TIRaQcRQ7PZwOmEjMI>`!26I!)<Pa2BV1-l!L|jW;r-aTAr~M zQErm10xvHISBr5JW5<4&f3g{q3x2ZUKOOW)t+={$?PpDEOAkH5M7T^Px6Hw!)k7|L zU$U3F8L%eqpBZ_!U{jW5E(3fzx~JB_wLF)HtU^A%UV-bWSSX)Rr0?+M%ivXwU!o^T za`iEagL*>pMpTOP7AV>zuuPkFTN}hD!?@iUMd_KIfH5FmwA&b;O@#Exz9?J9H8K@8 zh9GvIG{K$oxtg4N5zfFizA<>#Kpz;}uW#dp10XAl)~_RXv}qqjiQ~05tGUMZ5Nl$Y zNB&kJ&&zK3PcOknZVvm<@+Bl6sXv6!h2`kWHYQQQ6anBU>S$<JG%@RxUY64Ee59pU zTNaE8aT{?mS^JbW^?C-jE3FVtJ@x$X%LEucY`9)bGhvW76Ua?jD8S(>ji(^|U71M_ zmdNvE#9_*N)9^D9x_V_(D#*sasgpI{-swO1UirOBEfW_SqV({UL+)ep=Ll_ad}gTI z>X#=J_0_PRPf-Di#`t#-xE#RFknw1(KtiWc#2Nw>$LlS_{7m!`E6p~)Hw%j{Z$D7J zp}jjYQ5H@-{UPY<Wgc>1(S)4W7s9l|Shx`5VVeA7EHqB$tFN2PM*74j*7)y_O{*R^ zi9jS6?=`P}Oulh>Z!J8ytApsa^{^Hu%0)TlD<ZQZlXsyx=KY0RKbv3Im#F9kjNtxA z3xTP9r=hz`icK<swoh6apA>AjN9xrWTt4A9dyf4+Tn=J&yphk}cJK~CQU_%6Hjch1 zmCt@6v4KFC0=9k4-t2jDWIKy1mk_yTb58Lm68hD`ya&GgrGJd=gsgv307N*p>yR?O z-^4V7hHN#29ve8?-oJG!z){D>R)S)4-YfWzwfYJ~%r3s4NZ9zP-OUr`J%s{z?glWk z&8Pl$5}}e_K=#bkxR{%9I5u~nBqpC6`L!m{wq>1TF!y78gl$r+zmsa<bP$+htgZ0c zic0Po>n<YRAM)P^_WxvC17w4xb|@y$mQD#ZfBN!=tOAj}Jf`(6V)!NP^oT#mfR5Rq zAILG}m9Im39TX#p)Y2Qi+s3#*A9=3zD2RKXY;I*;AmJ>{YxBG00w;chfpugnb6!mz zU*8E2xn?mA8H9<F<5|A!4d@pzQK4OvHc|2O@|cv|vQnJ<^740B0%C84@|L_!?z=(s zYLgm-$+w1{HP{V!`}*VVH8IOQGq)`-?~N<>Z=osb{*_<*%6ApkdyNKb2I^bEsvx<P zF>P6xXh6(-<iu4l5u!K3TLB(Z+apPE*g`{g^i;R*jMqPm=llkX3y3+H{j%+Sz11<| z3v90bgAI#bGws2#--YtCl(gQs2Kh(+a_6d#@}F;k&h=SA#Eetr+u*BS7zMizHRuxo zbr$B(|MJT2>=+&IcReo1=kO5FAqsGe{eJk(gje%uGp)it{9*qPG#ve_2O4)jj@Z0w z!<p!NuFm4K(i)1Dr2jHOJXZK8YRs~CtR9w-QQM`LGG<%RZ!-(qp)4fXti!Hmmq?MD zbirE2>{_<OI&{kWLoU(a?d?lN?_I+NLiJzch9g<_+8pD%!o`OsN$>N|nV9f|R+b70 zn(lq<$VEMXMg3>~s5U0(g`A^Cx!-qn|C`IkD+kezV>Z3HdD$wny3sC<U5_yXzI)?A z8n$GOhhz;4r(@r3h?LVp4<t0F_Hm;Jp_JpPpQ}~UwYQ|l-CeaYF$XchRx+fzDupD= z{bQv6240Ft__b;IHZCjX<k_#l;>ZWFFG8BMY3A4;xAkbWC~4!j2jcMWCY*yED*5rg zDL&l0e&+(+Sy5J$598mJiP@4m*_6~RdF@lKDZ%1P!Nn4`UX)!wYT}=d@u`o7&b_FX zcB4U<;>UcoB5sZS9vDDp7x*eL!b+p3%G&cfWv2yuRRfcJ-L~Fzj^|%I1-}KAIX3pY z>42aCSGj*o+gHc-`+?aXE!!Vg{f1+|W?NOh$@^HgS7e(~c<iB<Xy}el1KKxS-O`*$ zPPT27uzNmq`Cl3(U#ni}+HtS9YPK!g$tpyU9K$&<6wG91NhY5((G>7GER5YSd-L6w z`JGQ4?t00*_V>XR4M5=qVbY}TBqh*1@W|uVO!h<PMM-#dPSSCWQ!)SL<-ygBy+EM- z^jntcfw}3d>hpR&-~FNnp@lDx*ID-cXMEM}xe8e!rDHIUQZr~S^CSJ%Ew#p2{lS0k z>-Tm`Z{;qI2f(!QgHG4`x<v!fK5xG-C`EXi-leS2^xm=YHe=27mv{SCdir~Md)LKt zz}NPh_vCK=FmnsN_**s5R>!zm$5tRh=aM;5Tm7Em!{M;}E}q<<(xGnDAl1R#iw@s= zR@Tp86@HdRU8Wqn&7Go!|DchVqW|R4A1VJ4(A*yov^hc+=6uQgB%fr6f?w#GpzmDA zRnO|DEBf+pGs>RzR6R~Ae`Nj~XZYWp+kWf~osW`&4ff2uwl^d$%ij>Cz?4lSR=q}K zfM+)X9;N59vHTx6>Yoow@@tg1dkng3K1>QRkhM*Aqm#WUp`)O4f7N9&P?vO!&-r~9 z?IKI<jXfGien_*VH#a2qjz2c|=$S>BA%OAK_2r>1_`uaG5d`7+>-H8u=9K}1pJvnu zfnWlFjXYm^nUA&6&Yg8~%>1Mt(bIElT^9D9V>g7VE~=NmAsLwVB7NC32v7QM;-(D9 zF~q1~xoryQj7(<V=XYN?hTat4{jc|Ev-sm<AbtsA@l7^~X!{kI6O$vUXCtyMoc}{i z3II~y#U*_IZEfh4^!}@3u8g+s3*Y<y{+%Gwu{!^kOK=;a2brF2;R5LFR3b!ydZ;9* z%EACV`L;S>^wBleFgGp<b_9c(4aUL*D9oYh$*EFqYvr!Vu%Jdd`vpHxi23>$K;zm) zcsJ52q!A`6I;lsrRh#O~(CG5XAp24<y3((afiNYCurcj))kYq`wQtGwjqMPDLghdU z^Hkhgj)G^yV!hXRqx6Wjv^t)#K*DvCPda4!^;nN6iXg<>N8_KHD2TkdfwS76u0Z-5 zO~BZDK20`-O~Uv61yh15=zQNby}RPckemToACn(c$+qkoE?dqx{0JFHmX#n?dy>Ou zCQ1_Aqw+d8Ca{XVd>0?tAjK#w%8?$NGp>;cB`Qh1;%j~;^Mcc5icu<1ZQaxx`k=6| z3LMTp#3nuU1wX3;B>`JV7yQ_!SkVL#F0{-6aC;`A0H|Sa;aE;)?FI;q;{A$$;1IGs z$OfAjyDf;4_&Qd|+jUM-5xsay;xq5Ey+n(HqSI|*;l-7ktdJIGO4D<XWo*+oF*C+c zwhCv=&@w0ZlQFTqveQDw^9>r{Gf%`=oGo{?XBZ=t=cY|D_HHxgg3)s`mV^?wS!?;^ z0&ZoL9m&4;NNr*DxSi7)<Rnp7(A3<luRM22sQd*37`2^1*hTv=EOYD(%53t%&NDI} z1nwxg?~IOJcV(mSv1)A}*@bWx0u5MXi}$4qP8&!cSqb2}<oIg*qzqy=K|)Sz<y@1t zw26nZ;m<K^$GGo`hfTqvQ)UBp$EDf*ff!{g>%v{p@DFr_o4rj=zmqqtfUYrl%R+W^ ziAl9W$E)RHwP#){CAwc<t(-UJ@(#%(#y7hbqN#kcidc#&@Fo&76>_|keY>F2MVegT zHu+?A-m_X1IYwKpOl%CxQ4b=`1DuVhCO^}+{Y{FzaX+=sPAB<j298%2A4~qIV2>|3 zB8y46ZA91GaIBGBg|r_Q15#L6)t;2zk+SkCoQQt%Ht$FXL><6kPcG%ZTbA?qo0&IA zunmE}p&X&ZT`(f3>TJ?pBL$@6i#L*6X9q2+_9r%-d6QgVS13YZcL%0iY;6`SJO77E zc<z5hWqf=0{X^9A-17=`UErM^;*P<ZVy8}krqiL$BEeSGQ;}}i)=1_aO@4nRb^X9L zK-q{(k(id>UYVJ0^elz_h+YX)Ml05ZvkWM9H20*_kK>m`!s{|&fbo{>ndYW|-{s~w zMF33uQX?)tbWx(z&5=;Us01Xc(ec)+z|Ez%%T#_7OesBAT5}2ETy28ur03<#Ry+;4 zrt?AGR-)UN_ZiUG-(}yDb5r*m@T>O(dO#I@R*kp}?-kl4#c8R4138)m%;g=*C`Iml ztYutxwYjob?y($OE1Bv+Hlyt&q&tHE{CcPcMo>$%l?n#sQstaP<jJTbNI-#bqO|X; zAu0ERz%62)#wNPxCWL{m7%ltb&92ej?cy^aU~TPCUS8F=Dy>#yZ7&vvsOKz#o6bEr ze?}IF;4SdPAIcF^6A+L;WLZic6{6dfug?=NnRytBcXsJUG?=v*w=<^TVz~(Jja6mw zY@x|h<^PYcaHy#L^}3PPP_5=>(*kgXgL!x#lmTNi!B<EnH=$OS{T8Kw&UTqIorO<Q zo>ep)^sO82)Ht5W{!*)G4d@=vf5tZ1o9mRbn)xdYe|^i9VwgT9!}?#Ch7qU?fQnGB z1nsoyo37>Nbx565K9vn|vY9>%NxCBH&wx||v&BV^GVI%??EV*~F=<)}IVA<atcVak z<o^$)QPqA@>$CSDgv?zAqOkm$xz9W8Um<k7H+n*XYgU7#JaY1Fo-^U+c8!t5GZ06! z+PSN&7%pNxSfJg4SJCQ#hYxnvEk_91I&jc&^G%`mwIHn?hknT~5Tw;ndo?;dNBBMZ ztd-L0i{1+(lvyT3d>@a@OUUWF`VMl+_6=(2@Nn?TjePG!vet1c%0cfZNMY!6z4=J5 z3Eo%!Isc~d^Gb4V+^?Q~6{BAI@RxO+)1^LV-jBR+s`0$Y?$ekQMJcR8^?}k~*PQeZ z`b*c}5Aup)*h*fEd=UNq<BWh>lun4=yn;Y~rp`!q(cmQloe4rEOtS&jB6Ei_mE3Mj z)^^?Jj3Q^NWKJWoBudlWbp%f!iqoY7@~bguK{tG?)eLiBRih76=(^oZChau*%iQq) zu9s%kl;Gs)tC>};^=SP;PGZ=(_wN6tH`BQ`i!Eo?8{xlR?lgSQ{~<KT;Cp)KgV<%k zmfA1;Q5i_^QP=(&>8n%w-5UpDX_Nf9oAQk#k;J7qr^`)7Do4-H`-&?PH$-(Vj?Lr{ zr+lBhCH4*Km@MqEm+u|CXjn!X+Y%mO@77=)-uq^F8?lVgVJx8@$ll*sVW5|UDXy{G zG*ki_cDyc=P+tuZN}A4**CgXL2h%eRX3lE;V8V^OAd+STp%=vuF|l+oS3+DqOJ|ye ze|$FQi8Y3eBKiuCoI7vE8$)Hg)A4JAh)QR|8>lE2{x24c&A;^nKFafo`e&J&OJEvr zHu7D-c#DXFYj%BqQg~oS|4{9)-^MM=<@o-6@H-Ec4}3BBUyU$#DnTe{L50S<M*6-P zy~>-7(u`e*B+Z4#z_5;nuNd>YC9pN3^1?R)eu=XE>M5In>?+ZoS=70SKL7R)lg*X* z2`ho3)8CO8+}Kf+jRSs;%ArrkaE)Sox|XT2(2v^-eCOFbAlT3?6f+0*f&P(Q0`3_D z=g&qOqp%^dAEyC=8E9UC3vNbRLq9ic*hZz1s-evYVK8cr{w{z;<>bgd611XiJ1J}y z#%#u@f5=e`&<W$Xg@59-Z?&|8<yvMRMg69~TaM#O#>_rZnRmj-KEuy@FtFn}+_5__ zSTjG5%6fR*f&hW@q8dM2GZZuPyJ*|Mqx*d*5#<|C;Cs#{vW%;b-XTWA9O%64JMbj@ z2M?-H*i$YJi7%l~H+$6PQ=j4~i;b)7-I!xe_)|N4uJ%GH@px49JF8f&0Q@`yV<a$w z62ZPc{S7XbAn}ed!w%*ZXu>2oN{YwAYSrekJ))oRE8Ecvqz=3ujl-LGG;P=o#`@`J zTZ<1wqp7SvRFS`>1XX8(O3-%?1{gNV(}|wrOTe=Z%iuyK+*g<w$}iGRC<7nj%ogK> zPjK2hl8KJ1!LYlqxkm2ATf4-k%<OL{nVwxYs)TrtI3htAro87;vS((>>&oQ*DoHTj zlJX2jJ&QxXE`hfu;CpsqjR_0kL?K}UXCd7Xzr?nr_QQaC&do`-zm%}xyuT5P&sLis zdM+2{h&Nkeo1v8Oa;aev&2YqXydHt`9vy!a7Mey>7I%bs@DRkl3BBIcW{cKzWvYv3 zLkQoDPTyMaGCg+F0gW5gRNljH&fpp9vWRR{=u_=Sl8P6f9*sZ*vn(vU%yxH1BZXT9 zmW}?v#pd9O*D)60kkG(z>su30hvh7MPdV(_L!Q%=Z}PZi?Rbq7+$gNRy{5qu+qW4b zF%8(Zi)KOZrjg56^r+}R7yM~%HteXvRab-jo)c<u3w0WVFXcM|qX)lAwJS>T?A>bC z#z+_CpKvh3upF<T0kf*aO9U<4;89IM5d_p=9-4%0*Ar=))7z@^`%aoZJaa;oM%sOH z<`9bBV>M$}KoDVayq<?Qv_qdwLRhv^3y-npAb-zJB53dLbAgv!?9(bWVQ$=_vaWbL z-nk2L_%RjBV>`+`<b|v<-h55iX426VDj%^L8T*buIp0r}ISMatL%B|zzD1mGwky#f z&^2I-bNJPA6x*_;aWufqYF7U*)^N;$0t+F%AtrxsX(aSG81tLF<;A*nqm;}w?X8WS z2vzv^m3T9nsypsYmXlJ1=6q2S{;kG5ySrlvms26``DsU6(Pd01%KTd}5r>m?suJX1 zcHVQtZ;%$WUx<gHTv6E&%kzfXJE-e(coK1sF^7MP!5_~<3&+|A&)Z*2!c!t~cvoeN zcj8<0vZt}K7i`qA_#p7(QDs7RnIHA{#zScu^SOyy0#$@V%ogXek5&a<NeedAkGCn; zoR{?T-S*}t%kEVL(5f`--R)hKU964Ga~wmAp9ZAh=AbV4eJ$7zExxljQvAZxObyL> z^7n`CMp$<PmJ`nS=PW-3V?s7o_O&+lrfCv}4{SUoITL}`^et5TVdUg4irs@iJj93c zMcw3!>OBO%uEM{?opkpI2<u=Q(>~R$ZQ83I`X+H9azHZiFy{4_6Ry!H4^z7nnkV2% zK^1QMLO4R(L3no+-ar!up2MFa?l*d9+GxT21`PTV2^PI^!jx=u+5V}MS^;d!Y(b8i z%i1B99+opavF_iW<h#N2g0y1hjP@kMy{`maJNSY&QK>o|V7q{aYbMM$n+GNt+*!aM zI>+!dpJE$LT&fCZ%Z6)y3&Slt1ip;=bZF$7lHBk4gfm&oW%uAP*wk==aO%5G{CE5s zJ|014C5U#TY$;#y^QMMr7YvF9@diN)PNx(7aUO&VyrEV2g{LO*%}E{KlQ5(HS}7Sg zoyXM!o8cH)uDR7iNu9hy!-|UziJoWJmM!GJ<DXzt<4umIP2=OJa627J?+bUHW+Tip z%B~t7>Y8SM!TtolC5Hs6WC2fHf(N8VZ6z(-c!>`kpoG3*vMDFf$^;%q_J;CE2%mjv zH0Ehg>E`p)bN|;x{OtFaNR#8PM5GFxXTnv$_y@r(Xvd3j);dT|x|-0l<2RFRGe3*D z-|L=nF-?>=DMy_%h*@Cx;<zVKxwpp?HYyr*C<oIm#Jrx&Jgvo*k{$Szutr>LV6e%s z1k=sADQ{$cB2*5YZwbJ)hHPF(!$@9m5iWRppJ9&x$7O&^XyoTayfzyd*+43n7hKOO zEsyw#_#se9DMbl1aX(|gvz%Zm6^T!^=YM^tEG3Fvp;py9vfbU&vrh@cNocK?!HHUB z{oa!<X~#Vu1nx-|X_TD|64Z5XtbmQix)LKOFcXz^%-lYA!n-TxzI3=jm?;Qb|GgWw z=b3N29}*?taQQge6~*>r-+?==fL}uKb^ImK#fg~xU9&6mtCc6@QtQkQ&2<Ii`*q0n zJDRac=jJ6)NuA4P%6aB|d9Y>-JXR3%jrQP$`@4S13vIEh)L>(KHufrN-j8$^zX>13 z^k-9^-o*Z)i>D-)Ud4&A8p3Qpx7M#r$pt~oC{H@c)Ub-p*R5rK8Jonsk_eO_vPEJs z^=#Rw&F-}Ys?*=srLKJET`_ES&ahOx={GI>wVF`jQJxkie5!x7FTD-qJDz{KWM1N& zE0NkU!SkmPLr*a>pkbI)E<CO9jhiViK8TCSz`Sxb68nw%Me6x$x(UwcOKC6hTrs$G zq0c>|KYmkuCrNAH9VU0FKjQAd2Wzg-*K94GglYVs<;ww@{!m`VP~qL7lHWsR`nRhx zZr5CNjp3G}T)Ok8fF&S{Nbe-3GfKGI@i|la_c^kWP*Z^2x}wuu*J*S`iKfRV@4|-% zLH|%ze+SY+B&ZuT;p4@6T#<SqE^+LQ$U4jKmJ%VG<uWpbndjujmPb+J*uzHT{mIrk zY78IPm!*G#7^EckfN&_AEHmuIgS;<WnBThkXrHorpW`YLEGH#Z$7@l<*puYZF;Ng0 z#i|tC3-&uPlY3rsa^yU_Y?o|?-Q;Pod`9_ZZ>L|zY;a&wrc*$eY~+e!xSvr$W{pFh zq+8@<8ZWO11K?u1)*^T>Fab^mX!;Uwqs&y|*(kfu`gbf0_FJY9<8<`OBkLw4x)I=G zP#$cpJdtLNPNWo&Uk%TuutlE!bo$S5pOCC!f}ivBQG#-iE75oo1)BvCXL&|_bKlPT z8-^TarfApq>4_Q+`#Ez-j?2R4-T&f=1l=i-E@J{(U}IbzgckXGPt|{6FMmPs!NO%J zXEAt*YW~ZJ=82p)STRx%oat!8i59|B+#1IFJE<V-5iur8s3R#Yyfq~Ir-YvAi~MU~ zBpO$Z2MJK8g-yb-3{bgYnauKI!uTR?IeGu@b3Rkmp10&$YPi_25uBm&g}ej<D?qQj zyJy=d1D+u$@boON7{5ob&fv2nKwtboBEZVAU1V(|sQLk@jrr($vqBvlO%XXl?TH|k z7?XLNP1%Aa0g-!gMQZhg(d&_LZss~N^D0ozLas8ns?QSCn^w6=plSy4)tiih`$6hU zAZ#OW)N-*=Ahc5vLR6^>RHXU@c9cD<Z3U<m`}Cc<eBu#81OTBMLABJcVMeR5(mY=q zj-2rTEOT8v8`(1&K{;fA9+D9^@UN^1$Ay4zt_@!~z`PDOPTpXFlmdg*340vOBi~Yl zRNdAa*47)bPfKS*I;jZou>8X6!bb_Wq%(weyzcNj{AxqmKp|o^;GoQi)Yq`_`7GfF zUeRC-%gommBmGzM0r4ygbOEqsHzJrwzdKNJgEqLp*J3v)roZ`{y|WOk;jbs9@qw2` za!pBAgd5BdQuDlUuzR!Qr60}8#F3G-jV8E6Q*IVP$5H|yBd*h+99&8OzG*bio>Q-{ zN4423uTg|A1WRhBD)6zXRI^hhugeHZ>UFc<m;~r3_2eY5dMLFN0ulwRnMivm{yV3i z`V8_ZrO6Z~XGfeWrxl_Kca3#ssE*Aw7b+`LiLx^tes|OV`lwdqRI~pWK8HvMePjrg zLZTN#nx>l&QqQ)KQyZgzN^vtRVt@qcLk^VMTalPcN8UXtPxhV35SJQ06#=2}AW&DG zeg^Aklp8ZGwwH`b^!hjF+r4kO>Gb!XDyC#igKPbrVn<o8MAH-u3iXG!m&S^Pk2}D& zc8>JUkYAVRlM6$XV=tb#@kaxn_<A8$KxD)sF<<s@3+cYMuy0prk}KxyW=UKQR%qK$ z?J+BLCxVZ$PuVY)t)uO><y$V87mxP=S@54SWsY;NlWSuTA+vl|%$YGDsbYqgB9`P+ ze_;|Lb97o<BwrftBlE?cml_NcOvMA>q%o+EhaEdm%tcejKmzaaV{m4lJg%H;;SBxY z!7W!=4G#Zlg%-bM-$y)&^iH{8BCgFAT1_ss4y_4o5L~P>Y!<9dDbS4@$Jyx=T&f-R zh7th#?#ZyrS**gvVz^TGSsdjpsAwZDlQ9^^vh+051i)YwDJRRAX6bU{_tM)^K7O-O zSIun1J}sn&Yeizpw5HbSa>w9K40i;gM%>EXOX9Q1KTKtq$!#!+YOX0(-DqskY<{!V z@FaZJzr}lqX;!7j8*TSu;SL>y2q|DjUo-SvG2w1GeSIKuG2EKAL;*V~88aW65lfNI z-gIdm!uEU@Qgjhh&ZaOaWtE5N7XVE*;o8j)w4z=+aeS=}AHzD@#gFqPUX{7W|K={* z<?%^7w}!R=yM#%Zn}-`FfelX*!WzHCkBg~37TGiT<D(e?)MS&#tB(65b(wH)gKT6x zR&^O^(6nnWLH1*ll(F0IXQ7p5qyr=ixbHB-nK*?gIpu`6KWBLQ447V`{i-FYb{gaw z*tFIbr0h1{4H<^VQ;?|XT<;pUk&Xr~P`UOXw8c<+3<8sg0(*w+CNS=z4pe{)vy2pz zXQi#a)(F+^;IkQ5qnthhs&qEFM!%*&6IcGRQ*WR$<JuH}t1&daWTnC5jdM%Ik-9>X zr*vSc;CPdc{6!Tf7(PKr`sPFE-}Jkl#WqrZi4KkT@Q_Exn>6KVV+MO-pHN>^vjxY6 zukjocig21n;FwVHOsA2G_RD%wch;2uaWep99Mu%${g}@U(8E2V>Ibod#MwtG@@_<9 z+VRe(EGU&X{i5*q65pNIJ4z)vYo+3CTRZ{R=vM8=Nb#_4G<dpI(Z9@$(E@8o<U209 z=kq?=AU?Cxc}?=J)|G_2r;EzVgzM%oBW-<a=0L;Ct*CO7*n*KKCQLXLq_dQq@#9@@ zQ3zV``V#_2Vz!)@7Fx`3hOoQ0Oau?q#CF&cC@#Du!>_I~Bo)k}Os_u|8k{x$mv_=7 zyT!*0%zW6ff8(tG?En+?@fz!<^D_PV_29Ch9vZY1glre$iCAvc_l~P<QMxMc8GP*@ z0g?6CxLi)$?1Af4!iDjrYLit9TM(HpQ<WoSeCKqYS^Cq{VVdl6otnVeA?vd+=PHhf zQ3~I&kMW8Qa@Iikqbioy>GAx4rI|0t(JR|eQO3Xo*0YV7n{+=RJ6@!S=U#b7Y2UK~ z*mXY(A9Z0V!wUS3Un|7EO0?0a3t`#M?k-F4TJ@3&z!}|UD*kI)FW=(CR=cN3U<5rS zA<weL&(BQzTI0RRX^9KeX%O}k@0~Li<&=-Ka&z)UtsFqJ_=VIeOZ^TyeJ$ad!Pa${ zV7PiUm{>OkQfTP=^rA%pr}V&X%>`26R-+P9?tgp5NgwNQ@?DRl=;tZ18{76>A<IY) ze57Zy4R6fps}vS=+C<f+NL(SetSRV?v1s#5hg)gYRo4j1+^HuE_=wsT)l0_tg%sy8 zy|Ekk5@t4Yv1*uwHBXR}Hveo<%d7Z>*5wB>!^PFO<o(!HRFbyY`r$+W^|s6AZsvrE z)drnWb8x+{qa*rhh+8?zwegYlN2lG~r*Dvh*B)eV#VIZ<W+|@%?o6eBhZa2Jd}H>S zOCG+ja~GQ0suT}y%Nr+MF}dwfs!3^p5_xb5?@A|*wZky{$0SGJ&u@hGKbPJx=QDX# zQ_7i-qMicI;s7@4X~nEB$lR>ZvR(28-BQj;8=T2JJ*Houz38%^9{F(sSDs;&VdvQs zoa6&NP`#S~>|y6C^`C-+I-Q)}r%gp_6`g2fJ9*vJktrI&5QW=(x(j~<n3P;D?hu#Z zj*FdrwdS>Rth1f3+zXKUJ?}a;S^<u>o~n+_sxze(*(xhJJYv&Sm=qI;)H`;uzK@PF z{c$gft28g1>@Ik~J;FC*Z^@xpc4S`w@`(F7NyH50vQu3-WC}v&>(DYhxkXXSt~r*U zaqQ;RK0mgs{w=z{7piCuqG%FY9FjRVofNesdX)=e9Yg2esmTsP{?@ixuCy}m-_iLC zp|*z^w({>GgLGvkeiFxmzfJRB3;SBpsf_)|(HS-VFH<?JlQ>abEeL$7>MHp)WLe8_ zoBw$#@jSnT<X_G=__sc4_&@#pupfgV89#8@e5%ZBkvn%bt|G2*oT1cNp3oswXj^UR zxGiN@4zeD2?x+~k3u65gGnbT#3of&bMiyIlzBE5`vzYQ=``HkpUr@aC68>Gh>W+Zr zR}U*tlFwzvo#a3(vB9SGJHfI!(yvYB)9k86UzYKFbeSSd4eOJgQpC*Pa4hLWCB67o zM!kz)R%tY;jz%<C=2lRkoMwH}%_r;TFDWkcf6o)$dil)G=3`}R!Bw0|m`h0Qk%-Ku z!&q#0=!ykz;}0{nj}1aDms10jquy1#JGcBnO!ynbc)0^Xsm+rX*||BRYtu#tl4L`G zv_JjaIa{-(fBx9z9A|&}I;(Q5P%Nz_7VH;>OewZfiQ@7yIbz2tc?<S;7f*)q5Ac|r zK0j)q!?L=DI6qqdv(yi<zU(_XDp7tg9U|kous<IF;GJiIWzeyN%*es}Rh=oT@6XH* zhS^*)$^+hd!Uc6Uc*xtdxv$^O#hwUI$FLhgC3wP<PK58@uPX3-@{OdI9IJOeML3Mo z(Ub~F6#={)-MRn@Ycv|NBwFObWBxLs9-c_arsnZyzP^T@T*oa}rNc2+?0AQNYl*Kc zc|EjzA3O?0U}ACQ(W1@)w|J5?q>c=%)a|HRwQGX66Y;1vp<}(!nTPz+UZ)1x0NhFR zgITYT<ul~<=*m8{Oep4JC_4Uh+U1sjx=^a`1g?g`=0QQrW)dlWuLOTs^8T_^`}0zS z6>f!;FwGYzh>r~yg2|m73OeHpLUOo-6qlWTTItHumL_Ax<3I)A3_y=v;)uX!+XlEF zxvP7c3JxVYz7lL($9ZVkmuqDBHz^EB1@Oum@v)^=Sn~9EqNDdcu|IG$hL{DLkO8~+ z%(@7TB58VQ9c^XC!_kv_Fblw`z?VTjq!WPbO0^fTt_+U`@OcL(GqTvtL}y5!F7k3L zB_vPeHKN%)NU*?gSg8|bL5DYVBPsKdx)t<X&kQ-6tuQ1!m8m0?v{72}D4{W4dPQ4F zz&&b8s_^B-a9`&rH3^R|WyCr{z`7Os*Am6e&snvJ5O6oOScbn~IVGMk%fboDIKRDE zboY1>!Z|pf$HMY38o3i;s%F>oO0bJv)JRTvH!-RLOyhFax1A7EPm1w}@%<vxAwlOz zpsd>hd101W2b%7xZF!;?9TUFu1s4&4()oc0I@W@v9L|x@k$mix{F_JS&Aewr<S109 zPl6mP^njm&DFV6W<r#0Yfs|_%j}KfnK?Oc9&zpiwE!p|zM`_NVA_JZEt*p@x$_*Nw z3g9FlF09c1$O*{``5+{~%sHym3R!RJW_df?y07d*5XNKNciB8myfT!FAYc3{indRy zbH>?{YOh7qa#L$>{scbDcoYv6P%O@tt(>*=Q&Un2b1$)=kyddRSj=M}YJs@C&u=(j zZHeaSIR`h+gJUqweP&+lm58MxvV2N2n%zB4@iGbVN|617RsFIR56e^C^QW5kPs-<s zyl#v7I?#pB5ke_)CtO+-Oo+%2)v|8uDjjX--FeIAw7q#oF2XS3Nt1#Uek<gzWVZH( zMzdR#=o;<f5c+o#jManlxC*%b<axbo|H`?N3*@RCF2u^d3@N)*B&mzAL0=$RDIf?S zqGJb79dCsggb|Ro9L87FRD)N9Z|haHT#}<n2abe44>t@-Irk?&6j@dW>#l>*%s>oJ zuem0!k#O_1hWNoscS;xA{zXLE5s{26Wy)u+d8@Cn%dkGRRi#Z<;nS|ZHE)gH6uhJD zI(G<oFbz<6#e@esbL=5@RI>}WF9S{`EzEMW89j-gxQ+a3c>GC^3(6&t4rcrqwno6c z6-d!G$8-Y@U2G0r0PRXb4b{Mb<c^{{e42ya6|iFTKm(7|GR3;QH-!K;(n(}vdFo+| z-87W*sDQ;g(7FsAoC3JwZoFBkz1$=WndZw`1CZ!&6}E5=0>Cj1wd<nJ>DU`!0p#@Y z@1|DAtkwH9I^JzUIVv(>gqwYl*A=`23e-ZS%Vb|y1evbmeqlueyDKWkfRfsFdb%u! z$)z)L6gTZ`0I@BUCQ*X^el||%Xkrl_0L!B>&f;YRtg5R84MifuffUp0%-$SsIsj7z z7MB4@K_PM^#sbE^pwLs9o|^g!%0Uc0Dr-4aYa5Ik?j5vtghsUm!BE6d$(w*J`ij{S zl#2>LRL^mv8-0yoob)~@@umZ_S~G}($kOZWTl8BTZ@t{zGn(2yQigDt2CVOfxj97| zKzeM70hCi;a}dI|5fJu0N;W3d&oppmQ1+~Nb`uri;NlGHpg)L<EM4B)HE7aE;`-vL z&)EfANcl#nI2`YAb5W{K7Xu|qrbwHFJ4ee2V(8izmEw~&v|4z{m?A+Q%B*B^%+3Io z2fu9$kbI)NXxMcu2EoFg2r7&j)D!2y47AX1iN<G6gVg#HyCE|z*-fH?7rI)UZlnt* z95o2t>1=dKWJ6b_+fhb{o^U1|Kr{jf>h(E^`%4+^E=AJzH!E%}YL9RztpC2Yo^k*E zI5CYK3yJIHD?_B#{zqy2f#X!YzjRY(5qp0{I0&4{z~5n8QoNsXy-TR3HQQB)>U1U} zq(?HIQMzZ#pQ-mg3d2pkdw&^l_dRx2q2o^vbl;b;uXuld6}taf>0`ex{WxQNgR!Dt z<wj*70Bd*EQ3%}&G8HTHM36dthk?B?rNKZ_r7G`?d{n&0MTtMVSW*5}ZPd~^cy!=W zK8FMi&fuFNv6QTEiM(}k!{?zOq><irvy->M8oY#N%>0`gGZ51HPq{XY4@z~u#(^D^ z6}q!ycJu7%7xKem1}7l!Y6@WtD)nf)d?d1NY`(P_?+je%x@#efxv!Uan}hGcP1Vl{ z!^uz1)%hwvpy*z$`=n@LFg_}cyg-7zRYYD@ecZ_OKKZeJyh$M^63wAe+vs#xsQW*o z1u<D)$$|(XjW`BZ81{av)_w~8tS*epxr%M-LW@Z$PhEu>=ysY+aR=nYm|e*&eRS0y zemL<N4^k9P)T8|3Z+6pvfsIaa(SNRw-X4GY^&^HtqbM{ICosmhZy3Y0J#$hK;#RMw z&bPIi2C)#_)ELk-0NQ*G(W_1>duZxGt5%Z_dW$jCNR!mMwvD+$V*qUEaCT8`2PF(U z-Z0hxbMBIb6&B!RV$ZGNs7|x%<f|I$jZl2?6@840$b|1Yl*R)f(2aJgjj*^<RNd`k zQ51Dc4GfGlu{Qz;3uE;E^3WuY`ghn}4Hv1h@UlOWe|fH(>(%+uCRjme4im4(8D4DD zI<&GW)$7j@e<KI{U?XOa8=a7iB!uU*!DT?^T>fm6T?@WvVffSOJHb!bvY*Jok;S5> zrY6&`!B5@1CE3i22Lv6%<cb#UguaUKP(-|<EJoQbMoWflsgz&C#C{&k@WZr-@-(wT z+~*;;_rIKa-G{cCbQVO44(~iytQR`PiS@Y`p_T9|Rg{M89y{n^)8Mo7UxSkRMJ^D{ z0v<08Ib&oDJmyjCHGc(Z(btwsuohpu-RSSmNK72Gl&t#kXz;y<)|AXE=U)wZd_)Vq zU+Z}2&VdZn`Orw99079pKPO(Nez=V3K!QFzdFpz=|LXDq;)*IV%ncbZ^zs5jVYlpY zPm{vqX!I{#-YQKw(gyUa0jVJBXiEf;)Vswm11{C~@Ldy6mkHf?`1optB7`*Psf?l8 z@jm9nb{{005l%3LMyfhWIsOWoQfvV3#;Xnt;C8k>)8KVR@F0iN8GMW#P38#s@g2a@ zR{!J0A*sM^vZyuZFxQBr$!Ly^%X965=cZ~(7co|fMuP+T=zRa{;~aqdQ^9MG+kHxt zHB<3^4b%Mt@3<PKx1MgCcMw9sU(jQ0UPmD=mVTneeX62<nmMD`cPiy7#R<9S4Rh;a zt1bO>z4X)RmqK^n;_e&p2DhJ_vb$9}DqtkB5FW;4g-UR313k;1xzS&eE7i=@WxpRd zYlqJX@AIB}DrifU_(B5|OjchT@a~#se84TP*PxvYd6hKXk(G!Fb-Jrp5>F2_2|PCO z5_d7%5sG2I2p*}7S3z!5>@(2{z4~Z3^p<F%#K^ON<oEgPqre>@qxfg6H=Hr6{#677 z!<_aIQ{{wp0qM_ZuLXkGd$52oROeX$`o7qgNb=2p_n%tp8mR}L@FW&sj6W$~7S7(- zReO%}=>Jds1hJWjpaSf9;BI%I`^5SBSCeejcqH!Y%ieQK#<wUXMz{7e8ux;Sgv3k5 zEH=?!XxC|7*w+q7zpaNd`{svL6wgXg3w~vjjx4c%jvP4~Z!}Zq&us-A8+q$6(m10x z&nE$y4q_^amE;{@MlPDxW;*Is-8_3ehh}^2jDzb*TPsxFG~yHot>D}R;9l_6U_XJg z&OiebeZR1$Azq%6c}wP!b#C7N#=|o&wV!X4mj1fQ9d_;0R{L}HW>#0_8wh*zG~!0q zr)uh_zDx_8$|l8MbLjjh`UAEJ$^1!Mp>r2jpxvr3UX$t!#MzmCza$JlN&|lk(N^Hr zNHV^0NcHi*x?c4fVEe6aSuY<(=lPk{xLd2uD4}LFrm+e^VQ<XoKP@nG{9)*Gv14g= zm7~)o5OfQaOKRdQ(-;o$g5wgVn-~flAi417E}-o!MBK`cKGS3dTrfcPNnng208IU4 zh=emB2LhnbDK8iDgEC!?>{H8S+>Z5dsel>pxeezQ>nfF#i*D-{bo?>Bt3LCa?(N?F zF&`J_6)6kVNbXE&--R#UeG&7WC*Le=`3}XuEb0mQXbgt2Jj}|3=3jo3yMM*3@R#Oh zMVrf2crkeV$2QZh#w@M52R~A-sCaMD&5F@Bo#$?#QZ_-|JR(mL;6o8w?IurkosaQG zE(V(wYFg^ib>>&V6&|!>Uur5C)6EW2rB%xDjuZ!IM|}dEG5jemubpGnPEPI6R6!-V zH|e%7nYv?rS8=SSB0U=lOt0tOm>zJTe-aNkA{B^0nE^SP@E!m{S|Cy`%o{)W7GtC; z`O@WOr+Fo8R5&$;Z`^MKhvSJTQ{H$ptnJ*U)@M7ncym7Aq#bjC;7VsjXZ6=Pg-|3# zhl+H8|NgA@UnbPNdz=XRSmDT9{G`IJR);}_R<oEZcRSiLROJd&pM)C%MZraPKuM!9 z5-*1pBM07EOhMbq0wB!WWo;aQ<c){>vsYI5?x<ed4u3KE)KH_SROg0*Pn+bmqhR^I zG9}RUduOqJ1%-7YRTGWp-VQs;tMn&PZXM4vI4CeR+p$fQVi6ZLXWLvd3myRNKCTiL zhPBBAMY&43mx3AQ#sA|rOnL<sNNq$YoN+(x9hza@?Hzul>a<Vf&HjaUXX5p!LJ^eL za)nrh-4oRWevOM=j_PXa>XQoI%>abYYZPg_@uf)bd65Fu<GhetfoJQ`DWWXp=qSJO zN!}Mxgnb^GQBHJ|Mrz19!TY)t^pmIdJ~Xp_xlI7|0{Jhl7~}3F%5z<8(@@CMSWIbx zY20xqpbc-JfhzGuh!j<~>Z>cAm{oM8nK*guTD`H5t|Zs%$MW-e<?c4R2;VF#P_yM7 z-RY>ihrgn_9%w6~iBk)Xr}`)_JTjsO-Z*Sl5ZjN;)>1FhPg#vYd7k)52rG_HBy;zU zfl~QN;L`L-1)ZzUd%j%!(E8R-?@H0Jjw$==qGSQ8kKuB{e2#=$I7!X*CNj#T#MD9d z#yB!9xm;RLSKc|7z5%+yo9uNB+`HFyuvrut(ezF<dw%oEQ0|;$o2)XW$aGpmFTJHj zRI2)8T_~J+>gpdDKK(4;dH1MS@3jAAvi4tiQqCN{N%?o?2V(XRDZ{7J2(X!%Jh611 zI1r9=G7I%DUowRxjR7*N1oXs<qADSNq4WD(VfNR>0GU=EYvs*^(DeG;hHH&^RnH~! zU96tem3OagTn~Qyvm&vPBB_6^fE+IqGF5%YtrB@(Uh@5wN{6f-dZzAbD8j08C27_m zPb572tUA&vvQ>k=szmmFjIdJu$Xg5|x(&Dp{fxt%P|bHf7c3Pl_%zi*v-P}6THA-e zLUH(exK`D3y0fzIR7)dO>QR9~<T)f2-m8QKa&uN$8d%7*(zi1x7RL22+OltJbUVqm z5dIHE=N(Vg|HtujuY0-oT9<2Q+<UESW@kj#wfCOcA=&%ekb7P0n%N_gof(RdvZ4@W zWF#^|5}8TK?dSLBc|1OUzR&rb_xt^NJzxBsoO0dYZ9=_jFATp1#^tq+AH`BRFBlAS zvAz<B6#36o!H^^W64EU6JthYCUh9dnS|zRtr~iWWZjJq*)h(gK(kOj#cI;rLXQrQF znU_r1fn4^j%$ysQ-inR4O#HpAiavetPCFitqg^lqMQzf1uo9=ZRO^gL+u(Ti&~R4K zJrF8}tx}s@BLVXkO3XGY(Y{@Sng9X+-CJ`*uv^w;;w*j4k5Ei^!c@8HOye7}Jz=6e zYNm37=Tg-&^?R%8)5@L|^s*!R>>i3nQrbzN(~oSNa^u4DkCNVb))+=ij>h}T3Nn0O zupIa=M>bPhkjVX4=u+Bk>q-%uS|cxCt0g(axhV<G)FA+Vyqw?7Cx&`RZH9D7?%Rl? zO95Cgzz$%zTP4rU2{F|i>R{9z7Zx$?=^MH@mFJAQQdt*G-f78~>ti{fkL3F7wbjJ> zQ+Y$n_%j#i<ww}cX-NfVPLz6Gx$0j2N;2mM1CED8eZ*GWIa+T~SpT+aoojb)?gtu! z4VaugAbE%>X^^n|fgs)45Gu_R9-1lsb9I^4uH%((V8~zr9B<wSQZej}L0)?U-2PcV z)dpT<-6M%Zz>Pj3ZWe)&j$~lBfWcGJ;~#=R-ipY1R9W*=j@5imMf*<t-EIH>+WHe5 z!|xNxa{gASHw0!~Y_WyV8a=-9xr&=v50fFi;+zK~XW{#?#*);LqqtlAePqw7MByEu zE0H;$_(#1r6a$k?qCD6h*$+yXrif;J2Ou&4QfJcEv)V5Szov||^XZLfEM074nC#N! zmDPvrkpKa08z#5V><8PPyZcIF8BV*Nd_?ezHdaq#x|^Z-4_?eyD;y-yrb$IR>v>1> z59A<ilNr}v0S?q^1$5q=R>Caz#jhVt1{hjm`F<<VpJw$}JL(rhE&CR{g{nlQ5COGV zZ}8W+zDY^(6sfy6jITRR6^TgWvObaMfKVBy2Z8BQ7E0De)1Z&SyLQj(v!9Xk(L_@4 zl<<{GRJN|pY?o=PWsR}-N0*OH%=@1orv-GT&&*;<7>=o$NCy8mx=+OmI||84#o4lb z)}qM+LYjeh{DXV4v|hdw&U7BxgbRdM$Lr2F>w&LUD9?*kYx|gT%r0Yh^QXpFU)`&9 z$X7tMFC~1wlpq%puipB6nf`sN@Fr0Y8t#EbRnbB|0)2GWH2nzE4lw#7b}f<piRE-2 z#oUWFFh?Tpsqyc&=!iL&6gP$SH%!Xrr(IL0TWcAXBKp^iZXH&W2%~5Vd=|97is+qH z$&|S~8lm2`_^0qCse8?$v^_8$`GV{aJyZ@V4UQS=64Pd^)e=7V7;}=hLOjoOq5X29 zr;B5G-WLRkS{D2sYfq~&e{A!K^Waz}lwN}#IAy19mjIoAM&LB8_@_Oufv%#coq*1_ z%c2*TBor|6<-G%G^6%)z6RE4#rFK_c&WwjFwn1&xjPp?N)km?O>qa*^^|&@pV%$`g zTJ9N+al?<ivQN;xUw-2Qi2^&au2t}&t3v?mKcq7cG->?n+2ic!BaqR9F*;E8wAFVO zneS7J{QI|GjJ?cxhLsm3!HzToz1QEi>sx#xE)hAqIDD9Z?Mic@GiOh&f3Xh-Ev{U? z(S2sc(p2=ac?Efr((|OI^hrw3^9<Gi6-8e8B4ZdtV~&PtyEj^1f@pT4Ohd2IE-ohG zrcroPBWCZpyC%SS8F0U)$(_?jQ;Nxxz~#T9s>h7KEPL{ZtFrGruZ_oAvl5SCnra_l z6;{yd2CNa{KJ_2o!UU~V<8M+(tRybBe)MR+z~#o8!)De>)!f5wO&XENYf|VDnIxGW zCcosO6*UDX*sLIw*cR5ywJ!wJTxxV9K{vIOw{z8u3ZB7g=5JFFh0I=kTI$wCbepfB z8J7?4Fovcy%N1wdkw>=Gmg-lC$l^dKTnsA=ns@>-mmD;c9Mq&_%HF`6(#MGhlkq3w zc;&VyDsAc%9sFjm#89ky2UvWF;hBB0L3q!hM6x(q1x&>A?_iXhg0s)mGzzZqQXOI7 z%PC@`Ff$LGn7K|4N7#}e)T&>&o+|T#Nw(Er4Y6#2XKK-Ww2XW#(M~7PxFM(&Q7>~p zl+tLWrTL-2!x&)&zD$Nm9bm=zT3@l$K7%bJ&vslHq)7@iqTj;tKTT2b(i}RhMY6m? zuXNqdBWAG(fq{x54s$#T5JQ-lLvoBEWV}Jn2gsoc2u3l01rNt&0EI6M3VCT-l@0QQ zDB5nrCOCvqa{&l8Y;>p~KJ=JZtF7rdm=;HZmgeI(btIa}5_^N<d&+If>d%r1mBD1k zQ!UGk=C&I3;=|Y7hObhQ^7@zQWl?%$H{!F_zcN0jDqgRWC3;_(2vOdvB;!5xEjt=l zjgmEJUWxegLp|^B-l0&Pie715xS~S?S7Pg|-Ya=I3fnJlB`XXeRVsmku7>7<zNpO1 z7Z09Mgnt6vocqS!e|b_B<be+3gQo@X{oEo4?WW99-zXS5!vKz^6hX-OFAVMr5n)9G z!$lv4pU#ns*mPn_fkFjP1#IBi!X@)L8qpKklyl3O8<~a+*i#_UEyvb8CyO^5O4NWg zlzSV@B`ShZFQ(u|y;?tH8=uL%O(eZ8Ue?@-EqvDT`tQO}OovqOWmu*=;Ryh>TIE$a zG^@x!N3Qj-G$i8(+N(F&Zt-dnD>|MR`Cf@CHor$|JVSNy)Zre$1`>r{UtBfj3V8%J z2gXN}<5M||+^7Hz9_SEC(dr-juU_7(mdqPtadgXsRfqtyFyRD2>10SW_Tb~Vypdt1 zitVw2zhf~l(?c=PYB+2&br^;>T~|nv>@Xm2TEa5kmETIsDt=+y3?`0sDIc`PiQ5C< zIYD<ZlDaSW$*ov%<@e&7=Re^3NN7*=Wdwex{5uMkFg(%JYc|F*&KEZtlTmuUr3Dzf zQ&cBMwseK8<%I^5jrS^H>=daA$wE~bhOXp0cPtYr8nOdYw?|(kjXsYIYck9n)s^^A zkx}Y?8Rjx=%yCyBg(x<z@Vqc+0n?<Qk5z9sjDQ_my?tBpuA<Zu)@&KmYuO%SP$+47 zPd{#rs+}U6JB$~OM^N55=Ta6wD45s8iSJdY*C^v}0yJ|KdY*F74uP7#E$THRl}_l} za`YMBCp?8m2Ni@{B<b}O&Gm($R5m3ao0RsoH|%3cxT{S;L<YU5J|+JN#mj!QPuwfH z5;b$TA^D%L$@_0Zsd!`6`T?OAdSh819KcB|(>4{#m8p_^bYm1%hMAwY^89`IJ?>7I zK6v4k+bMJOCT8(cLXySjBa`JEgO$-4sWEuam_cyByBOSTfwtA%9JsBzY^6W>$*njE zJOJjZr}ZI=&k^lJH(PEg0_U|=+X@z+qX{-h85=Pl@kCr(RfVrwJkhr&kH63KnTwUF zrn0rYHe;t0iD{F4>dS<o{dZxhQYlVqAM50kpY>NcU307g;BThk4C>{YKPmVelOUQT z!y2397t@NP(@JYsnWr7Xs}us(9NP9B{CToP26U75hzo5J^N$ZL9*%Smr|4If+WHB{ z7yXS{S+IRjGhe_k^#nFsz-!m2ZdJKga&p<Q_6d0HHYZ;ur#Slk(73XQ8_+T`#rxf= z@iKj8<M}3Sv95P|MbM=U>Gb8Q{i|Goj5*`R4r{ZtH}B*oj6*P8InSPSaARA`t_jCG zJ(V*v{6MVU6Y6Dm&Z*L7j2|<!$<cFjzA*})`!fqpb*^?p&5nuAk6AD1Jmek|Nsy(E z*savKvAbBGsY%{mY|AeF%nn<>J717G|7>EWU~MKf!v$9A@}$`X7Hk@-I9s7CMDmnP z^aE?ufFWEYus*3ZH&&~eGvFhQxQ}+!Sjt^!9I+`P`S)ZJbjRhcidy2yMIg_Dw^f}Q z|FOB~X&cf_s$wOxqkZUsQ=+~6pw~)_c}_Uv(8qOq;Z}sSfs@sP=V3;piT1@q@e)b) zi^>cux}c;G_5O-@$uGIBGfx&dW-`*kz&0*kwvpuVM#Ka!MLigRc06vljIb-dpfUM^ zh8RA$ZVAxMp|-8pr@-;H8XH3L8#es+#LbtSX+OtMmWI^ZEf_PcHN0&jzcf&Nrj)Wc z_X5~#t5Mfn08W2EH2C~ooazELGF#l^N*$DRl~BVFe+_RReppwt01e<xQA3yyU8Yqg zL2wd+!bvutQTWnzp5pw9j>0?q6aiwlWz85&2Tdc(6)VR@F&P4*P5`!Evh2xPCRe=X zGFgBNgqkDE!A2^^<K%|OtXwgyLu5@E==r1SvJV@KoXP>imJDy6*;c~hRhP*q{5MG) zjo>@j2HR|mj1?O`S?AE+s3Jw&?TM<hkA!l49=w##kG!r*QkVOxo<Vf4-*jS0PqyQ) zDoQg_e^;U)eNkmWBL3zwRTu{M^*eZ*Oqp(Mk1p1Ic1?@ljS3Z^-^~=hQ0}{ZXD+s* zeMbAbWk<V8^!2Zp#ajx=2(l+xS;%qGb5I02$9iK)ait1x(R|3C<eA&2vHr~7+__?{ zzQDo=-3gQ~$C_KZs1awXPr2?RAACG~UV~Q7W@Xgq)rwc1+Y?uLBqR2cpJg^3F*k!~ z{?G=@b)To&h`YVqdY6P?r_T(&-d^&(TECF}ca!rqYYM4<!)Pt06ns7oR5{|rvZ^|3 z0YfE)8~jO>?wO=$m}G_lJ(7aPo5BDPVLVB-82~2&k}?RQ^oiwKC8>lzNv;4`djaU6 z;~%>CCgMHh@X2yAQ$?wO^f+83(nEfIeweM1980YehdsIw0bDWU9nqAQ(07GU_9u<# zwa1bcUA||^)Pl#pmzx9Njz#v1n`h2Dr(WBy&RofG5*@`aars(W@6rk*kLg{N3Z32h zIj%8VHsX2K4sK9lWEgua60hY<0^YW5Nh08cA2H?*6%<$Lhr0Q~l&BmtvxLQ$UWlft z*H`;R)7=9)Zw3m|JI%vvu4w@WBSyhS`s8NF&%6x0{k<jHOXQ-$D`VIUymJgvKA>7b zIG?_JzHPHR8IKQN&Ah(>htSf%TSg(aX0H*%m>r$(Hg5w9*oVswH7s)Os2Sm&F|`B` zEdcYHqiy{4t(uM0xuA`mpv05&b}AS}wGW0-NY<ki^Knc6i@~|uGt4KEFqqE06OjKs zk~aRo%__&T8Mp}&6e<8>5`c;D&$5{%%YqKr>f@pUNw-#fol@##H?&4c{*BF}Xrdk? zYXnThyaUlc#*0`aYmyRmyFan7C3bx8<MS#kOam?d2kJ5+<FQ(Tj6=>B7X&@)hNP4G zu3ZX?w5&0Ib6Daz3OA_T$=u@y;ZG9HE5(@Rq|7`WS%FKS&+2A=Nyvax>`oP0-2A#s z_-6;L|LARdw!Iq~s*?~cyoQ2S#GnwNW3yiYiNFsXeoA2(_{#=2VTr%?!q4`OKaA95 zD`paS?+6x9BC&T=gYRn0kD%^xP&P7eIY}%cWp^LZ+}}Xu)#%%`%qs4w9xu`+(K8Jw zT!Hz#nYlr?CyV|Msr+AYDu5&f0|Ibp&oG?pZZX?x?B?H~e*?9AaGjgPU&R@}Sm<KD z<P5WLC83DExZ}6;QXM><t0Fa5jXFM+qf=|61{<0BT9=<G(=cg_xW%B;XnYiR4eZKU zfm!jfk<UW%O>fTzuEn^?yjjok9(*<!zbvUbXT5TguJ;yVs!>g$fPzOO1{U7ojvl|o z*1f}!g7LoSKC%gbhM<XPtG<LgtXS*u<}!986rF91^786{1dmFn6Oaku(n}FQFdo37 zGiU@vgqE{Pg((14cZ|0~4wGA~p-yN8%Vh%;hEN{ZR+!jSwdq4bns|ixbR8qe`D2A* zy)6`e$q~v8tj^KeHcN9C$&dz<;Am+d`s8HCc!mq$vw7kgqEs9U`T$M&?>r0^Ni#ND z$%3H~kE&B>zTviE8YlcngS06m`8CBJ?zi}by=?g%BeRG?Z{jk44!kMciMLmiUBg;e z)JbN-(z(~@F@&7j{20jRMk&=8&M1UgmL3PEm2l#-3+ZNTF|ZLsi%H(vxv1Xj)*=$K zJucEG97OkDG$y6;+-^^WheqL-E<wTWJ#pmIUvzye9RGCiAP8r$#T&E-X>Td|nv()0 zmg9q_ITb6YJQPo2N=L&rBkY$;v8Z@fY|QyuU7ycEAJBv_`DR&RnFs|_TukI<m}auV ziEA3C*NPhsVzc)UZW@#56lNs%aV@LVlNClp$1JR~<;1u-RAoa!9#bG*9a?~$0dKvi zQv)L5Z!>*trPG%Y4kzV7Gk@FIGvTeBOb=deWTTMhplvTw=dFowfX#5)6;`M+b^EUA zfSv_yIJcGQA_h`q1j|vGX7^<op9y@as5((D#x4xpWsC{sH&anhMn<EclNV6(#1KR# zo-^jrC!JvL`%~dn>p7kTJ?9)h^kYm8POq2tz7<+YO3}y6wzF=$4jPl?N1%-5P}wT4 zW?g;U`L)~#S@KyiNvw>~p<fahRt)DQFdJKoT|*_Mn1jO{-BB&P(7!vzrE@~PzEBW- zZ!zOf+gx|JRHpRx?_inc8!rZloz-Ev!viAPv=mk3eIU-sya2{-E+_VI<J;u$iRGXu zfg^0D)(B}MDM$Fkr2WD19aHPU3)HQY@kXc@HmDXgon#*Q`)pP~lL_2X7Awr)kO8-M z^~6Fr2Iewg|4hsyHItPo{o41rI+kFlq!lz&kRyjOcUsFhnX0kjX-Hf^lExJ^E28#X zp$V7R)`-fC)@#vvN{SDfl&_VjTrZ_q+8FTXt8Gp&O7-!JS<p1MzNczX{dI!!!`LJM zsE=Xx_N=W<Facgkrz)mIW8P&%6k*%hQ-Y4iy{Xd5!P`I57@HX8?qYyFG&T17YTS!T zYkg<#HF*_;&+dOyO3aRl`$KaKM_(4p6H0rs%ee1uWf*3;5;%gM4zdD&B9m|RebEo1 z1*9_=>cx^<;6KPpJdliXSIT{OYm_C5GTMZhK^VQFMdy$q*yye&Oxg>NI#J~^@oW7B zuT{TDPs=i3U48XGoYVVq8B-;tFTh^QZJ-uGq$oxQH$pXW2Dxw^-OHQAZIhbI%B~R~ zZyM_HOW(Z-z3QdGnaSCME*~Jn%rVk%L52!!6CWW&Wa%)~k}3jzAmQYmI90}7@2}Kc zsS<?6^RDP*`1BV_5*WyTS;PkLw3=I+SeifYq0$HKXB0QA|LHw0>2eC^&LalY3OGh7 zgvFHlhRDYFJ0^B0I8#m;2EO}+BIJ{Uf}cGipd8|2Y5Q1oV3rwBZY}A6k2zEfgnWZn zL^kCc+v#~4i*;!~jrdeH|M95Qu^;K$$#R_4M=y~)fS<rHP7+oCKrcaf{#X5DpmTm3 zeB4T_<EtqCH>3#R(EEqA*963CZs7+Rh7J=a0a5ER_`N@t$Hwh1Syz1@zG;03u4$&j zo0oyU{4K9VACMe{As}NIZi|&*kzt%FiMZLz%0@*uxvdLTk}P|{1Mv4L;R@%oQ4;tv z*99X*;piK_1omR|#7e8sRbs09ew5{S(QnUKcMCBB(=s5M^C4PZ+wel#jp=$18)EVf z8K&<vXi7e!cL<E5<Q@GSNI@Ilkq3EbTs%n13|>ptT^KWZ1lFE&Z^JlxvC93LMN&p{ z*?RjWG&A6&XEQnlobFh?+sYEPo<@{&Vm*O=(hSfa5EH*UhqvBpvA-LRMh;8rWr=*; zkPN+2{X+lVYo*K!XNe)u8#^2##8C3T(H(4AusIe^E;};^gc@zUOhtZ|7L!=PC?IJK zZ9W{z$9^~afpml{9U^d^8FM5j$>$(U?c1Igy3M)rO1baT2L{4m^Kln!FJT_J+A=EI zDA#lbM$XsZgT&kwngB_HcCQlxYa^*Y$xqLIYtpWP*Ww}jx3^EL!#@!F7>nVod<#qa zlb4z=p6Xkr8@m1-*oqCRt2esLpfZB@?Ee!UOpxA2!JoH3mn&(xar|7!m^%ooduZ=G zqK^V`LMY-Q6h7k3g4n)whx;p{PPL&r{id_8$8K4xi1s)5FnOxlE5S102d=jRS_Y*< z{B5vC*G5FNUqC}<L3KpZ=LE@-CTJnkga<Th#8}b6MZwM&LuyZo3b^t%K;Ksi$ii!t zLQn<^(QIRxed_t>So*#)cOgNl-MdQ2KM+Vinmz{5{Lk|`zhbS*)5HVA1hn|NU_F+> zMW6@X^-&7A{%BI+P^01Hu4J8=97b)A7X8{xv;6+g?d5rk@5E9#w~S_%t$+3Q><h-5 zhqXR4T6>ZIiRo7CK6M}Q2&j7hg7$N>W1-y3?c|@<JTA`Zg$$XfF74Xlk4iV`$8Ga_ zJ3jpR+-_AlTKqgC5-YwqW5L`^iWTHt5!*O;a;^;Juv{CG{vGrT9{S<Bysh}2`uEhc z0G<rt%WF!nB${W4i^~ZpNWllta7DK&i=3^OdD}Y)Z8v9R^^;VPDgK(~pDKGtsls06 zm-;;imszeHIOy|Ygo(hJ0D_u>-m=VpKBv5hG-eIla(tu8fsjMcodH5un~#k7;UGe2 z+{Cr1KOY7;hC@O1BY#WO76sQI?^V7@LUil1d-6S+3LPNM9<lf4sbnYl8@xb2e>ePk zeVeuTlPBnxi)_VxOLy+Tx6VN>FJ4KU=FE)e1O5E4Sd#?b-qbr{HXU90Kh#j7&E2;y z+s)PojYtda|7y|wuGGxS9R64&Vx@Z6mHYs!$ug_{JM2xt+rrpd(nIg}9RHq~xYbzB zUO}vCnqJoXOf-~DcUll;sYo^qD6zZu-|O9t+|%$3*9-|&qxHepCWrJ-_LHv+I#(RO z7$5Tk4&~{OWXCkrlXrE@i>V!P69v4!DlmPS2Pwt_A1fyz)mdeV5U9s8(UVbgJC8P* z?_+1&$FlRg+?lr8GBES4v)B@1h7TvxSBfNoJNT{aiG8Y|5pd;aOMpNFm;pDZMjfCy z1rSZ?0HDnN^nsCx0%&y*&AK|uKadRYl73sv^2?B@xL(#5+?v)!UMws6J}cHF0(*zG z@i}O6Bp(%(56JXxGRCnh_ktiKfU6hW@iEJuOw(a>&KTWpK|88|P#Powsyl{?`4jS* zco;J<9F>`P_iAnN=nb!jnZl6eOtR?ZIi0wr2kuCl4DK{cxr)Wo4^In1hk&Nj1ZS-i zQx^D)JJAA{NG*84{V!(XTT3buiq@~RS+AvQV&MbN&`I6beb{$Z^YU^jdmQAx8`Kms zBlU$Cx45DVt8pHfJ9{Ip!dl&_4c8DPLZV2W$}IKVtI8u>I0#t4f5plZjJ993Di%a$ z37YKntub1Oj9xn^6jasF;WUNd_B7S%zFd(@R0o4ES0i!F*Dh<s3&Sc2s-BpHavNX) zYq*5xwV_eaL@CGUdRL<S*L0Qoo;kUGT`Vzbw(;;>-QCCPdD5%PLAQ!Ma)`NC!{$=& z1Pke}dg?xRJsq^s$z%T4xk||_Z&c(?gI7c@y#AIMmn$3x+~x)`IddxJj#jSaA-_!8 zm_Vr1MCe);Iz-cMV-og^(f+ou{hvvE_;R$rn<BY%$wyGXh7U&Rv&&j{LS%{L8vRyZ zb2;#G{j=`+qe2I?;l}FiPUI1>*7me<8+or7=e|BAojhzc#I7%sa?CPd@Ejr%{ZM2Q zyVdN`7VH`!EMn6!@>vSnJg_#bNS|-*rFC<9z>C)!$h0z@wU``HTy!41l@h*A@1{6V z(R%egNKnt1?wXRpLlrmM^hsirpf$xLKpi@xGOx4wM$v_5c@%>9OHBNPx1jKC{71fi zGx@7c?&q8LzuqdpzL@5%xz`6~J1<g9HGZMiIBty1#k7W(nlxj~dfmq~?iXg@ZdSht zHJVP+aFFOA(unLOOZ)idy}kV;;ZFY}GwrmA2i`W*M)`~oPr^sMo8cM!QJ=mJbHpcY z1yrmf?)hA`!BNISCJ}sIfb5{Oc8I7wqp0Jw4j|<0@9s6Fs2%DsW`z@6SJs)1aJ(8C z2iws0Rb*xBOwp{qo@4ke$5QMY+&kCfMxJl&ARZ^CY_SC?&@0Ow8!Bw?@G-?#Gdjl^ z3gg7wHq2W$j;accobo__2C`KK*+BqC)gV9mMp8mfx(1YJcJLr!3v%17K$09c5hY?{ zQ@)>;x6y#p&-kY8zi_uKT>%pZdTy9}yyTljA9{>~K)xj^Q$*EukTR^+I6*3;)K|-= zAA+tGekrW?VJupk<nNX4u)mS_XR8TZuXS*(nbog_=X=5aSMyXWprbNzWL$?UFNMd% z$AJv8uP6GpX2*mYfGn^C1qrdg`6O1H9s}Z`wC}iVy!*#*2w}fvsqgLJOp-`%n+9W< zDdexB_T;kbGZIc*#K9Wx-IEM`zRDma-3LN%7iJN>I%-C^zml@%@HbOH9E-+W9PE+0 z55H~UFT2$;X-k~F30KlaMgg!W{H)?YBmb;6F|{8S)%$i;ShJ=s(`kU_U@YQsgVFdT zv2<HIhcq0G=g4{cI_XOb&&~ukK$g*OQZ8UhS1b-Zad&h;8AGZeQTv~z6*;86N51sd zl9>iMfwTaEBh0v+pCc=v+VHUxc&6C8<88a|R<|e92XDKI5=f-6HZzFP_gH9zW#Bb& z%;>f~cop6dmZ78SGVpprME@oiUI{K0=(IBUUB{E2rXlG!%=O}HPCe@eBWv>-rRAF2 z+xXVHgi8O$Eb{W@MF-ZnYKQBZ+uM<KCb*6t4W@Bf8`|)6w@^*syOO~(<(etP?jCEC zP0sawY|w#*P+WBF<S3+Ca<f{T1WF}ZrDc)b#}c#@W56Bs)TDH46YN=>laZp?P>W*+ zS)lKUMHh$B;pO-jD-3bq$A^{~COFbLm$ZN(Io>pJc*RePTAagtpY4XV?n)LRS~LEI z^2*Cl`;GBcBB&R1x!1u-QxDFfI|$Luvkod2OCxK4eI5snmA*IA5UMmF(n^E{hV-Fx zKpZ)4!4E9Oa{+FMC48GP^Y$2oOoAU#AUAnJ*at+K`O0s7`S5@=^n)UwOyXkb=K}hI z9hUQI7M_a-v0n{2kltbU+vmvViMv1D5e%so!XM7Z-Fd)vb3$aafKy=kb#F$<rXqv{ zCUx+8HI%N<U8sxt7}u$kMC80a3x4>nJwAB{g!iTH9(&opU5|6H*l(iD6V_kD;a@I% zVwNDd+%2;JMNX%2_*kXyMUw^ses79Ie1ZHewAJ`RrK3#lsD6P2YCdet3W@j<&GrR< z<UngnO3a`KhlN}`4W0Dfzes;5^T;CKW9pSs92Z?^BpkozO|CzaAnF1A+!7G~R#}>R z*bxScV#hTLj;~fV#gA?WT6m<(euBs~)k?i%;@J-<`?GU8_;~^+*Wk8kiJstd)oxG_ z@8n(Y{CJO4Uj8Q&_5PO3*HAe<fLXvSz9w%E*JB%I;RZ#LjpF(_S`Xll4|I_IpM&*r zy`fq|2a-Ylm|<U9q9aK<Xqd<?Bl|SmDDk>XSGe)p@a$!CD-z)Yj-)9rFQy#xf`J4s z_|896b|#5eL#%M}U{DK#ir0OVPTBv2ZWOCh#SLY3CYPU9`ATdw7z_H*nF{{E+k<}@ z=ElzZS;cMzQX=-36Wbe(!YT54#<JE7hy_)+=a0kF%fNRc6i-tifl~$|xd9&ECz@tn zhF(9jd>S?_!;$!-Xs2G^VG1m#HI_o!-I`(EHh~uW(EB<jnJBI2(+_8OS3M}%RlQ?e z5$XGHeZMa9TwP?vV2vl-NYYFsT+L%w?sJIKd1RVDqcq4aCH<*8dE+ud_4_LS=&_Dx zKR=M8QBF(|_KXj>Q}jVj=NTYZuOPEgV6!)ANL_6Tr%O|G06EJWJR2>QjR#{=`?zpm zr9W{ZlKRQ13i<{8Xa=z1msGKu|G25R{-}#dK|PTq`V&O|5$VEB5)Hw*V8g`&QLsKe z421LD)d}U)enx7)Q7}!e5XG_W`RhqrGt9uth)lO;`DkhIP5jE89fp8%U~<<<$|I!T ztCQ4UPuM-70(*V@)-n9gb_7^^c@g-D+qHi@rYoA`&5p(+%pmCx=y`AGr0<^4d)1EI zI6=CPToquB$TmU;>!iEJpa#rbRV|VxPpngK6;|B3?`IlQf2&Ad%9A_`m@B81nH~kd zAv!wU-0<vY-TO_`fq8iNJHuhz{Sq8<J-^tmmL0gw^$sGC!S?WL=S0R$n;N^wZ=xzn zpwjHlqN1Yeus@GtRl|mE)?}+vn|Yp}IYrb)nA6CBPzu0m)gM=|MT6a7?I%cMSWA7Y z*mdjYCiX$KG<TZm)nr`1HD6H6?eFvq{zY8qeAljWax=lAL`&z%z0oJk^3~y+Sx!Y) z3{G3_oVLeyxu)Ol$X0U~Imd->gV5&`a{$$WS#;?8@AvaI)JD1*iAGyFjMU#*q1IoW z-PQBVb*YO6*J)$k*ZJrUSf-aoxvx0?^p#fBz!V?q+*4hA>TDGCx=TeMZpsu1fFTON zW54`gP0ZfJqO*^QchEw;^Y>)uyUsqny1Vf9?)Vqll=o+gU+#YXe)c(E?M*mpi6(lP zp1O>p`Xx?0<&0jHpsvbCe?fgOZSDACL|wCrUcVZ>7~quaO5F&H{(6V{^&t{>S!^>q z`dbn8TLqQEacApk^!G06_p4NkMuqLE=>Plr@4bZR5UJ;i9xx7gy&Ano|8EaP9Luh; zLT7@MqxR*Ahid;0=}-NY20JktM_2#-yhc2(=rsJAb2i$297{Y&`F9euUmB&Tm`(gs z|L@P!o;^ck(%Y$~_J4n;h-aVvxl_p;RyDi?*q^i0fB$G8Vlgyu4uzXYcS1Zpw^H~C z(nC8bzsU}S$mh&}GBO>kf&mGTeT=;@U?hUeC$%v1=bL9hX^BBfZg7&Jwz*w{XZas? zfBTke!+DB#I078o{60R5IOPa*>I_SC^eW5^ba{E__wmnD&S1B`SU9Ir6j#V<$+;cH z;xAXI=Ww=|-Loj}Fz>M<l`Fczxn|cVDh%?K?((!v3CmuS)|Yw?{|+ErnEjEYw%GZu zZ#*45l>dTPUY&oeFKOHwwwZl%9#C<g)V`R@SYSs-Ra+LvegD+?-!CfP-*;=0`CVfJ zj}X~(rVVjS_r_I>HoLf;rqB4Vm>b!_*M9vI=mnsXKVs^A{8A80k3GZyTHe#9q_5>& z=gLkg$t1)&wwz1?!%oKQ>2-KB2UtyteP85`7^T3sIiiRx0Qh+CVt4Ka&1jZ->#4pf z@I#G7Kl%2+_p(3sTNj6fa-Fh<MdS_719&G!)&Q<Xr{NgBSM@BU3#Z_CS)h11lOQ^# zP(!MhOsX-=<5EVwQ(iBgBH*eNQkXfLS|<Uio-dO|-MseW>gl)tW||8BUN$Q)u&={T z=nFr{nIz7ZI%PJf^Ezh$5FWSk7zl*4Z@Nnbp#D?2pSL&14Pz8Ss|wKw&pxE{OZHi( z2=?vCr;^+enlw)0FgDRiC*;Hr)1Tk7Ia&5<-XQ+tlgX}!>^&_Le=P1cANcZ&!>Qu9 zv>zS{x>1AAGi0wHt4G`Tj0d#m>|Jzo$l@rIAdU!gDkr%8lwJ5&8ig+pe?-r<636b+ zQ9<-_9x{D;8-ga$aZW~7f&CS8U3wT?zB$FSb|mY^J9^D^8E-SXjZxTwIoAukN^W^4 zUf9Z&#JjW>V7@9u2RZa;w-}M!b-I0x6HKcMJNb(WD5QEN@B3SIjU`7*!sF8!4Kj9E zB3C(`V~L$cAO2f@S>~=UZoWS0YO6mr37<K;^L(dU&7g=o`KIK9Z>Dma!yjD4zQyOg zR#Sw6xZHdbkDHnIhlC&gRey=uaBS$aTjd_=6`p#r7DqM7J9r0n0RN;zqzxt2r%Ll3 z&w1%deQ%uRtDo-)DPN8GZ189}>GK^r31WYT*wl;Q?6<`)yZBqY`2TEH*^P$A2Q$^* z%qy80{{HoRye|1(kmf<a(4*^*ooU{=K0G`AU3WK#=FQ|~VE4xDLg5Fr%;>-AP|?n) zU!ejaL(>q^;6M`GdKuhf`7+LFSE93P(ey=iPyNyRoBysE9B8*+rj16%Vc1q4^HPw+ zZpKP`M*O*{KLcoSUqgrsox@&ANy60B06}g7kJ(;3>uDh*O05=5gOqv2Q74UEy$ZwK zF9m4EGeE{Z3p$VS1Kj*>Ad`Y}os(t=l+7&yg?TtRdMU$Lp$tUl<_^wl)=9Qs0U<V# zH20CZv3oIa1{}c1x%Zfb%90U7WLtABKKFp((4gC3JUz-yU+Y~B`dnLvZF*9dWWHiA z;|MUx%C%&K?2=VJx|+)M0e4;w0S`U(kDs$WvwETp3|}P)vhTf$RlxYl_-0%PO48Rp z*uIv*3q$)PiN)NU$V^ti3*IdRY!H<JG`0N_4hL#+_T_~qPvSNngO!M}p5=+fgk|)w zgK1camH5B;DZ{_Y8K^qyp$^^hx@K>yDFDM4aQ$YG<jm%?kn{QPLmUeos$Bc_k3+-v zton8S21xT@lrGKCSHdcLeN3yLuzM7*5p6J%^5aH%rTx4f;|KE?{ooLq7D8RIqM`&W zM{`H}tMLs-tD-GWkMG1BF|pv+RTA7*n9`w2^*1V+R<sDwl~y;Zf7X=x%g3cuBZ~PB zoP?<IEdjS^OV>ZQLPc7k*}V+7nu2rFdEzQ<5#M^mg=QoirqJ}PFtj~F&?pNW_?-cm z51hB_p|Uq~#C$D@{3AP`lPgSXPeQpvrYod|tjauU0cDj;;@M4Pj-+g@zOF;|JuhPr zlm1%D<7xR?EQDGD-eaR-6BV&64t>hyoCM-Re}ux93-`pVT!>Z~X^*u5I`|`Xt$Fd( zvB(xJK0hsvO1?oxG>9ILch<^-Kd#H8e7KBv>-^-r8{LlRz60p8ECVZrm)c*3vVg5S z=^oDyVIC4qfb+;3*?7kR1pPceR4Xa_U3r|XoeJ<3*mnVZ0x-0~Lm|6uEfT!-70q6h ztBe`%|AdZIHbiBwLXbLAe`Xx%Ru*YS)jmK9>~1nIODODQ!}Y{SP1#Q4&M3?JeOT#( z!aW{<Ex89!&@?JNkpx0dodpHBhu8kjy=u6QCZ;atqoefM|8cRp<@x_YYcSr>w*Qz_ zg8TW9YFuTIHY1#on4sMENRbj#=>Pg!<A;ZcmIMEnU#%b#l@V(#Pr%}88B5jSn12X9 z0+Y?<QY!a2y-HPtn75wgkP^x^Qc^53>Z_0|&s3ppsr{$FHV0AFX0UIe7VuR?PzOs{ zBe4~hLs>ABT@s=w)-rc@7uHFkwEMur7dIF@k_v=KW%ROb7yjAw#BZAG>{~n}AiJ`j zim$ms)Q2`FA?xI*XG2gG;nyN2$#{P?ms8=HJ1q@2!X92&Y&k8cLLIayJaEJ$$9;F= z{16a>zCFki;`cCs_1##)T90C8q~?HX5Ye)kwHDfkdx4tt5*WFqNpt0!*vllOr(Ufg zm^yTc@>|Rw$jTJHfh9?Cez*~f3-uHc80s;G13a8-tH6-&^BXQ<MS}jrm+n{$GOsEI z_NC0iRH_Cpl)ocpSCZXb3@oI(vO>Qr#lCbwb}<u7T%xx>?s(@AxEjz+9F-rFh(DHT zX>PKI2nbEjXi#F(9%K|Wd48cOln1(_!@8FEcH2j8{pDc$71J!&fw<N5GN583kzrQU z?f4=-C2P1>PjO3Tx2wm+^KIF|U$n`4-0YW+8CR}EZ%c3=X@;tr{U<-rd-3AX0;qZW zrmN2St^Bj?8%vchU4MxC_Eb2bR@;fW=C?5JbT73#zGYWlq)rnI+N8pE+8&8|&W31E zhZdeT1~(J_>0H+vdiXSb{@#T^O}v!;(e5yE{qucv(}!-&{-odYJp$DI_VMQt)U&wJ z#WYbT{V<6v-{nKQr#V0V#r6Bu-D3;gdCBl@)P5`RfT3gcySURXdMHTvB<%}7as0~= z)0#c_?C-WXZSc;sKn#Oq{hT4y6bZGGxg6LueA^FWjsX5j7jKz<axzc7c`xw~{S4PV z9N7R9DrEz^hwk{6cw1<N3A>HYK;z88g<}o4pa7-46^{O2)iN042229N04Kg_Jx<?) zWUz{*a;-j9N-<|$eaX9nPN*Z&$jbm%uuZ)2iqZF&8X=c9gRR!a>o^EjTjtFFsOI^9 zk<7&RXWC>V{T+bu9^1xi+9~5d4A^PJei29IA6&-Pvt2k%Kw_miyvo!>7x|PGTv76V z%9ik}AIWZI!7i%RAU%OD^*r(277t8gap(s(?pla@cz6e5Z`RjEPY?}##?bvtTq*m1 zOv$-0v%Yip2UTigVKZlj8N*TegKP9H4|e-`(ERpA%<Z+WF2M&7=3^f0^vE_l)SrFI zf^T+0#(pmbJC5O4n<?1e8-0vDW)zB=;7YUL>I)S3$6`bPtKVM+ag}Bw-D-Ty`;a>r z%0#rU#S#B%j#DNZ5ogZGxO&Ld??-vOhuuZHjqgG{YIK=d-)_=PWb#q1EQRglq!(B) z3=;g;Sy0>qAm2%mAXd?<My$UBJC~8@e=P!VG8gelUF1O;2T)zJFQjgX=91(<^>glA z|AA~lvm#G5CJyCT<~uUS#cMHmR<;YVygQkqAQGDcs}ym{QmV>>A;e6_Ba4QG3<g>L z<n0Fu9teWVGLN&)8~uwG(ja8-MLKzqa#jH>Tjm}@mM&XJjLht5^eB(DyHxrbKjH8` z3#MQn%LuO6dV&qfz{pvm6p?@HYBAFCLIyF6Z!GWdkc~`3q^?;hT}R=Z4$x?Q%-X~% zCF`;{5j=rAhz=hY@i19Fw!pAkG`zFqSPK5t`~=f)@K?W&Dt3W&jIG~~CmXH%RpJ#3 zqh_q49f3y>E_@^V^4qD)0sTshV39&25$08CqMRx>7z;vcSd`y^?1>~a{N(Bd6_5~h zB*g8wJ*4!JHKVkhM+)x&=EVl=%Ar0#`LvXn5j?`=#s!ufl$GYjPWPi`Lw7G<Vbj)X z6?AN&+V=B)sZ(cMJ#QXBOr<(3%R0=xI@iK=o!OMR37I)hMbd-li0?%jS~PigR@1Y^ zbVjrU$p4tY6E`#2`oC!p?_S`>UJz!Jz$xJ9!HS$7ii+W=#YssWHse>;#sP22N1hNh z=m?jX$$hOYLKGRg>?RS)lu-0w!{0!C;VJyI)qlOzeU^$;Rsrnv<?O%DWEAS<F^{te z>=|s*t!j5dF-oo4J>kZpxt4<p>VsiqF04r+i-K8yW8ApV57h6xbddpZK<Q9ADO@hd zN`jlrT@|WXlZ8$|JT7G;T%A7E4<kyLOc6R!n9uc$P_X4&OFfBc`+JH~2008}!8}$+ zV3t-9iiJg{sq&W`Ix|9M9MUkyg2ka0m8)PN%HqvS$P~)#gXJ<avSW}o2zEsyb`K+g zT*;TM_L<WzyAkXcbJ4+JDt4<g8`6rJt2y`gME;t514ttM>28eWdOjI=B1=EdKPe9s z)<(G%ee_*iVhR&?&#>jGAaerdbDPDbdq&g<_Jd+3S1VhuDGS#{gXlSVEoQ8Z=TE^% ze|fDo#~avXL$IMo5c-9#&0#CLV4nkC{&qoMl+QzB;=L^&on8BcXIGZp?;K%Elzk5h zkUTC(5BKVt@v~@_y1FMtbf0l;%8)Q3gVhg(wA=IyehNWyFf!sk7joEgo^19{qhD-j zpS75A8bhj%ZZHzYStHag$U^vRFbU`VKwij&{A0&RKlzA%#ck&&jjw>&s#6U#3H$TM zS2g?n0+qs?>CC=G)_llA<Gv+!tcAe|4dW4ikF7D<Q>tCow;;qCJ4Q|u94E#yO%O^p z+L{hY%)gmw?C>%?2<~xCk&U>QP8D3((yh%^Nj!8k!cGU~aea-nd(enE+E0wi^iCAl zC{mJ83%paGW5}LsLCpPcBG6?p?@h8@^w(dL8n1EC)oar2fuHQq8|k!k<vzmwgH$$b zLoXmm)(gN+hZFO{gD!EJ+4|7;^Dq~%C8XxFeKTBt7r1^9G?iOX^WplHNM@}WyV(pP zJt1V@`sTO%_^Wfp9gqmYS#4%EKsC4~>pvE?crvEH(Uyw@1=<zL!)j;sb`I|{|B4Zl zC-eDkjW!*SerR&`Ukym=D_1xH=P##E#7N}$u9zCVd`k4}lefG(7youHRdaJSxZqL2 zPjucdUTz`9stS;j9fnq!4Mm;(7-=tfdVD9;R!BoPpiS6@*OmoJ2y@F1+JC0vK!6SY zhoSvxJH|=AHmCpSS-R29G1CHc)U4v0!_+I>IXau~=S?vO`3Y*{=_VnO@6822hsAwY zo~A{UesK{^xjQIkSorTW(;z`aZb6_y3|EZ2Z*|JOMDxhBJd%85X3b&j#p>894o^;k zCyPf-psoGA4mM%Moc6*ZItsUXWSa1$ONuJRA+vFJvIUou-rqLsbVFei<{X1Q3h8n_ zFnW>@kbjHbLFih9v(9dghC3$8;_qX$O)yv11KTX(Vf;fQd30F2@2e;Nuay1N3WXOs zi!Sn1i0NfQmc4(sIb7qwQ1L6d8*kegB;AAwoz0$uCvI;z64OsR^G=nk|J{837s9q( zenlx>E6ik;LkRFRe8X?v&*9O*=H^@DHiGL&7A(AzkF%jgE4F3FMYN+=+3#J=wwHIT zZ+{+6v`^FFa|6Lhr88Dm!`ub#YXf<tHW#5dF^~G~=6FQuV=Rv#u!8t;-&?2u@vf@< zmHu9Y8@!<xkw>a8dF>LF_Xt{E#pnhfsse56_>lvWawGr_H+XR`$dad+&-&V1P8z*z zO;ZLj7To>k%Cwm02`#pMsFw21`8L<CKzkx{(a)e_O;wE3EwkzftQ=-K+5$LmlugL8 zh7imm<yyiz>Y9zIPdKs24OK2aaule&kmi0f*NhO#<L>)H&viv#ho2*E7hb%&<9!q+ zT=TBt(_90zf2AQV>tcW7%s0SWMb3UlN7oeH;rltgh)ohxb@#bz^9TmffD>3PRVQBE zes^iL;ZyO&!aDe>ukh`*vbfa2qJD{D%czkouL2FT-<Xrqo_lM=OCHRV=T^{mxs%@B zx?$USub`iISf;jsaS<Cdm@VP^GkgU6-Yt=$=a|o3#_-i(R*(CcTtGu1o8<{#&!_(U z;^ByO1i#yJNGZTZLKI&Tdh7<W)cHRwuTdR~<RJkf5}@F}as@u1s93<%_@0`_z~LV7 z?y=PcERvUs&$L$<xYdu~T?W8-fUO?U@M4(8d3=h64Txa|&ICgTNGxaC?<(G#BQkSm z#$9iZODs-abdKEccb9!IrM5VwLurrxJ*D^HgOPJ&|Kpb?&eL`erf+NzrFYw>uQ|_L zU%c91`}PLkY?$-xx~KPli?io|d@1ej_s<Jr7w7KreT=UFA(od0M#{7K<|~}%Wd)tJ z@Ag!L%s+Mh)c#T>G^j-3QEP|u!kY&Rr-V*e>8E$w;>Ir)J}oXTJrM8S(Lt2Lk9#HF zeF3=)cdtBHI$d0<AdDQ#0>qiWOZ1<YnY%@RvbJq8V2F1`fPYo+v*2ctnW^I{XF0RC z8?6tCmWp=Aj=O!izDz4!vev%HT7Vuzy@hkVT!UiiEP)MoH>|ch)J+3gUb-F@J^veh zlOYQv{b@CVioV>pVTEQC0W&3+uypGnqI&6W_kMfOO;<`~=2~SXmbh$HxNJFmmU_&; zb=Qq4&Sm>ew9I7briwc@uy?}?aI!DmT+)CplQ8_CA4}aRrdKS<)Xm|N-BXQ=p1m6( zZdmEE&5vkB9t_hmn&~e|Y@z#yyUPzw@(%%ljor^OA_5z~KJQ+7csNaFNp@k<_`G4$ zi?Xbs^Y5nRafMnE@leNqJA$ql{=T1Ai9b`ij~E4a16&T(9{#!`AX(D8;o!z50;ctM zq0+g;()pLrR+9GusEi{0jPLk&e}4W|zx3xJfsOayhG;)?atTw$(uSUfIJRulT>x9Y zv?0|a6ME&aY3Xcf377SGgU=lsg+B2U{Ozvsv!eVrM&M5Xj{sU9&a2;C+7}B$i8~E7 zm%SpVTUQp;Y?S2(gTYe5W_g!Hs!KCj&RJvEqs4dTw0zR47%sw1K%&=*YKu!(!xa?M zX7cw-XgP?^Vm3ZSsX^5QU$MG-JOT<nCwQ$l*h*!e@P(U`8_c-)lI0hf3sg8pRJmZ~ zrud2eL6HiLdhNFmtv7|r<w&x}!2O8vBss^ofvuC7Me?e&Jt1)|KL+Z!7TwO-oQFlq zWuHzuGQThse}Mhtx|o`g{#65V(I7#qDCfeU6+b;O>S#@ud9ApMDHSDr>B5!q3##NW z5j`fcV1B8E5(l~4F{zTj$n^61Wk|srl6o}E7B5(qoRGS>l{hwApOttn@0yha-pI`| zf)A{!-<xY<+1e<qS!UW=!L2<*)TFV1jF1HWGZ(b#^g;4jMO-qcu=b%d*z`<<X@Y2f zV!jZwBsBCb1)7EnUb!&;*0s^?hwESs9p2$Gcytg@8bR1MbPfYt$AJ0)9|~Ki5mPaS zzVZ%f;DTyz$(FAsU(;p(nx*RRkRfV}Fh~|v9vT7@qCfNs(ce)1y;7ND>-(*$z`O2S zb#dg@w>TNtpq6fi@z2+Wr3J&4<}SjJHzmaS)r?$CWrWURx;h8jsy5+uM<v3OqjIgz z*pO$Ed%*NaKr7SOt3t=QT1FzD(1<r=8yE@6s1qwq%1A;j;>URdH`>bCN*d6DS>TXC zaY6UTbK(U5nl5qrQf}?dtOQ-L)pFYDPLCI=QNDY9Fwus+euhiid#{jhkMz>HF+{Zq z#A;Psz!TIrd!%5`2u`|@O<<tHTm#YShmdJC*k&*Ym8@tHsHI}Ay%1}V*&*0!oSL_i z?}txo_lnTJ!qJ9&-_f*4m&|x8wzj;hebL`vRP%>v4lSedSKlY8vT@?&h|JBaI5CMP zn2hGVI5-WH(tw}aK=^FHuf>~R8;QR@NBs)OVkW#SouCh#dA5p5qhON-FB=b%E6ay^ zJp@W9V0eL5r{)uLepL8@wpfLULfT^Yo1qKKh;@0<z}C;I9SYB-yEcSxv5N3SXFNH1 zh+<zbe_D4<#pXPz-awVX_h@D4g4L4EIMelWsl$CRoL5>fEm)0(Cw&~`$3(O@tCFVo zmjNg7+L|5ZXqI-MJuZyLU<a+2B|JkAvKiRpLD`y)V|*G_@P3;1ej*oTC<ta;3g#T@ zrB&UFL2f5m#E}zH8T_zB`=p*?y^P;1JGNKuj}$4>)U!hxZBd}IuP-<VEb1$o6?-=4 zfTj!}@~v=i0pbD!t8kwpvGTetx2a)yE|^bQ>~6OpY&XvvsTc3(^a?f9U2;;j$tdK9 zD$^XNx;3S9ufeV09GY`7?Ce{H#^{v$0@cvucbVj1RN>V~LykVx`Tg{pqZRzWhTa$# z`eCh~Qy3X@v&5L7nC9nJn%-zO4p0A7D+dlS^8)ZC#2Q%)<~&a<P)3@LHznA5!UdlR z8pN!b8(j&{+cPiBDl-|#{6l6RMf5lR#SA1RI#J(S6b$JnJ6YhK`P&tM4KfsJ9-&Xa zg9yi$2yvAGP|0x)Erwg-vC8F&x!)?3+K0yiZyy#dGknzx?(9yPOSh3It9(zJMa$c3 zk_q|d0cFM_?8k^<=p2O#{80Q8c|?39t%0))%c=z7b6i%L77Q6HpX+a#;-hvMwricy zYJOmjGZl>gxom)N^)g471KuZbSp(#_)?kRr4a9>a3uGhCl~Ih9X~1CW{`^t3@>s3u zj&0qt`#`Q($AF<JTtD?F94o_!GoU9JoR2%R?-wJwh(5R2{KN(lXxiW$S4QM*<g9UO zC>}ogtp8DTo>5J7T@;>#1d`B_(0dYEsM170#3Y1Xq)QWNB3(pOq?ix^>4sia2uK&H z(lH>?yNHU2G!YdM5D^u5KfZtSYu2n;bLXCO?%vPVla*7#R*mA%+F}ON5SOZP{~jG# zWzdi;HdirzieHEcf6m@18)xNDFS7Cl?iy|F)hAfgdJ2rb8QAx}q)_~pWOM#(cG-A6 zr&9nT!3oLijjy^yPVlLa*D0AA^LMaF;MD$%HXfs3Ic>seTp^e@i3!$N=HGF7S(0uB z*{qUHwcO9oZ<^L+2%VLL&dz^%%bQ^Rh~<UnNoo0V+My~`Z>a7@OCjDtTq?-YAmL}q z+MQFt>xK=BClRkl7x(4)9mbo7Byq!N6||D%>X|3R+I9V?_<fAk&rf7a7bUA*giKL5 z={3cn-#$)p4>yen*opN;E_3CzJ^VN44sUd&Y2;p*df}Wtr;W6quEY?sove;{GBp2b zmbIG|#0b;Z7lq#)3}{U>q+#QS-|6+=k#h&7+IxN|x&-l`F@;gi?q9rv(XJ+0hsN-& zD9n|6bIRY?`rZ|RD&D^#MaZrvC>DX61}NEn<Wb+dY%4XN9^~^nN;MG77hdy@)&?qe zpD<hmYNW;d2B}=l#cUQEq?$`D!Y1BkGj~5!wdG;VWQ_GtGhUzypb6X{Z1BW+AuGx< z+S>Sz$P$6ASW^qj9q+*FVzNx5za10OgKcJX&OLp43xgFOii+-dY{)O=929=1p7LQS z-h;jK4VUND>*{I<ojod4t8_Y-)8d=I%isAo6HoOgKAWXr@|*Du`Bvgb<Mb|nA#9hK zvfS8xI~wvNw9G<eJgLYz*8P?Ag(y&4!-iMv+P>+<`w4kQXph(~;pYct3GV4;$giru z9=F|A=a-B?x`x^`<vkr5X)Hil4pEljA-o8q7K`1C!oxNE`4d)R{;0+A4Cy?`sXD$- zQu-tLye*HGjb;0KY34C;@`WSxVVz5_dbFiG-TcO4L;We&oL()SG3mW?n$Iy3jx`wZ z6;1Q}dYfjqVmtkt*mIs<+Se(m(6nnfV<mOH;_zF@z0QSC;=OK$N|N{SHj|V@_3Wqe z4UeEPuPV7bZzP#rm6w!Ac(3mFxkUdD72#J$wB6lW%xM3>X7Y2=S?S23UbyQE6cn0~ z`@jG{kdEouwXS<7E$d~iwqsCGXE>vmG5a%nt8KD->*nNN3y+2@&R(_Y@}LY{70^_K zw=qD>yiXi*jcivi7Etw}e|<pdjN`d_NU-XpH=`~}twLL6Ne^h{mly3iEkL6d;O0s0 zT+H<DX*ok{m-r_}_zP_B2?Wr7mEto@RVFy{?ln(O#cN1G4Z8L1SAK|P)>9!Ynsk-{ znpyDcNdE8`!MqsZaDI_%o<i0xcRr#0)LBkHhbOZI=RsIXBqR9R!nG+Fd?50~j!YPg zc!gcnO>;XM<8kBEHYQi)WZq?D!6)RmLI2g9%L0bTyfSd30Q|_d)ZyTh2l5p1-|L%i zmrv-}M%(tXSc2hLfs5=~DA5Y!ZTC2&wNzqjjDK5v;G6j11awk7$^y#6s6R^_VDaA; z@BllqfxP64kFQy+DON7(xNF`TeDYKlYdT9LPTwjg8rB=l#V;f8F8=lvi{AliieJli zn>7M2Y4HjE_9sMd8`5}^@03c?{3YaVLeitW3vF3o-KC_rKPlK9m#y4bh{xUceHhnF zuyV1CD1Thw`t^<<J|+Su1#DS#2njr@P+=LF00LVIl~o%_k%7Nrdp@9~>>k)}7!_^E za(Rl4&V<=a8NB`#|D`Q$^G({87MlS>LeS%6>ma(I<w*V-LwK!K{+BnhOG`&ig~jJr z!X^GhgIuIHtESA=do1dz<d<Rpm3vxxULIypB~VIV2Q7=wBUf9bu1>l78>WD#U8~Q> z$t|&}l;efiC~)?tIKTioudk?f3K>0>F}Rkdm7l58o*9-KEM$G$<nyE~r6}xPhGUcZ zZ6w(m6V-4mx!YIN1uwByU1m?u2n|JlzLUVE#y4$*^pQ=+=UlpZJ-MhN{rhXDnhaip z9M=HNjDaDFXWKQ|&v4KXZmm4vdOJ>GI|JgOKdhEX38bZ&WhCl4<;CC1OYrkrxRH@6 z!&~$d&7iXW2V-e8ihriXr;LPV@CoZ8WfYLmdq=AD97A`zVRh>e78Rt7KN~uwK3ty8 z(gn(WdI^b=Q|FP(k+ZVIqI}vN=`yQ&iWw&i_%kZbr~EOBvy;p%;K`5HWcl}os)jtF zNM)tGT+db0w(tXr5)L3Y^Ya$ps(_FW03<-gpb<!5RR}QOzQ6hQ0R$VY&bTvsGDic8 zxQAp5U4jV>sz(ECe{P|2c-XGewRAv;LTz-iK3f{*VZjRgHo&$P&O={fOA9H6f#7q! zFb*B`gC$rfz?L#~e@mP35DdupGh!(24`dO58G)f3k=OFbygTOh3FlJHh*E_H20&+E zO8|v=hL&(yaDu@FKNP=VG^wEM$h4!3v!wLn+tRZmWj6DXq1#DTDv{+wg0>xxT;<Dj zMoJMNL?lp-ST2?AcyOVh+`pqdaK1d`QyIH8bOR2+>2P+Bav4Nfa7RTHWxnF}pNiC< zj}Rc3&IoW*_z|_BGO437WxkSIsuI2f=pcZ*5#?zSRe1$f1szp|;3`;5g{)~gE2uhR zq^dlky0W0U+L=E@xGK}R>Q+Z}qfSk;bIsEN^n(awOmQg}P@@=8!xXOV)2V%4P{ZZ{ z1-mmi>K}rM)%|~Jr-UhwXF4h$cOYY!wJe}&U!BJb^N$z*JU-=LD^~J&$+>PlqHbe8 z?bRRDL_yuwpSo?~Cs#U-7z~}d1o<Zif3StcY}xcD{sr*!^=xmxJb_8oiB8u+3hVi2 zph8rT;1sB^xZZpoBC7*L5qNUwfN&vThiTw%tP>~JiJxu^jiIn{eXSP?fk=szb#^dV z2s~^d43K+;f(Vwi69sc=(n;pO5YmY6Y|^lXBI*Hh09@u1B-6iH*aIGE1+`#8ET$lq zR#1&jq**<~0%*Q=wMjU=smu!cf6l4ZF;NxxIfBYRM!8x6?~bh;#Q>`c00{xu2~d^* zlmqf9g|)cl<rk=4AxM<js*0_WjcAa*49$#aWwnN?p01MdZ$mV&DRi{b*aa{FNY45O z1knEQDB=l~3Z$_E?8VKTy==#z(F&JpdwQ+R9{}b7O%>_jE^aGh0+q=f_Js|y@<16K zE}Yx}uV>?K0GNe9kxTpSKXBoxdakcf%83T}EoApCB;qtH%r2x`Y*fXb+CBIV75lgC z!y4pG<Wofu0$R_APeQRHJ7oWqAv}&h$?l;-epdzLr$~nVQVqcwx*5RW|B5_c&w!~Q zKZw*o)8Sv=J(F<;>^qUak{MtStTuqrWrkp>XLQdabBaqjb)Q9dz>NvVY9~6IN(r0Z zY53_IEi%FYr#>KC(1WpNZgpA|Q(H9B;hgROZ0adD5sKgdcFmBWC<fb7?@{p8cIXZh zaEJDEJfNyn{1XBCMv+k}?O<%Xj&pSx62^1*oGqkv+of&4ru2kMr^5nLFN%>B(7)y1 zC!5@-v)`>arlMS1i=$XGiM2*2qZm#B{HB}0>kf)o6tXyyVLmnx5YrDS>HqCgezpL9 zodaN@A5WbC(?AA9Wr&qnDQgOp0f_X#Di#lTNgxBp1hhF`$bRYIKy{j#Bjmdn4-Q*& zB3ikqy$K5gdS-Ar#U`aF24~2ig3j~#=0TbH!AqbQy(tt_(dM)EqM^MGWJ%NzyyUTY z2*YgK*ly|tPz-QPH%^F-hIK$Jne80)3{X8pOmSkhY8YyLG$i8;6<HYOT7p<&kOQKV zoTvdA)A32yy5P<Fu3E1K-9dJqVU<Ia+NQ<tsL4y9i6<#2&U%LK;iR|qvohw;pRawO zrAZd-vG1Z_5Ue`MYmT_?3J^Jl6{4U|-o4-pLc;4AmI@=#<q;v#@|M8qb$M84msjZF zs7%M0s^~M0bU63%12SiXKrk-C@Y<-{@02kw>ld;*F9b^Z&pm$WTr$K`(l36d8XPqS zk2!ub<A`*)f;><p3OJ3w0AprWx&~f#F(`IcL&yBq6<2^mwO_`$-}%g=hwf~&Ahug7 zZ|;mEOE7QZ{=r$&*-Wh<q$#KeFvw;Ni*twN9C5Ph6&~YC-{u9uQtqRp>LDCd!22Cw zu{0s;0X07+vL3U;ttOjAVD|OLP~uiIcW7BMazAjA$bsno2I&`t^>$M%Lf%neR+F6; zNY4l;C=&W9iZRj6HYrx$9Lb-<gyg#b6<v^iS7gri!fbS}OaZVWRv+p9iVcJ~@BR)x z1-vywu%D@13u5x84=6;Vs7nxw@%J1|$cOt#&v^(Z707a(U~gdS7W=?@725rN2ttH* zbGAp)+ga-Y^WsG)2sTR*t51kzaD^<+iY-Z?7G#1atIr_CEZ-ZC4!%-a{F^w(_xH6= z%(UCL8X5W5Y@q7XNiWqR#{uTj5v+kts)tftv{FWA${^NmM<eZ`8OF*JH!W68o#A?s zAGwkrXDv0w6A<zBAjdk;MC9?j^rO#K(@iQm5}4Ex2Dqqe7)k?Mu4@CASb3{xhqF0S zE%*ZzG;L!sYGsMAC?4VEScVX1&bq!rdct|cIuL}F&BNzSQONVm@r<#V@Gj(G?FP38 zJXQ}#Vn?KIwUv${9jr#ku4~hr0ACbRHFcQP`a@j+yzn-Io$9B1^xVe+ji_B_^Z0zW zXz(!LtKDtN^mHw<Byi)jUe(3!Wt~4WfA3CwDx4C#`srU6(v%BORRBgWATQKzs&q3< zFKn9lf4sa^KU;%zxqZ|aM`areST_kly5HXNd9W_i`+BoxRa*7SW+8yM3jHb80bTmq z9r+}>hjCpQ`8=3WjQp$_wVl|*fJ~xtwgG<1j^IPej?jr2k#soddmA|9Dc6T*nQlm^ zZdD}xGdyMk6O2--D_uSMUb(n#kj6Z#`w`Ocg;i{;-VOP)8xpg<)0pDaUdQZIM*rSy z<2i?9)-i95eWzG%S@pj13LMhv`2k0buqZC2v47&;SvKoI)>yuTrGF!(B6(7N+E7Z@ zZ?98?kn`|{Ev{s?AGf#uIU}#1`|cZzb}gENQGwXods4)PM6PcS9&E6v4E-+p1YZ6G zZP*3~b0rFZ*wNT-V$Ys%%y-m@ImzSdLmXhG0}Dk5;oZN_TtpU}tzuL80NYtp=m7Ya zw@E#Vr0;F{DM+sm&#bQuNWX8dIE!qYSocqJnKt<FjK+;NIa?)q4q@@(*{#DbOP%`{ zJyz9HSC1x;hg`szPL&Hcy6)UJ*7Uz;>W~MVfb_Fru;M?GFd{GLZT`2WkbB6`dm#4* zpbK=iyGw7*yFpkz*gUrX15k!=R+?Z(EHO`IthM_cw+aYE%iUVwUgK^kKBuuZg-lFp z+kQ(oRm@#}&)vrcA7ReZH5GHK7rDz(g_us+J`rMv3QE@%#*ORc&-M7gU3jcb{r7>J z0h1aM`{T<b@V8bhach7;{J9Iu+$A9P*4r!GY9N>wk)-Ny+Ag=XZI#;t1j4lnf8^$3 z0ZF#XZE*i)rGx~#UdY|ggkAh~z5P$<TmtHOjvC=nle&v%a>zP-`Od}jzs`j4=?cso z(eus#50`>q2TrL#I8}bbp@T!mn8IP3aX*K8BYj9J{DzF;+n=%L58{j}PG0@B6~e0) z1KZAe{;TG6LS;=&!FjO;u+y#ZyWzR0LF1ga-CAbln+KE%UuC|#r;wCEU#oE4)@{U2 zEDR~V-Coak-Y6X0d9WG68_)KqSRmq`$M4;ctc|WyDdiXYKs%f-1QILD?_FF@e$$cs z@5J0Ky{~W6s=>ata(_z8zr+to9W`Rh_`ni_y?uY0g?ep*Hm5$7-2K~@8~OD2pPeC- z>0$Zi!Dn{el=EvXCbnnocBG*rM2nUzJI*MprKOMMRgpW}JhrEYBjPm!vXb>~erTE0 ze)=Zu6=Spg*Wn~vbX3RQwtITNEL3O)#oz14$&r84qo17qrym*R;olW0Y4Kno%{(IL ziA3~vF(SgA?*vVvA6-SymkM{_>v`_;ZRv38=Fz9SM+R(uQBRgNn|YbB8Q;_G1}y>- zRxXD!B@*f1_o235h;tF&mLdke|N9=U`|bQ7nOGNTcKTV8UCr%N9{-8TOmLm){kHMz zzudKLZk#(J3|LwP(%7I;kYbESW(IJ8<S5&f9?LL?l`9UTJ!lzNA!lnL-(}fsGh~P2 zTQYVyLogr4_t~z*h<*;vmEiZ&i$*(d=S*}o_$W?`vePlCEG`4$Eba7|d3&p~xrhZ$ zaf*8I=9^$U;Ph(GnZ)|_!9sAdTk5SajBO$On(4<X^c3lw1$QXxwh$JSov&=jYPEm0 zcPO*M;Twm#Lhl*ZZW>?BZcA^I#7mh&=M0cx_SjY1C&B-8_BZESuYKS8cluy^Wia!^ zl?P8J+Ow^zXU(fmvdA7;tdHiNqx3|MDezEm##cJl&LJ)}77!m}FVjI47y7BD_U;w$ zT)RObgy>%<m&tJ#P|fxx!oq6{Mjo6R4koQ)Wum}KF)3FQroD!{38d(hWa`QJaLF|7 zFKv?d&ipx$q!aa^C9YSn^eGlS6eP*i&KQCNxcc~yvp+$3!ZA>xO5`1BZ9nV4^AtBD zZ&x<mQ>bK#TaL&q90FpT1I=$QqRw3K{%Di~Z<l=-{pYuAaSTESUlJ!A;cIksrhgC& z#fKQ^gYf=SV0j^489?8FykZoDEt?63Up=s<!lCvV<xueoB%eI-7q0U7a2j~rTvsKK z&-HD3qm=Xdk@hmV6ddxE5X4U@n*qbSAFUAKNha1oY-)Ri$H&>{_@{6EJC$1BNBmW4 zTTWtsTgK5+J!8(^-SUuF+$HTr{O2K!%G8Moweo$W6e|ln!a-Jzs{GsiNja5}69!f? z?5Hfjapip7dXLm&;%`LA6>=Y1f!<*EHWFDOr#uTd@oWD@`6KUhFe!bj9fxXTs-wE< z<0s!mH5sGW@l~dvgGl70#DxH>3~4bZ<S;|XI}v0dvLr5t25-v~skI{Vq{E{?Br_jv z5JJk+akZY2$ltJ<mcWkXPQWjr_l!Wgwa90mg|nzH*~+yQubOg8U8!IjH>n^Y&fA?> zMjrJ>Yfhw|KGIsFq?_q!f6Nw`yD_J#8a&m(Ghu<iU!v??dL_?C-zDS&Y1ey57ga?t zkH4C=W+1RzCj;Cir8?fDP5!m(<1POQth4R7;Pjzcyg)-si86g4`mW=Yv;0Y_s$34o zgM(*hyd<oD-WvHc^CPE_qW9->%`?5f-?*K-h@X09{~Am4QKkw@S(%&!5KL*hiKVjs zt_<G&!UOq)H=Z==E1_6x_V6VZ5E~Uj*pA`C8^4Ckq2G%^EI&pVAIRWQ4e4n?66VIR zOMOU>{4#iCF_@)avze3g6GlujVK>4DfUboAd7g7b`AfV>YatOF$=QE1D*L6?8jcbz zqj0<x;Aa$C__j2iWSYEoIXe|D72`0S>9GF`tyc^SaNbLuM}$^Wqk|IIvExQ%yy@BP z!`N04k$%erx;+0~?6WT%AgV0A`|3_Si?+CVHDH7hj=dKUIkd=uNpEgYOv>q!l2NZ3 zwg|OxwN*?&rVh|sy+7WYS!NK_JWTVb4e1716t1$71FS~RTDnl+suA9S-Yv$7!xmzt zxLNbgp{25ZgbtzmeRYVWC-F^+CSu92+A}n$yvczu(ck>2<>4Ld+u2L9&*dhrW;7M8 z>t6O4i9h-7pDC!x`g}5ECH6cQ0W{`14eD>B?p}xojfflzu(mCo8WVGl`lN=Gu6-Jy z#MN#lai_bV5<`=!e?AJl=L*Bm|F*pA$e^ld1M+aWGXVJ-M(o0QP%w*@p)lEz8E8DD zJdbP$;=HffEoXVH`sMusp0pD|F#LYKb&{he_xUzieMJwbtYgeWUZI6^JkJM@&Ol5b zhb3&74hd-O?_!B!{$#ZVHd(tE?hj4J?x?zYwlcl7dxf?``=%rGcaJkGZgeZS{iuH3 z-N%6>mg4U%+Kdlw7~O$`;$m3=hr5CI9^Y7&bmxR7NhtGUu^Niz=`UW7hdyn3@K4eA zg%`ACH-<a1lEyM;aCV1-0MvCa5t|PjUNEhLIjd4#MRxhC=RYF+kKW($v#yz^1jQ*f zvJLmUFy`sV3C-q-Xyvd{h4-Juxl)tPOiDbu6xaHO|5UysI9y`MDvm19<s6;RJK>#M z=VSn6pUmPL>5OfnZGt{tuO*Ss+kV+?eRlNk1oc+LU>-S4H!{<lC65`)8hFAqcIAA` zYTsgBabxtIngFVL?K0=Jw&!0&DD|csRvz1!8TmV6v;UdWE~Zi2q;P2~F3#)ALND6} zG<zCa3F%a*c<~@21mGDkD^;lFkbw&BJh1wD3|!V!)>*%LPXO@7o<i}OxrGK_t^KHU zt$oz3=d-vlm8yaQK%5ENxi4$iPd2rW2j5mNT2=g{{qk)P_07?h`#)+wQO^8mpS*pW z!N-qm2DbMn<MlKcJdb^UeB=Q#NKF)VY}ZGW3=%}oDid$bHe(}{Cm(54>MQx1_w084 z2Q^5q(#V?w2rrFAPu6-VeRV3la*4kFUEYl0+EYLODx&OU{T-!EkATrR5z8m0$SH`P z)$&}#=a$vjI1f+T&iT0>%8j&?#~!9Sf~r$nwpQoOQGQ+`%`v|I?Nx>FmYGxUh28S2 z{wlPvh_Ank^aoG!Pi-aB-@Sk9Oa&pVs8n{>B~~p}S5CK(xF>Vx;o(|+5;O+OW@L0y zR5-Y(L%>Wi1{BT{e(hh%6}or+vy1^PE%+{wGJ2qDp};%>-4^{$3C(eS?(F@!`l8K_ zm{{JTFe<0wpHe03vwj1FwU3EAdpd8839d1@?Jx4{%Kdi+VU>S0YVJ&2Twd1JlDGcj z<!M9BxNG|kRK8}<?)4obWb2Ll+&aZ=u;*=5t?qthXfZ{3Czsbb(YdSBZI7oyzXEwr z{n`>sRjt^+16S+-nG)(ztM)CVXXfqn$@MX4(+v#j{ugvi<O2IiEfROvo|S+r6W*i7 zWQW=66(-1a%2%3em4M*Kq-_mL0XXTlyiG3G(AiYuNlNlX?31*M_T$sV$C43N4D(1> z&oVq9Jkm;iY@OmgGR#IpSZ?>MxcvDt#p55+*gEw32um8K44jtoo)?`Ry0`+YB=@IB z=lj1Nv`x@m>*YGG`tV&DSGzf~L?y0oyOEnGKA$xFx^Y1}UyM3E>*@XQUfaVxPBKh; zi3o`O7E1aZM4qY_C$)|4b_tm8Sb<|NK6Dg&{~3B}2l~ug{FWeyb+#DkYa^pU1wm%V zd5dqF^L2+%a@)jM%Z)QEtS`p*ro#Of%?{vv+bJ+~EdQhX#O=|w>&5h_V#C-a{f$AO zkK-AP2{N`Av52b|EOCpS`Z*5coX7Ax$L`#^t17faoHfi;9XR<Lj`!}9O(EU1bBlkE z`u7tG1;a7Oi>waA#BPsbUk}5whx*2;TiqN-qSh47mwp#qyU=ef48E>?2ye!+E?^`r zW4S}w8XpZ|f|1T;EAEG;z}_%Eii81Z(%v+D2pbywMoiTZE1bmdSA6hq9v}JuALKEk z4SBXHJhnFgL`^Q$dm6@CjlMPb%7G21t{^!|$^F=yDq;W`tM8rpQEWisXQDJf<4fVE zNW59OK`5qtTY+eLv`VcYQXgt=!R>+|QflPpC61Mi3*NQMu3_VRdIl%gVfdt#Gdg6s z;Jc6@Pm=GnfD9R<MF49trAFcucH#J<LcVRH4l7tg*iiXF!NiNwM`5G9nve}8Z@QLe zn5dV2t+^przoQ4ta$U+&5Ax0FXpO?9%w!>~5g;T!#a^%|6Ra4+w{+g}*qo&TfJK3= zS8E1YqfhEz@vV8kfRZe2J}TT|*ov;Xiqgcg9*HdwofbjT9AtcW3@VJu8bUxFUL?^k z35XI=VKHKMG*T1|%iDL6pN5>pu!a$^qU#q~%O%kL_`Hu|+aHOsG$+b@uQQsAHDC7* z?juBj1x1N$fdHFmFV?Z#X(h%aCI$tIK~ag~Lk5<M&JHVUXq*1HwX$EsKIBc}pcoY- zMPSkB4fKRaER~5~Edq-Yz`6jR-GYq=Ox_-3nI?c)TC-5;1)l--U3;ySfrb!CyjIMh z5^!uV$E0QF9Z@bw@tNbkeJ;C(Ci4MB00#k7|ADZVVo>DyVF$91QfeEx_8@_euXfcB zZhu<S81taabI-Hn5N9@DYIX!OcY_E_WZ%~!2e}%A+<vXmKH+*{W9d;^%x;VT2#EIY zUn=Gb9Zw^MuZ|_A5pWj6YjLNXy$r%Y9zF!tS$Ec0N(^DGmlY}F5dk6vl2CvgUAR{k z6Duw#m#O*LGgyXo&G$Ixlw?Iq^JI$gLePL;+FY?;21(Et$eafe@y9okl*^OL<m#0& zf3cs3DL-c0AH-W_^obiI0qA7|GHX{j{y&&E>i!3UF--8|=;7lO&_eR2FP+<=R|CbQ z93^u>Fk@n)UAceT-}sa{-<~fs#jl!I#hxs$4BMzO&MKu-Y0`E?zFE)ex-UvTM&nRH zU71SVQ1&y*WHY_Wdu05dVX3-mh>AFbeV{*(27aXTlGQZz&9RHpu9pvUA7%md*+VC} zE=5*C_%gudf&PJh4sL=xsWxPRuqsOWZY7qkKu1&&!(;L^{W$#z0mA(m9SYrgRfH%~ zt`D_CnUn4#M-24KeCi{v;m1n<OsMq3XY{#u1h5jyjW-4ZcTie3<YZ!|e!Z2sRS~bX ziDqx?%KemL1f&EVTN1Hqqymzt5+n*<d~VKRcQ63p-A29$Z**n+lZrh>Sv)GycVE=c z%Hz;`ArW&aHNl<_mW@X$#rWJkz5lvaCZ2{y+?gxg{VX3lQ>%KrzaIfvJrnz|uRpNB z=8B9J;9De3P^eU#`)1XffKy2J7>Oz|23ft|z><eHYUL3YZss|rDc<BazM1j8_(R`J z8$aS2sDodIP0)|E*^fvWQ|Q*I5(ddF3qz#oHP5)n=(YgyC{kyd9ML<NlZz;*8_dev zYa7PN_tdh?0dik6_L0dT_}iq0KY1R>6zYWtqx*+9=Z9zm*TStq&0->aqgU|?=9{@o zAOM6902JpQtpwHWoFnNj8Z@W9pCOw&ezmhgi_Ik9@%DTGrBC)K0bK3SYt!?^!x6-i zQc|i&{GC;%575pb2v_u|Q*$qFia+AU9{(9+ja++K@W5l^M+h}C#_=);MgU;|mOVFv z?HB`@Z7wBZ8;y&m2ZhKU=TnEURII#oSpG9oal9h!No0dvI?Sug*qg+oLIt^gCoNQy z*5v)ADa<2H<`+ZqCa?fV9aFzT_N_p7hA)F*b_TkSKpae96Uk#2(y=4|^^g3mt8@~i zPh9X7-+%nlO3QM>gsPAQJ$|z0@ksEnKdjEo8?|PnLZCXty!u#YOfV^`%e#$#a0(Ih z+MQwSo%MMGN{{blg5`YIH`W%vvaSUP#`aOV{~YW03WAA&Btdeh6gS8tm@0Kq?Ve#U z-QjpGZW5!w^pzL^!74UUHP-OZ0(3cRf*dNm*CU?DCMb6y36j+1*<}9hKc5}GuSQ&% z;P38};$7$}L-ITXFhK%5j=jL!&08^nq`f+V#uDGDyuUicsUg8E;}IZ57Gp)EynFQi z>p<#%KKE3|gH=BZ<Czu}>5x`u+ep_~ex;?PehBicf#$E>lqj$S?_=qNz5~xbzx-Do zb}{2JV*84ZNt?Y5GK3Rf9l?0!bD{?MY#7;gj~t1^>oViZjT43Y#f`&IlCx!R&%tXJ z>;s$5R5+X92}kKDgPVZ{`eDB)%4D9}qoAb2O{+QoY~DR1S8m^~urq9I4`f{KXVA>f zHZuc{Gco(YU3+t`F$Pb}xt}$I1Jn2%I3MAtCpDR5SztS_cDhS|2X6~7x0QD^92TB* z5>*Y%H-<FehQ8Bif0TOmcsXepM9r4=^&~E&1BCGy&L(pB1}MShHKk~Ai$snafnqdz z(HewL+p<Q7s+|5*0XrIwoh+@g)eH8+3ifZHeY#{I_)w}obyr5BUuLhSDppN8fFNks zm+3&dgn;zTxeM@;@rr?*{JVw(c!L!0g;)+U|FlL=YA(mHnF`bC63?u(CW)Xfw`K;o zn-4XczYTk}gP{P9C&zvsUE(>roU{6QzFl|ZQ<*&}@SgLP;#M8VgNW+yd~ZRDAfB<X z@Tezzu~+00`tT_<JV5)sf6asX(~N_;!2HfzYAuvO^B0^oqhG*O?wRpE#SQT61%@rm z%1IPouc-S)3JaR_79Y3~uRHi8_8Ivpm$|7XB*x5$dPqT88mTKOX;nBY$>k|7Js$n} zzV1D=w5R{!T6Tylyx;BS06@0Ihz6X~ha{ZfPW>z5a*ixm7-tIkNgDb&Ixv3qcg_{) z^y%}<Sxx6-;oN$eE1}#tQIBysy>>z^`vs{dr48Cf^qM^J7$3D*IWH;-LtdFHMk_+_ zH<*5A$`o0i^^d}kBmZX#tQca3a(_^%A5j!cm+7@FYl=XTVYjplkT><C@Dd^I<v&(& zi%LMz#p3vJ)6CkqR_)!8l+;X;=7&rdq5dp(2%OcDbZ8B5P+4xK2fC7nViie_;3cbr z0nV0pABQMxT9jlOK8xfWccqklpnj!}fN7@Wir6J)_6ci;``{rGdEefu^)GT*Xx)sD zT)uxtB;1e+ZghDemUdtt__rtgFL`}0iK3<SLP?I<rcb_NzR+2=-*CS#)}z<LWaq#h z5NFGvb-m6wuCe0r+Q#nZfC()x?KY>gJ2hq-Hj=TB>|5lc2vT#JH+TOqBw(awx{}ga z5u*oX?>XXavW}_pL(Rq_Q<GA8^kZ-HQdzWO+$Xi^1vm7ibXcRRh$?DjlH}rtH+r@L zh>mg|j7FJ<Rr(80F_>63WH~8`j0d5Tm<_I*oa7z@#)@eQ4yK$54wHxt`;^S&u&fGU zRUr-oPY2%bq!W%z>oZ92Qup;KOish*_&4ehYHpb8M!D*8(XFWOe6det_kJCSD>Zee z5sI%|Y~GAjISzK=lk5LNqMigD=79yTjMxW$<?3uiFb(QXn8W@ih|Ui0ZG$mXy>WZ6 z5|!Qlm}wn&S|7rWre?hj!D0KK4??<S`^7i8zn-F=wax>54I^dc+1)U^t-GVBKa}Qu zMDG#s`|i`9v^c^2DN4IM^7L$ap|mj!w6M5veUAXUm&w~?hyKs3EJ;;}35KbdcZpm4 zc+Y}YCun&9RCl6688Ua;1i?d@ZA<quN?}9bw)0d7L^d82FN8TL$(NmvakGXO_lhS= z!}Y?o=u6bNVmsxKHls(G>Fnx4c~110J}6X#)(0n4^g*CJu2S2(8_#9rp%`DF^6Lu@ z!70xv{RS&%j!e;clNu}|y;&50JM`;|WvSMi;<V7@W#kK~;IrDIl#HkPPH_%)^LAP- ziCzg&xN{JvdMb}u4pz@<xN+H@1{Rc;#?LHMX^10UHMt@3vJVi0W|a>oc<^O6i&@6K zFAR7tU4+$B!t<5_+2Yp)G=PFXlQQfG>f@dZo-$@1dR?k{@rUBF_KMMe?EJIvzjCUz z-s<Ze{xbcbev3rW^6!-XB+rdeI0Z!@$R}x)beLLwicMwWe+ZmXH4DCWip0(>WlV|> z9EJ170iTh;k~o+w4K_w`QbA~QJkQ6Z$RSWRYa0zKYgf&9l+QY)inYqiLr{SbFZ^*9 zXq3BQwy3eq@EwhjIt-}jVB1I#UZBj_C{7xBmd{0bqk;sVT!Rx66Kv$DBfOzt5>4vP z5c*r%bAPz3CV69Ai)TgOL~2+nfqEoW7zLQddCL#Us<GFro_bkcgtr2UR8(d2(0$ex zd9JvGm`QZwiUpAK#>SYn)_f>~h1)p0^Sno@{hX7Z*s$iDp=T&gk^6n6ElnjFuTKLL zC`^!o>q(nO{HeCXugvYLP2bYqDAwr9<VaP{XE}ty43&7C_Zg=y{_~eB@R$Cm*eqPS z!PQDnIPZ2VnZSYTd@~+!;;!cJuh{MxGy^BS9<h<oS$$2ZV$crE=P-sV!cXVJ9E;(g z)=_?{H;<Y+b@oQ2uL3Pz-&m7oEEV^T@-CEJ+b%oeg0U&UG%z-x@ees&zONoTG?uL< zEc7OAMhagOc6vqM_Zz*O>xkD30L5}ER9Djct7|4Y5PE7?&t+N9^GNgPHP;CTH2q5G z2-p(NgTIaokHF|lU<-r*&@MTF8yhfJ8I&uc)>>>M;`}=}jc=vV<r8?QkQYVy91L5b z9R%9C+#}q&M#Tv@Z=X!0hCZ$7hJK7H$z%`R!@dB~jlF>IfQ>7x_1^o~PLbTAD~aoh z8(wnkAw^}=xLr|dsboR;i$!?In-`B_(l##3=9p`j=&+kwjg$-ST0H6zQtR?AYg7Ps z%BRm={P*+ixuK_Tj0(O;B_8Qfno5u36X&o5Lwj4$D*-iafE<jajXoslm7x19z8(i} zJp`m!<Nz&G(<}ORN6(L)zu5cVvF2YV`D&+PJ)F25zV=a3^62>9T6$bon}F9|Hh+&s z{|P@(iarpZqs&q3&ebcxx=p$t$Vb5bY{J}xIBE;sufg0|DK-k8)1llAPr<66_9XGL zQg=#}FFjor&0R7=tiCYEvVC#k&2Qu7@-#UsVV(F{%~N;1`3f$7XoW85eo}e{C0Q(3 z$fInC_#Q5+n?D4RR@;GFB`|nXy`}J`J8*s4UHZyrVTl5&>^~<%dD#_rQ&#s=U^NH@ zz<9A<4joCV555O$r>yd!cBTD?;fjka#U$@U^#tF*G)@m%vldN<=AMFOO>uMgSrHuK zb<bo^UphQ;$Td$0v$1~IRR{@sjpRg=vptK3@f1e+285c&`PO#Fj@FeowV?&ZUw-J* z$h?0zaB@Mx)oP|}B5wAIFIUW*h=gY%i`Kn+(32ZPR75((<+{Onbgwv2{jo;yj1&)A zSD;$ZQ!Y5-661kYu|BVW^*u*V`Ku$bQxIgr6o~nNBgU#_OruBVL4pJKPxxc=HvObZ zdfXX<WOj+&=Qm8G?h58%_3_ImM7NT05PkLwQ3)zvVDxKFfmXE{j_LAy_Y7M%lLppJ z6zPxGu}%w=l_h`M;vAGz%DX*(5*L{q*QK1wC}c1+aJ>!=5XzMK25I{g)#s=MS6Uy- zCw@eyLN<m1{{E)F?s7mFYTBG(I7;DFlHVRC^zqnRZKCVyHNWW2W+CCR^i5f{>>-V) z538`8Js}ZcPED+JR?XR0Ss68&3O22y95>Y}GAOKMDg9c`iVK}K(D}ZmM3;<p{a9_n z%LfXD_U4z#GS^-1*79D0ynU>{DAkqgVc_Y0b==KFwMs=N_Tl*$X;R85Y6X&d=Rd`v zn|!phtLU6(|9*Za3PfbZ8}?I~v#_I_PC7x+!;!@@!SK;nB+Hk{o-%NiDR~~X>6gn( z&7+uJo*G%COF>BQ7bK|ums%lr24X!bhdO7_@u%NlIW)?5#C%*=Rdjdm5~Zr)y-P<( zGyF;U;9(Z->BgAizIq)J%fuRZn>_0M3g_U+6ng;|u3xmTW!IjH9G7>=dX$a12oaTg z`qn~SSt`jQL>;3pbXi;W(-{A6AuT1GIR%Y&@CrZruHXOkuC&y#Dyx`=H*OdjHso*2 z$gYj#z3-%dV;pUvMFsIPA$38r`b%E0v+$M6HoQT3C=>=*G)cFu5XRo92?j2Mk9CCy z8Yt|^>eI*c#lRm_q^jGK*3&$4wiWttp9^H2HNQ5ckFUm31<9Bw^SfhYx$Y>6arm@} zTO$76V+j8Z@`k+s)`Sf1M$=OgW8?MNCx!37<-GdafqS-_c5u6c^}TqWd)txCr0{d@ z#1)dRuqP|2Sy9EN_0*(vz~w7}v)wHT<uEl@=YJ{1Pt=w<Wi!|!uahfPkIB=t1-icL z;l*GlGuy~F^gAUl28(;$HtSnIP`+3RNyb!?Sn3t8rIB}{?Dj(M%l>GO4M`tU)Q1TQ z<#adBIfY1kO~_vqL3xND;?Np9M7gc4#PF5+JDSwv^9iiMsf^99F@dFK>2MRTIkXwR z8Jy!DXUq{P**u}5Z^=pZc{kRAZYb1MI@W%kJ$Q$5625(*nYa1`*|@rvqT=rceV5n; z-#Hth{Fsrj=w%xw6S*bYq_1zA=sm>b(0-kS!b$Dn7JPs3zrN(t_a*kIi);6~i|LDB ziJqtr=f8IU`uF`bddW3E7H4}^#|YVlV(E6nA~VAE!LM2&2-n_!TO%WGV((XldN4X2 zPG)j6X=_`fytWTq!*VwIlxE)eRh#S~{7eQ&x<77+10LtHZI%99_xiBnhqM*<6+#`C zoG=qWE^W!sW*x5JI5x^fy+(!mK8?Vh2s3UP8;%*0u?_=c9h}(+#vYQ^$vk&!><P}@ zyIY<_wF+_Fe7pc#g2I_U+Ey=9zhez!zSg?Kd6&K(XF-YvrN5!9@{oz?{Hf_u!;OcP z0pMOxPcSHN384s@t}e~8y2ra|_&xC6f)pt)OX(eg0g;e@Dttup@(x}I;e4C-y{#km z^rH9oq>T>xXYH96RQc~4h;xNL;GdNypJP9kKDCn88rxfl$JLL&UQ)T`!`R1=elmk( z_$TF9RdL(0NFEC9p?5v2swz+PxdUC&qSZ>PR5hl08*BV{&w<r|0VdTx?gOqo7T&<S zLm(!gWBM1a-U#pG0}}G|Gp*Md;jWnJ<3h0i(*nb1j``yx7VrQzWjfweS!tL1V@B<N zD(;mDN|B0Izy=rg;1g1bwys5@J)OoKrH;nOVr8I|s~F2<6{`nbLwwJN!n1-3fl07g zvSe|v<f6Bzdi8gC-2CDfdnqd(J`%6uG9u3%)H4A(Vr);pDLo_V*QjEa5gRgN9K$VG z3~({wKQM?#be)4l^x$?O*k2}WXV%afySa{%kmZ!<3wKa~R9V>E_WImIKOOv7;7kZ- z=?aDG@{4e1)vL<)uo|p<(w;W;$W{Vs-iINO3kF^AmlNp=@26wizWv6mSk!T)dSBW1 zVQ>xB%t@KI!5S6EXWnZyNQ!dc#J`|ralggEAbIae<HsEutUL2)xx<j9Vl_#tyFCnC zGGnaW@{XBkJ#N!ls(n@9@{8Em2Ar1r1&Z#HBp;4Den}0=ietL3N_ncz(Ejl<lotA4 zJRM!5bFdUwV<S>dLySNWw!^6qnT07VbNUEd$t1C|+i?A;p$EL}N5A*qm0et`9T<zA z9pO5S#D+iaAb9v0`pIWm#P-z5qx#H`>pm$wM%GizsS#_MDADPOnVhNL#b7BXQbAyB zV9z>FpAU{t4*p_*PWIqd+XV#wZ#hLX)g@)1nqsuqhnugTUX^Knso9I`jV(h!hwwt4 z3-!C$dMP}rFJxd+a_;IW?Q_!JR~G1oRL9UCUD9~Gr&wkqwk=3Rgc}$9<RD=X8OMdX zFoVtU(VX_hwV^F$*RWZX3iioHqv+=7rEhp$lu<g%Z)X*(Lwu1S*v#AFDi~A9VGL*{ zc1mfKjnHP@U!wO?b(Z~4=^Y^@#lH}};#4oaP*nmCOo8Df53IZg%dt8DM_L8Ts7kHe zRV!v$!eMs_Lhn~pMHrQgtGFTrOO|5w;g!>y3P5NBZVU;qQYL4edG~W9OJns%*HpmK zpA2WELJyV@iRvurds-%-&wUwxfZpJ;EG(lElyQkWz8Py7BFV8~eUimTndDV>jaB`p zkqMC(=fPb-J*He7yOX(@17~JmHqHjm<o)ES#eiT;M-4d#ow5^gYKC_wB>pLD$$@#d zj7eU@ce<n~Mt6cvU}+Ego6%?Fyt-6zTSJorL1&Hn#9zMRgM)D#gG%38$jNY|0z;pf z&Fhnae3XH$ocVbKV-PySa&9CV%HTSzPRvgXivP|&ue9&^Qd&vdQwfXH=XF5e<Ha7+ zx?D5450*6ly~<r!2UT8ntWM@Tk@9PVL_0PW*8vnq5o(RMDmKOMgW^hB$BY0d=`^XA zYZDkWKTbOu^ZmZGCf=t$-N({J;N}2vq+wXhE0H))wE4zrth-y7KbFHoMU4Q<V#2fl zrQ0x;Ltd=j@<6!h-IN=_oXgmK?vqv1!d1^19Z=QDIJ47%mqQI{XhO)#pJ@mts2V_0 z>XtzBNR99b(R-5yRy9DVp()JWN3SKBoNbqFE8QjyZ~@M_o|6SU$b2ROY4*W;98t7% zJ?PF6p!WGX$WP=K@=cHRo+62MBj>cccWAU7ugbEw2mnF=pgO`C35%w~A+*deJ@`ks z7!}cG=yr$IB~r}@(|iF-q8;*dP<+=CQ;bw!(J>R37kqfI8takMfik?zh_mT(@_oTK zG~Hgl5cj)o7j5HH-%7lsUYqd)Z=msdE!X|wH|h4*WUt2#EmI%DCg0sSiDLw{=djXL z_Gzku4jMNk-T1s)zA;Js*n@pnn=e>$Y+`@N9~i^*@e>8Lm>M63<DXn!JcS<^dQCW+ z=P+m8)!{i5HKL^U11nz=5S^qU>8T!F{gId97Uj<ZksRPBX;2)4Bs{HbGqDbtr%jLG zK!>{gWyVdDn0H^QN5Qa`yh^uY2DlJO*TN^|31Fl5O6>Hnv8Ppty;RQ$qm+DDk#I_4 zSZLkYD~L-QZfnEqR}NT-a)bBS=TON6rJMqRJz&xSXJk0f;y*hblfZJ^uYT5Wi0!AN zRw!Z&{oU86ShR3%ZTK?fm^)s+|61LR8mUJ4o&+JuobqJ-p9UB6Wve8Sbxe3pF^Crc z9ZxbUzS@Z344ksKznkPfGID|LnB_X@cZK}r^~PJ|xros?gsdnx?>X_J-k@yN?hLmV zdGP>@Eu0oVF2`^g4_0RJiuHqZ6JqLg&dHtE^10Zcun$BmtgB~a-Ti5C@kkqz<6&^C z_PW%cOG(q7FewJQ_(ohk|0>RtmktC-J16qc&^pBxnuLHv6t*lp$$ALO+G1t@@?Z7p zjmdhPv4;I?KT3+%8*D8z<uW7dX5A@1TB@u@s;}22&DISq<c$pFS#a;e^Q8j6mJnWo zlYb6ej~wkq_i@G}%ks3jrB+Fd)cNsU9-ssvntx2uZj{&71!IvwFM2~AlqQXw$2$z9 z-W6E65M6_r%EQ~<z$Mw>0!KlI&L)RC_5aO35o*9vz?OC*4ml#Y`9`VeLP<K-)28y; z!U2m$4!vqpnnG;GnrG1ep3;AF-o9JA;FmTIp<3i}<y}7?u1@+0=g?9Z6Ws8lJ~9^v zh%)bwYqwtS#A-T9>Il-#T#}qi-`aPNg%_L3fRRXdI|u<3BH|;`XL?~Gg`MhTX=-g+ zpG9H(p_P^TVa$Q!)<95LiKd0?!>GN-v1kAsI{7#}5gyBA>2SEh=gHeq9H0)s36GA9 zJ<2F;Wg>k^KlmN$*W#r)WDywO=Z@u<BRcbdDn3H5HYwFYDEytb9T(GjNsvXmb!;hJ ztK%G9m|%>+xbu0!4{rf^?(LR&i6Imb2R5fCSeF(rkv1^MENnv22*fMcZnF3CjLhfL z6Mt$;W&El3S0(e+F2-GVE28A*V|!X~fk`<0QxfqgwRaLaY1j5p*t)@f-_^TSv8NGt zP{l6yPEBq3vbS?n!>x;jQQ(JB*c{dr)$L$AyT}S5z~Q^QUzaSN(ZUnyaYUgn!gz|# zvsF2L8NV4ht={&c^E6KQ`hBN&#lPpPiLyx7n*jq(_P4d0=f>B!$aU@dzFEzFD)0IZ z1JK({E`$e<AvjRp1t){$-ee-@3#V0S+`RX76k`I5mJm1Y-{TsE*J9qB7e>|+1VoO< z;Fz=N18L<_(%7*ml|HKZ0!4LZs9{u%2bqEBVC7Z8>H;xCr32oj>xe*2gx|-xfppRn zi)^E?7EoTLG>yMObg%K3%mpK9l1NWrgu#(~7S6_G<VQsA_gAU_XmswdaQr6Trx3?+ z`TG{Wga=GfbjA9RW=#}r{32SAIYim}e?0RsA#bUGfHpg6L~WUpmh1KM>c5ZhnQ3?* zQ}X_SA`Xe^XNrL5n;`4(uO;}~r*B)VscOzeA8n*B{>oyjNX>MVib|Ce)5uFOiq3i$ z^fW*o?w_>a-Tr_Z@ZhdBe1AFawW6oZe%dkSYEv3FABK|qej$rf9AHF5XSzISe<SH@ z@z&%xOGf46=n8@|7Ji)W2g;!$I3y@<MDx#{+mU445GNTkLw9c7!g@ZzO$-~@iWvSY zib;MM6C~a?t=%r+_QgF9c%b*$TH;9QYts6lU@pk4@Np=&_e1V|4BPjF&$bkYYMmd` zgK*xX`Qw)3y%LY_%^Rzm*Hb0v^s_Z_&lEKb1$Jb2|I$+^UeZme7kIeMUg}{N?&|s% zokIFv+<)<GUm*9lDv6-b_uj?H=R=08B#AbojjfM8-i|<PHp+7SN8djjeSP*HOXvd7 zhpvh_p4^537%Y{QRfHeXPbeWDb0@XCHjuOZ3W6fa>Bc~*VIu$O0*yRBCK+O{X6ibn zIz>)7FGI=EHIa`Y%L_t{18LXXv-1UI!3fil3X-18V`Fn_Q+XeV$ZhQHi7p|rX%*_e zfctvNlv%>e%>}8FGcAGdjyj^*Pt`57hkc#T?(~jv>*m;33#VQ?@u8R9`RVmWDOIZ! z`AOk!cJ0QsVc93T#$Dcum!8@e=x%f}N7kpy%qWF=sX9NI^=U3<yp=jn14qo1PpAeq z!q;B}OXG~ki?7^~wo9APvkb8-mbX;YX5+;pF@%X<kVc5_WcHc)AFfpyMn68E;qh42 zsL$N7FEf|2IVopfvXhD8Q={tIlpLfv^DJI097da(Kpb6pc6jY5fFK5KeH|O(eh1MT zOG!6Jd-M;IV=$MpNiZGn9FiI4V>SsKR))0!8TZ>6S;|4|FKyYkh*Qv4uiGTT|J}%l z`_pg<8p{K(mk2c!KT7n@FjY>pO{hy9^3JlcG`W=R;FfqvU$0}X;Fi;Ec)5uSNysN( z;1(FhXYYs;3!8EZeQ_*Eb%z$tJ9)gI@HyC7zmQ}U=ai6t+@EzMwVkwMrW(r$W|(YP zv~8Tf`7xKCD=2p$;Zi&+>+7l@A8T*Lejrmqx&f8<G|KPd&Ah|e@RZla61<INpjCNi zS=9Mo`B|}m>y2zP`q<E^#RX+GB<Q-~7n6D!J8vro-Y*aH=iHKmo(5W<Mu99TzU;wm zD`{rOPTkO3bMYVRA{VR>(9x~z{O##jz97p%86Gwc6#&Gl%e*Tcwc!L6joiIz>*oS4 z=C^z(V^>4GcjO?#TftsHHn?RhU5LDs=^uqI59zL)0$sK4+%(bYb@V44XRuPq`EGlP zaRN#y>C!xj>j4o0*YoJ(vM(sLRv^4-nX=`xrwOQGpdY_!Hy}e^H$bcm)sl1z!h)NL zm%w2p&Ox&qZ+-L!05D9H`4s$oC+fyR=%mG|_c<EWn~M?OyIWsh|F4^0!jfY`WXaIS z6UuW7=rdyG*p&bvNPRQ`lz9sE{z15d^{0pB)(B>aSd4N6Q9%~cLK%7PqoFW&f$#55 zfL0=hz+iUYNmW4obVR@?kYe-tNscD31V9S-?5~evZRyf4^-s+LkGt(TT5+?8ocyAt z{eHvb$m4EA6+_$dLpAyKs`v1dHsOief481-Qx110&r$yEk1CC<T7(FwNSFz#v_rI( zKwMUYk1%9`=_cr$KLru{$y~kWO39O3oDKJf%UP*eC&@+tjQLyCMi*FO^LF}t!4>@o z+1B#H6G1?<ATA@PKv$GqI^2yG_?ma~5t2<btf9k4^}A7JzW-zBECZTq!!Udnz%~I# zjE>Qbw19vEHX5W$x}>E=1h>J!jZj)j=?+PyL}Dl*iiipbNJ<C_3WBxo<KOvp-gDkl z?|Gi<zHcKIYdx1*ttuhkfO!b!oUf>AN&I=IHD%*lWm~dsR55R{zEaL-u;&V?;pslI zmE5lj#PF6?_3(6pMJBxm097w@iwjJIumTu}`k>~yDzKmq7q`f+yrjAcy8(h5Kp9s> zK|!OB8q{=uEN!xhc4j4PRG<%NUCBvH%5dbT%|7ml>ev^NFa}d6WQpfS)bkt;I;OQw zpub5%H_GTZSDYnQH6&VPKJO%ueW1CYIn4$CR@g-cPGBn!FMJtXqg)D~@;8Yr^7~F& zY089SWQW`t9D#6fJ|$ROJ|tfs_?&MeVU=y5`%Po~hn8*m1KeglD(bcDmG6z@@lm!s zM)A>=;ZeQ;F;dd75vCkv(#vk0#GEBiwRTeoFRm<!P1>5;xXJpxb=x0dykOk&q7$E{ zE*JeYeeJ@%cPt-;4u$y^i<nvBl;*7>YgC%+&9A4vE!oYz9To@{Y#;#m@iUELEJ;F( z0YS9#gwuEOJ>Y<mZ&}cu2LO`WxE904yMF_#nXNLF_`N7!ejz0iMeAKK3}Zw||Agzh zDBKD-^-BP&$TukA4XfsT8F5lM6TU}48eU<NWg%L%Tkor1H)@|g_qB2M3rb#hN7&7+ zDt2FGoZZHx%ro#pnrK!U8s7JIIyI)VO0GHJO4`C>$6>^I|FfTs>8X#FTSN#8P8=Lg zcS(E&$SGbIm<i;Z)}0aJarH5jMi4B%Tl#Ue6+{^OnB_3O7E_X26<fFN$5Y!!%P+<4 zxfxz$i5?z>H|-jQ)5X0ZyNR~2a);_KA{0%<tJ=AAh2nTWTH&5cx4V+o;uW`-6J5+Z zuJ2n#eagO6UlT(cVhn9f5@cM3mCE65JqAH*+gDA=di~HgIW+4BLf5$BgIaholUU$b z_UDsoz|vD%VtC9*8k@+EAGd@6l=t(B7v(o_J6D+z0OsM7hLt?nou#!-wj0sHczz>~ z3&KWXm#8s^qhp!PXBa&9{Yv=Iciipj$+VJ_7OM4FB%c0dT3zm-eDe0aH6`?Klh{{L zEgcWOrEh6{@MUjI7zA?-lB5AJTW2&`GJAqSS{<!!+MOtNSBo3Z3<f&s#;K1Q%uJL0 zKcL-QtFc-?^IM6%18|l>N8b4>jr(&#h3e6|nU@|v_F0PqiNkK}2eNX{j5eo-kgG49 zP9J?miqN!E_TqZ--rcnfx^b+MmB^4?@o@j*HP)SDpM-#Ul?zS<>mq)Jy#{+b9N0;C zR{O)(8DFCsZ!PWNTXy<2ZIZPe*XHTlLeM`kXC(BQV<*$s<Co@{1$3B9MR9V~Q?t~_ zsXVm)UDZr+>mX}JMIorA!Zvkk$L<AE`<&p(vDPjJ-OcHVN5Qb|?Wb7EbhnTu3vi=U za*wp}+o3WPrUxE0N#NO739VT$uGn8P{x81Lm-dLg>uh|HHSD7+kV)b>y=8DbvZpxo z$-75)kDG!LzI@>s4Jpro=N4<R1tYNH2y-6k$UJuK_i3Ky7R_L@i)=s5Yivi}`#sr^ zk5Zw@+|-qCS^uI2^>2y!>f$Gt1zA)^hF^wn??nWG7CW%av9(U_O>UzWKKoy-F|N^W znN}}Tfk^!82OD<=yzXqWmWuDed==-yK@M#qa--wJ{V5}0qi9dMt>1ZPX*(+tz|p{k zfx~<E{!S-?XM#X<3#Lh@yid&xZ=L=%Cb$5@-^;%OjyH8v82!b`_`e$xm&f3&dVs9w z?++qB;!1C`Y$z48b3iaJvL+RJ&(KN+$!%2kyIXk3VQe(WogRo#r!tge-zc~kd^swB zNg?4(xW}O%54AEHNBLC^GTh?4MX!5Bd<ZKZ9yBgaph7N5Y(^GT%Ladr%JxAL53bX; zo-oX|6UH6H7Eu7~TGFMlB<<~_(HlfS0XSbKe%`}fJTeHRjyyh5IllruKWK8|i_|5{ z<5^d|=yZL@tAO(dK$bEK2or$6ANcX-mHMav$RPAj%$bBVLE$2&)i&1R6iBR!x_gZ+ zrX0;b3)p2|t^L7U0uHmt*Gg1nfvf;$@^4cQcSf%S{YVZN`cBw(iVHokbw2=}MP$~s zJ2wL`dH@T@afVyo4bMZI-n!C%PNc^Vk<KLGw=%`e{3(~aMLluYcK@^|<g^~gYi8SA zAT-jLi~ZIMvEC=9c5^%q{+iDV^kNE9zjq<MQtVvT(qeRPOgMVHoFhbnXo#^G4hR~F z+PpoMbCZ84?HUWfJ42Sxz2jmX{<0D~laKWDM=lm1bBqw9k$%kKPOM!qm+*!<T;cN8 zbaz~a9eQI$*%*L-{+Z{-GnsZWCv6>?iRhhzAdxv9*nw`bf5zCH5z7t_iX8ZEGyTU! z<i~62Q1rd)AhqY+fR`ac;s)ofuz+iz3w$Ei7$qZ7Hp#45qAm!*vBSkhVaL3Pd;Z-0 zuBUxDIq~N;*J%IL4`W_iIruv*hk*RA%xXm$&DgxF<9V(-dEq~RH|p+THV!6^NHcW4 zzf~rkZt}!f7M(6#K#xe<95Poln-!N0o&zEZGwsJYn9=t^D}l4LYUFE9&O#uUT~W~N zg;x+UGubHr`Ue(&<ILbgB0tDlH=NE(%GabYq*C3t;|>d7)Xhg=Jf1F`t|NkD{v>bA zDmZDjs7<Q4!?@Vj3(ky*yvX4atj<C=2>qwVQ-+~~g=s@Gf$JK)g@eW7i2ze3CDRlB zQH6zm8hZOCkNpb3fCM06XID8tD+|tyywPinY}yFxc@Mp12s{fATc`pcNZ|QAl*{3w zLmBW)Ny5zI0lv$ab1#|WXuK43W<+9AmIXq@m*uHY8KQ2g!&1e-kg}Zc>nzfj8Fqco zG;Ln(WdpSa+|Fg$<>;Va<sv2(Vu2MB&IZwj<&qN>v^>iYSwy9xbfvOM<({6LYHDQ_ zQVqU<v~2|t3I!U{Rr)4XxWKCO-XR7i6$sWUrtly<wXVuay4uF18k}mj>R1hNHu`CF z>sr=*Cq#{>bdC4!Ed~_X=Xc&%ZWUMC-JsN(>xkNL=~_m62fK^4S2bkp#}hPe)+X%M z;t_Qx9Tkv6nNQqxj|(m_1|kJ0)pvI5?jh>4QswNCz-wcdTB-UcV<rM7$OBwrA)=vN zx}g%!!+Wb$c-hGQKcj}rjt*n<NIL~Ie|JNNNn=-FBl8f$d1Zk6chRpKjoM@vbU;KL zxa3)2(~H!m8>#r85_W$aBFCNMhY-zgO`6}C&>BK^0S8O?1vt#2wRS6@+2KROs!7Xc zU`sdxG3=ji9@i50(`g^^=urBRJ_0eBDv!WxJc`Y~lvMQS-|nOTCi4EfmJaf$1O9l- zwwKa3ww{}89lu!8qDcC?&{~HJ9anAROl#u~O3KI3nN0%^PXKeEh3Ah4!#f{NUApYb z_ED2|xi9S(&UK7QHwSqtX7F@eOzY5S>?mxg2xd`>>Fv;!>C`vvwBEJ<MJ~*C>NK6i zcbb3c6m)iI-$gz->9h;#a!Bhs&z%tSf}7Q|!|B{(PnpNwlc6xFioo}AK8=rqCLf3N zc|1$ukTpdNZa<C=dU7M}$u!AjZvojM{NyI>TsKjsJE>1T)UK%KX8@_OJ8iN%<D5L3 zGJwD3cDmc07u0h<tp}0Ab$_Uy`LL*^NW7<9rnl0xw}$9~zuH^h*xNYSOAk_cz0lhx z)7R10`|CZ_LZQ9$KBqL&B*!uUjj#9Y5|+ts1%d||(g)qG+W^Z!_}<`o#-XvcK_<Q- zRPYcdA2(b25bw*OO$6e*K{3zbkcipvb7#8JnQU4+#f;HqSZ;5)GEP2sGE?~PuxjuK zvFJ|d?@X2W5$(N^>$_R(i%D94M{vPZ8xvp6zhZ?Lx?eTo$~dZ_?5IsTzVck;W2ZIy zi#ujkW}~iqqY{C1CLrQUM5kr^9ryI-0WK9pG}ZLGtn;Fo%;NJvvlr2P^}c52F2OHu zy?oL5`?=quQ-bVRl5B$$;}}Bm1*vH)t*PpDV&}`M7wNL&IeaxKB`>a-jTbhJ+x>oV zpKq*~aiW~B%wZb%12#M}@xZ4#XU~bt-<k&CmOxk)V2W<j9)?B;Yi7w#^u3&{Jf0Z7 zpIw%D_Po7>qhl;AU&2=sP^@Zf;XoM*Mm3|oOk@YBB`+O<k*1k1hks8}_sS6-Q}E0( zyVhDnIneMj|Dy}i{6Jy3b~2bV{(b+;r)IB@gAJnZl*ll;1a(E>pTmr|66IATtz4v2 z_QhNa8t&Uk0x7?Xz9=WMh`dmJFIN}z8Wr*epY*yRar#mIV@|8PcNLX^DKT&YOY%`y zqbv*59J%<T@VR6cN5Kr_O=JAU(1PHI4sZ%*^V>_Vm%0Dx^YVxBFClGx$?-;Xw=`H* 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 E7|xLlw*UYD delta 163552 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℘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 From 9952a3c456e4af1bffb4e5c85968fdf32a122e08 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 18 Dec 2016 18:17:26 +0100 Subject: [PATCH 19/71] :construction_worker: trying to fix coverity task --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0f9010b7..006647ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -98,9 +98,6 @@ matrix: compiler: clang before_install: echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['valgrind'] coverity_scan: project: name: "nlohmann/json" From 0fffbb8488bb88a938e2303fbab7874cbbb797fd Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 20 Dec 2016 19:06:15 +0100 Subject: [PATCH 20/71] :construction_worker: trying Doozer --- .doozer.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .doozer.json diff --git a/.doozer.json b/.doozer.json new file mode 100644 index 00000000..67012d8d --- /dev/null +++ b/.doozer.json @@ -0,0 +1,9 @@ +{ + "targets": { + "xenial-amd64": { + "buildenv": "xenial-amd64", + "builddeps": ["build-essential"], + "buildcmd": ["make check"] + } + } +} From 1178a8152a7bab880c466d1d6be411ce66f59e90 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 20 Dec 2016 19:13:19 +0100 Subject: [PATCH 21/71] :construction_worker: using cmake with Doozer --- .doozer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.doozer.json b/.doozer.json index 67012d8d..97f52598 100644 --- a/.doozer.json +++ b/.doozer.json @@ -2,8 +2,8 @@ "targets": { "xenial-amd64": { "buildenv": "xenial-amd64", - "builddeps": ["build-essential"], - "buildcmd": ["make check"] + "builddeps": ["build-essential", "cmake"], + "buildcmd": ["mkdir cm ; cd cm ; cmake .. ; cbuild . ; ctest"] } } } From 73b28e8f922e539a6317b887d4ece8a3add05638 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 20 Dec 2016 19:16:52 +0100 Subject: [PATCH 22/71] :construction_worker: fixing build command --- .doozer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.doozer.json b/.doozer.json index 97f52598..89386481 100644 --- a/.doozer.json +++ b/.doozer.json @@ -3,7 +3,7 @@ "xenial-amd64": { "buildenv": "xenial-amd64", "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm ; cd cm ; cmake .. ; cbuild . ; ctest"] + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest"] } } } From 57b32d97736d204e303be26f44ea6159c3041ad9 Mon Sep 17 00:00:00 2001 From: Andreas Smas <andreas@lonelycoder.com> Date: Tue, 20 Dec 2016 21:38:01 +0100 Subject: [PATCH 23/71] Add Doozer build badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 97ae6854..16c7eabf 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [](https://travis-ci.org/nlohmann/json) [](https://ci.appveyor.com/project/nlohmann/json) +[](https://doozer.io/user/nlohmann/json) [](https://coveralls.io/r/nlohmann/json) [](https://scan.coverity.com/projects/nlohmann-json) [](http://melpon.org/wandbox/permlink/8soFCqS532vOyZcK) From 38597ac62826d1acb8fc557e4127f3c62f8f4109 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 20 Dec 2016 23:04:07 +0100 Subject: [PATCH 24/71] :construction_worker: added more builders --- .doozer.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.doozer.json b/.doozer.json index 89386481..eaea3b02 100644 --- a/.doozer.json +++ b/.doozer.json @@ -4,6 +4,16 @@ "buildenv": "xenial-amd64", "builddeps": ["build-essential", "cmake"], "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest"] + }, + "xenial-i386": { + "buildenv": "xenial-i386", + "builddeps": ["build-essential", "cmake"], + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest"] + }, + "osx": { + "buildenv": "osx", + "builddeps": ["build-essential", "cmake"], + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest"] } } } From c6fbd305b04866632c8a2c5cf501a77f94efc57d Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 21 Dec 2016 09:17:17 +0100 Subject: [PATCH 25/71] :construction_worker: trying more doozer workers --- .doozer.json | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/.doozer.json b/.doozer.json index eaea3b02..3781b86d 100644 --- a/.doozer.json +++ b/.doozer.json @@ -1,19 +1,54 @@ { "targets": { - "xenial-amd64": { - "buildenv": "xenial-amd64", + "jessie-i386": { + "buildenv": "jessie-i386", "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest"] + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + }, + "precise-i386": { + "buildenv": "precise-i386", + "builddeps": ["build-essential", "cmake"], + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + }, + "precise-amd64": { + "buildenv": "precise-amd64", + "builddeps": ["build-essential", "cmake"], + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + }, + "trusty-i386": { + "buildenv": "trusty-i386", + "builddeps": ["build-essential", "cmake"], + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + }, + "trusty-amd64": { + "buildenv": "trusty-amd64", + "builddeps": ["build-essential", "cmake"], + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] }, "xenial-i386": { "buildenv": "xenial-i386", "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest"] + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + }, + "xenial-amd64": { + "buildenv": "xenial-amd64", + "builddeps": ["build-essential", "cmake"], + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + }, + "fedora24-x86_64": { + "buildenv": "fedora24-x86_64", + "builddeps": ["build-essential", "cmake"], + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + }, + "centos7-x86_64": { + "buildenv": "centos7-x86_64", + "builddeps": ["build-essential", "cmake"], + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] }, "osx": { "buildenv": "osx", "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest"] + "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] } } } From 2e5208d5cdf735bb7f2588992a2ceb0a63abecdd Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 21 Dec 2016 09:19:53 +0100 Subject: [PATCH 26/71] :construction_worker: there is no cmake in the osx image --- .doozer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.doozer.json b/.doozer.json index 3781b86d..072270d5 100644 --- a/.doozer.json +++ b/.doozer.json @@ -47,8 +47,8 @@ }, "osx": { "buildenv": "osx", - "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + "builddeps": ["build-essential"], + "buildcmd": ["make check"] } } } From f78671de8e8fe94e88d674c78428a71e72d89d89 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 21 Dec 2016 09:33:16 +0100 Subject: [PATCH 27/71] :construction_worker: Fedora has no package "build-essential" --- .doozer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.doozer.json b/.doozer.json index 072270d5..fad1a6a0 100644 --- a/.doozer.json +++ b/.doozer.json @@ -37,7 +37,7 @@ }, "fedora24-x86_64": { "buildenv": "fedora24-x86_64", - "builddeps": ["build-essential", "cmake"], + "builddeps": ["cmake"], "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] }, "centos7-x86_64": { From 91e45a8dd0b560ac01d3ad14c0b45bbfbebea094 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 21 Dec 2016 09:47:31 +0100 Subject: [PATCH 28/71] :construction_worker: the cmake of trusty is too old --- .doozer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.doozer.json b/.doozer.json index fad1a6a0..808dbf21 100644 --- a/.doozer.json +++ b/.doozer.json @@ -18,12 +18,12 @@ "trusty-i386": { "buildenv": "trusty-i386", "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + "buildcmd": ["make check"] }, "trusty-amd64": { "buildenv": "trusty-amd64", "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + "buildcmd": ["make check"] }, "xenial-i386": { "buildenv": "xenial-i386", From 937cca762fe0e5080a6851ed922deb8d4dd7a0ff Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 21 Dec 2016 09:54:11 +0100 Subject: [PATCH 29/71] :construction_worker: forgot to install make --- .doozer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.doozer.json b/.doozer.json index 808dbf21..2e1f73d5 100644 --- a/.doozer.json +++ b/.doozer.json @@ -37,7 +37,7 @@ }, "fedora24-x86_64": { "buildenv": "fedora24-x86_64", - "builddeps": ["cmake"], + "builddeps": ["cmake", "make"], "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] }, "centos7-x86_64": { From 2cf0f299ade6c778d7c38c06d2fe2559d75ba683 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 21 Dec 2016 10:13:59 +0100 Subject: [PATCH 30/71] :construction_worker: using clang where GCC is too old --- .doozer.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.doozer.json b/.doozer.json index 2e1f73d5..67aaa8d7 100644 --- a/.doozer.json +++ b/.doozer.json @@ -2,8 +2,8 @@ "targets": { "jessie-i386": { "buildenv": "jessie-i386", - "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + "builddeps": ["build-essential", "cmake", "clang"], + "buildcmd": ["mkdir cm", "cd cm", "CXX=clang++ cmake ..", "cmake --build .", "ctest --output-on-failure"] }, "precise-i386": { "buildenv": "precise-i386", @@ -17,13 +17,13 @@ }, "trusty-i386": { "buildenv": "trusty-i386", - "builddeps": ["build-essential", "cmake"], - "buildcmd": ["make check"] + "builddeps": ["build-essential", "cmake", "clang"], + "buildcmd": ["make check CXX=clang++"] }, "trusty-amd64": { "buildenv": "trusty-amd64", - "builddeps": ["build-essential", "cmake"], - "buildcmd": ["make check"] + "builddeps": ["build-essential", "cmake", "clang"], + "buildcmd": ["make check CXX=clang++"] }, "xenial-i386": { "buildenv": "xenial-i386", From 7107072f71e1e80362a1fe4e6812e381efade7d5 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 21 Dec 2016 10:33:36 +0100 Subject: [PATCH 31/71] :construction_worker: clang for fedora --- .doozer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.doozer.json b/.doozer.json index 67aaa8d7..589dccc3 100644 --- a/.doozer.json +++ b/.doozer.json @@ -37,8 +37,8 @@ }, "fedora24-x86_64": { "buildenv": "fedora24-x86_64", - "builddeps": ["cmake", "make"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] + "builddeps": ["cmake", "make", "clang"], + "buildcmd": ["mkdir cm", "cd cm", "CXX=clang++ cmake ..", "cmake --build .", "ctest --output-on-failure"] }, "centos7-x86_64": { "buildenv": "centos7-x86_64", From 69ed19e483681c2a64944f3b9b9351326872d350 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 22 Dec 2016 09:08:50 +0100 Subject: [PATCH 32/71] :heavy_plus_sign: added libFuzzer --- .gitignore | 1 + test/fuzz_test/Fuzzer/CMakeLists.txt | 45 + test/fuzz_test/Fuzzer/FuzzerCorpus.h | 217 +++++ test/fuzz_test/Fuzzer/FuzzerCrossOver.cpp | 52 ++ test/fuzz_test/Fuzzer/FuzzerDefs.h | 89 ++ test/fuzz_test/Fuzzer/FuzzerDictionary.h | 124 +++ test/fuzz_test/Fuzzer/FuzzerDriver.cpp | 545 ++++++++++++ test/fuzz_test/Fuzzer/FuzzerExtFunctions.def | 50 ++ test/fuzz_test/Fuzzer/FuzzerExtFunctions.h | 35 + .../Fuzzer/FuzzerExtFunctionsDlsym.cpp | 52 ++ .../Fuzzer/FuzzerExtFunctionsWeak.cpp | 53 ++ .../Fuzzer/FuzzerExtFunctionsWeakAlias.cpp | 56 ++ test/fuzz_test/Fuzzer/FuzzerFlags.def | 115 +++ test/fuzz_test/Fuzzer/FuzzerIO.cpp | 117 +++ test/fuzz_test/Fuzzer/FuzzerIO.h | 64 ++ test/fuzz_test/Fuzzer/FuzzerIOPosix.cpp | 88 ++ test/fuzz_test/Fuzzer/FuzzerIOWindows.cpp | 282 +++++++ test/fuzz_test/Fuzzer/FuzzerInterface.h | 67 ++ test/fuzz_test/Fuzzer/FuzzerInternal.h | 182 ++++ test/fuzz_test/Fuzzer/FuzzerLoop.cpp | 792 ++++++++++++++++++ test/fuzz_test/Fuzzer/FuzzerMain.cpp | 21 + test/fuzz_test/Fuzzer/FuzzerMerge.cpp | 261 ++++++ test/fuzz_test/Fuzzer/FuzzerMerge.h | 70 ++ test/fuzz_test/Fuzzer/FuzzerMutate.cpp | 527 ++++++++++++ test/fuzz_test/Fuzzer/FuzzerMutate.h | 145 ++++ test/fuzz_test/Fuzzer/FuzzerOptions.h | 68 ++ test/fuzz_test/Fuzzer/FuzzerRandom.h | 36 + test/fuzz_test/Fuzzer/FuzzerSHA1.cpp | 222 +++++ test/fuzz_test/Fuzzer/FuzzerSHA1.h | 33 + test/fuzz_test/Fuzzer/FuzzerTracePC.cpp | 339 ++++++++ test/fuzz_test/Fuzzer/FuzzerTracePC.h | 158 ++++ test/fuzz_test/Fuzzer/FuzzerTraceState.cpp | 325 +++++++ test/fuzz_test/Fuzzer/FuzzerUtil.cpp | 218 +++++ test/fuzz_test/Fuzzer/FuzzerUtil.h | 72 ++ test/fuzz_test/Fuzzer/FuzzerUtilDarwin.cpp | 152 ++++ test/fuzz_test/Fuzzer/FuzzerUtilLinux.cpp | 24 + test/fuzz_test/Fuzzer/FuzzerUtilPosix.cpp | 117 +++ test/fuzz_test/Fuzzer/FuzzerUtilWindows.cpp | 182 ++++ test/fuzz_test/Fuzzer/FuzzerValueBitMap.h | 87 ++ test/fuzz_test/Fuzzer/README.txt | 2 + test/fuzz_test/Fuzzer/afl/afl_driver.cpp | 295 +++++++ test/fuzz_test/Fuzzer/build.sh | 10 + test/fuzz_test/Fuzzer/cxx.dict | 122 +++ .../standalone/StandaloneFuzzTargetMain.c | 41 + test/fuzz_test/Fuzzer/test/AFLDriverTest.cpp | 22 + .../Fuzzer/test/AbsNegAndConstant64Test.cpp | 23 + .../Fuzzer/test/AbsNegAndConstantTest.cpp | 23 + .../Fuzzer/test/AccumulateAllocationsTest.cpp | 17 + .../Fuzzer/test/BufferOverflowOnInput.cpp | 23 + test/fuzz_test/Fuzzer/test/CMakeLists.txt | 217 +++++ .../Fuzzer/test/CallerCalleeTest.cpp | 59 ++ test/fuzz_test/Fuzzer/test/CounterTest.cpp | 18 + .../Fuzzer/test/CustomCrossOverTest.cpp | 63 ++ .../Fuzzer/test/CustomMutatorTest.cpp | 38 + test/fuzz_test/Fuzzer/test/DSO1.cpp | 12 + test/fuzz_test/Fuzzer/test/DSO2.cpp | 12 + test/fuzz_test/Fuzzer/test/DSOTestExtra.cpp | 11 + test/fuzz_test/Fuzzer/test/DSOTestMain.cpp | 31 + test/fuzz_test/Fuzzer/test/DivTest.cpp | 20 + test/fuzz_test/Fuzzer/test/EmptyTest.cpp | 11 + .../test/FourIndependentBranchesTest.cpp | 22 + .../Fuzzer/test/FullCoverageSetTest.cpp | 24 + test/fuzz_test/Fuzzer/test/FuzzerUnittest.cpp | 738 ++++++++++++++++ test/fuzz_test/Fuzzer/test/InitializeTest.cpp | 28 + test/fuzz_test/Fuzzer/test/LeakTest.cpp | 17 + .../fuzz_test/Fuzzer/test/LeakTimeoutTest.cpp | 17 + test/fuzz_test/Fuzzer/test/LoadTest.cpp | 22 + test/fuzz_test/Fuzzer/test/MemcmpTest.cpp | 31 + .../fuzz_test/Fuzzer/test/NthRunCrashTest.cpp | 18 + .../Fuzzer/test/NullDerefOnEmptyTest.cpp | 19 + test/fuzz_test/Fuzzer/test/NullDerefTest.cpp | 26 + .../Fuzzer/test/OneHugeAllocTest.cpp | 28 + .../test/OutOfMemorySingleLargeMallocTest.cpp | 27 + .../fuzz_test/Fuzzer/test/OutOfMemoryTest.cpp | 31 + .../Fuzzer/test/RepeatedBytesTest.cpp | 29 + test/fuzz_test/Fuzzer/test/RepeatedMemcmp.cpp | 22 + .../Fuzzer/test/ShrinkControlFlowTest.cpp | 28 + .../Fuzzer/test/ShrinkValueProfileTest.cpp | 22 + .../Fuzzer/test/SignedIntOverflowTest.cpp | 28 + test/fuzz_test/Fuzzer/test/SimpleCmpTest.cpp | 46 + .../Fuzzer/test/SimpleDictionaryTest.cpp | 29 + test/fuzz_test/Fuzzer/test/SimpleHashTest.cpp | 40 + test/fuzz_test/Fuzzer/test/SimpleTest.cpp | 27 + .../Fuzzer/test/SimpleThreadedTest.cpp | 25 + .../Fuzzer/test/SingleMemcmpTest.cpp | 17 + .../Fuzzer/test/SingleStrcmpTest.cpp | 17 + .../Fuzzer/test/SingleStrncmpTest.cpp | 17 + test/fuzz_test/Fuzzer/test/SpamyTest.cpp | 21 + test/fuzz_test/Fuzzer/test/StrcmpTest.cpp | 32 + test/fuzz_test/Fuzzer/test/StrncmpOOBTest.cpp | 21 + test/fuzz_test/Fuzzer/test/StrncmpTest.cpp | 28 + test/fuzz_test/Fuzzer/test/StrstrTest.cpp | 28 + test/fuzz_test/Fuzzer/test/SwapCmpTest.cpp | 34 + test/fuzz_test/Fuzzer/test/Switch2Test.cpp | 35 + test/fuzz_test/Fuzzer/test/SwitchTest.cpp | 58 ++ .../Fuzzer/test/ThreadedLeakTest.cpp | 18 + test/fuzz_test/Fuzzer/test/ThreadedTest.cpp | 26 + .../Fuzzer/test/TimeoutEmptyTest.cpp | 14 + test/fuzz_test/Fuzzer/test/TimeoutTest.cpp | 26 + .../fuzz_test/Fuzzer/test/TraceMallocTest.cpp | 27 + .../Fuzzer/test/UninstrumentedTest.cpp | 11 + .../Fuzzer/test/afl-driver-extra-stats.test | 28 + .../Fuzzer/test/afl-driver-stderr.test | 10 + test/fuzz_test/Fuzzer/test/caller-callee.test | 2 + test/fuzz_test/Fuzzer/test/coverage.test | 19 + test/fuzz_test/Fuzzer/test/dict1.txt | 4 + test/fuzz_test/Fuzzer/test/dump_coverage.test | 16 + .../Fuzzer/test/fuzzer-customcrossover.test | 10 + .../Fuzzer/test/fuzzer-custommutator.test | 4 + test/fuzz_test/Fuzzer/test/fuzzer-dict.test | 6 + test/fuzz_test/Fuzzer/test/fuzzer-dirs.test | 15 + test/fuzz_test/Fuzzer/test/fuzzer-fdmask.test | 30 + .../Fuzzer/test/fuzzer-finalstats.test | 11 + test/fuzz_test/Fuzzer/test/fuzzer-flags.test | 10 + test/fuzz_test/Fuzzer/test/fuzzer-jobs.test | 29 + test/fuzz_test/Fuzzer/test/fuzzer-leak.test | 35 + .../Fuzzer/test/fuzzer-oom-with-profile.test | 6 + test/fuzz_test/Fuzzer/test/fuzzer-oom.test | 11 + .../Fuzzer/test/fuzzer-printcovpcs.test | 8 + test/fuzz_test/Fuzzer/test/fuzzer-runs.test | 8 + test/fuzz_test/Fuzzer/test/fuzzer-seed.test | 3 + test/fuzz_test/Fuzzer/test/fuzzer-segv.test | 5 + .../Fuzzer/test/fuzzer-singleinputs.test | 16 + .../Fuzzer/test/fuzzer-threaded.test | 7 + .../fuzz_test/Fuzzer/test/fuzzer-timeout.test | 19 + .../Fuzzer/test/fuzzer-traces-hooks.test | 25 + test/fuzz_test/Fuzzer/test/fuzzer-ubsan.test | 4 + test/fuzz_test/Fuzzer/test/fuzzer.test | 57 ++ test/fuzz_test/Fuzzer/test/hi.txt | 1 + test/fuzz_test/Fuzzer/test/lit.cfg | 29 + test/fuzz_test/Fuzzer/test/lit.site.cfg.in | 4 + test/fuzz_test/Fuzzer/test/merge.test | 46 + .../fuzz_test/Fuzzer/test/minimize_crash.test | 6 + .../Fuzzer/test/no-coverage/CMakeLists.txt | 29 + .../fuzz_test/Fuzzer/test/repeated-bytes.test | 2 + test/fuzz_test/Fuzzer/test/shrink.test | 7 + test/fuzz_test/Fuzzer/test/simple-cmp.test | 2 + test/fuzz_test/Fuzzer/test/standalone.test | 4 + test/fuzz_test/Fuzzer/test/swap-cmp.test | 2 + test/fuzz_test/Fuzzer/test/trace-malloc.test | 10 + .../Fuzzer/test/ubsan/CMakeLists.txt | 15 + test/fuzz_test/Fuzzer/test/ulimit.test | 2 + .../Fuzzer/test/uninstrumented/CMakeLists.txt | 16 + test/fuzz_test/Fuzzer/test/unit/lit.cfg | 7 + .../Fuzzer/test/unit/lit.site.cfg.in | 2 + .../Fuzzer/test/value-profile-cmp.test | 2 + .../Fuzzer/test/value-profile-cmp2.test | 2 + .../Fuzzer/test/value-profile-cmp3.test | 2 + .../Fuzzer/test/value-profile-cmp4.test | 2 + .../Fuzzer/test/value-profile-div.test | 3 + .../Fuzzer/test/value-profile-load.test | 3 + .../Fuzzer/test/value-profile-mem.test | 2 + .../Fuzzer/test/value-profile-set.test | 3 + .../Fuzzer/test/value-profile-strcmp.test | 2 + .../Fuzzer/test/value-profile-strncmp.test | 2 + .../Fuzzer/test/value-profile-switch.test | 3 + 156 files changed, 9535 insertions(+) create mode 100644 test/fuzz_test/Fuzzer/CMakeLists.txt create mode 100644 test/fuzz_test/Fuzzer/FuzzerCorpus.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerCrossOver.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerDefs.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerDictionary.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerDriver.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerExtFunctions.def create mode 100644 test/fuzz_test/Fuzzer/FuzzerExtFunctions.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerExtFunctionsDlsym.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeak.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerFlags.def create mode 100644 test/fuzz_test/Fuzzer/FuzzerIO.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerIO.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerIOPosix.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerIOWindows.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerInterface.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerInternal.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerLoop.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerMain.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerMerge.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerMerge.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerMutate.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerMutate.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerOptions.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerRandom.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerSHA1.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerSHA1.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerTracePC.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerTracePC.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerTraceState.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerUtil.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerUtil.h create mode 100644 test/fuzz_test/Fuzzer/FuzzerUtilDarwin.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerUtilLinux.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerUtilPosix.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerUtilWindows.cpp create mode 100644 test/fuzz_test/Fuzzer/FuzzerValueBitMap.h create mode 100644 test/fuzz_test/Fuzzer/README.txt create mode 100644 test/fuzz_test/Fuzzer/afl/afl_driver.cpp create mode 100755 test/fuzz_test/Fuzzer/build.sh create mode 100644 test/fuzz_test/Fuzzer/cxx.dict create mode 100644 test/fuzz_test/Fuzzer/standalone/StandaloneFuzzTargetMain.c create mode 100644 test/fuzz_test/Fuzzer/test/AFLDriverTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/AbsNegAndConstant64Test.cpp create mode 100644 test/fuzz_test/Fuzzer/test/AbsNegAndConstantTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/AccumulateAllocationsTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/BufferOverflowOnInput.cpp create mode 100644 test/fuzz_test/Fuzzer/test/CMakeLists.txt create mode 100644 test/fuzz_test/Fuzzer/test/CallerCalleeTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/CounterTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/CustomCrossOverTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/CustomMutatorTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/DSO1.cpp create mode 100644 test/fuzz_test/Fuzzer/test/DSO2.cpp create mode 100644 test/fuzz_test/Fuzzer/test/DSOTestExtra.cpp create mode 100644 test/fuzz_test/Fuzzer/test/DSOTestMain.cpp create mode 100644 test/fuzz_test/Fuzzer/test/DivTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/EmptyTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/FourIndependentBranchesTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/FullCoverageSetTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/FuzzerUnittest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/InitializeTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/LeakTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/LeakTimeoutTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/LoadTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/MemcmpTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/NthRunCrashTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/NullDerefOnEmptyTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/NullDerefTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/OneHugeAllocTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/OutOfMemoryTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/RepeatedBytesTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/RepeatedMemcmp.cpp create mode 100644 test/fuzz_test/Fuzzer/test/ShrinkControlFlowTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/ShrinkValueProfileTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SignedIntOverflowTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SimpleCmpTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SimpleDictionaryTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SimpleHashTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SimpleTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SimpleThreadedTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SingleMemcmpTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SingleStrcmpTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SingleStrncmpTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SpamyTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/StrcmpTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/StrncmpOOBTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/StrncmpTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/StrstrTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SwapCmpTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/Switch2Test.cpp create mode 100644 test/fuzz_test/Fuzzer/test/SwitchTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/ThreadedLeakTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/ThreadedTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/TimeoutEmptyTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/TimeoutTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/TraceMallocTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/UninstrumentedTest.cpp create mode 100644 test/fuzz_test/Fuzzer/test/afl-driver-extra-stats.test create mode 100644 test/fuzz_test/Fuzzer/test/afl-driver-stderr.test create mode 100644 test/fuzz_test/Fuzzer/test/caller-callee.test create mode 100644 test/fuzz_test/Fuzzer/test/coverage.test create mode 100644 test/fuzz_test/Fuzzer/test/dict1.txt create mode 100644 test/fuzz_test/Fuzzer/test/dump_coverage.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-customcrossover.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-custommutator.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-dict.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-dirs.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-fdmask.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-finalstats.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-flags.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-jobs.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-leak.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-oom-with-profile.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-oom.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-printcovpcs.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-runs.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-seed.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-segv.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-singleinputs.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-threaded.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-timeout.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-traces-hooks.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer-ubsan.test create mode 100644 test/fuzz_test/Fuzzer/test/fuzzer.test create mode 100644 test/fuzz_test/Fuzzer/test/hi.txt create mode 100644 test/fuzz_test/Fuzzer/test/lit.cfg create mode 100644 test/fuzz_test/Fuzzer/test/lit.site.cfg.in create mode 100644 test/fuzz_test/Fuzzer/test/merge.test create mode 100644 test/fuzz_test/Fuzzer/test/minimize_crash.test create mode 100644 test/fuzz_test/Fuzzer/test/no-coverage/CMakeLists.txt create mode 100644 test/fuzz_test/Fuzzer/test/repeated-bytes.test create mode 100644 test/fuzz_test/Fuzzer/test/shrink.test create mode 100644 test/fuzz_test/Fuzzer/test/simple-cmp.test create mode 100644 test/fuzz_test/Fuzzer/test/standalone.test create mode 100644 test/fuzz_test/Fuzzer/test/swap-cmp.test create mode 100644 test/fuzz_test/Fuzzer/test/trace-malloc.test create mode 100644 test/fuzz_test/Fuzzer/test/ubsan/CMakeLists.txt create mode 100644 test/fuzz_test/Fuzzer/test/ulimit.test create mode 100644 test/fuzz_test/Fuzzer/test/uninstrumented/CMakeLists.txt create mode 100644 test/fuzz_test/Fuzzer/test/unit/lit.cfg create mode 100644 test/fuzz_test/Fuzzer/test/unit/lit.site.cfg.in create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-cmp.test create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-cmp2.test create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-cmp3.test create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-cmp4.test create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-div.test create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-load.test create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-mem.test create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-set.test create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-strcmp.test create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-strncmp.test create mode 100644 test/fuzz_test/Fuzzer/test/value-profile-switch.test diff --git a/.gitignore b/.gitignore index 42a18e82..099cad5c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ cmake-build-debug test/test-* +test/fuzz_test/Fuzzer/.svn diff --git a/test/fuzz_test/Fuzzer/CMakeLists.txt b/test/fuzz_test/Fuzzer/CMakeLists.txt new file mode 100644 index 00000000..70bd017b --- /dev/null +++ b/test/fuzz_test/Fuzzer/CMakeLists.txt @@ -0,0 +1,45 @@ +set(LIBFUZZER_FLAGS_BASE "${CMAKE_CXX_FLAGS}") +# Disable the coverage and sanitizer instrumentation for the fuzzer itself. +set(CMAKE_CXX_FLAGS "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=trace-pc-guard,edge,trace-cmp,indirect-calls,8bit-counters -Werror") +if( LLVM_USE_SANITIZE_COVERAGE ) + if(NOT "${LLVM_USE_SANITIZER}" STREQUAL "Address") + message(FATAL_ERROR + "LibFuzzer and its tests require LLVM_USE_SANITIZER=Address and " + "LLVM_USE_SANITIZE_COVERAGE=YES to be set." + ) + endif() + add_library(LLVMFuzzerNoMainObjects OBJECT + FuzzerCrossOver.cpp + FuzzerDriver.cpp + FuzzerExtFunctionsDlsym.cpp + FuzzerExtFunctionsWeak.cpp + FuzzerExtFunctionsWeakAlias.cpp + FuzzerIO.cpp + FuzzerIOPosix.cpp + FuzzerIOWindows.cpp + FuzzerLoop.cpp + FuzzerMerge.cpp + FuzzerMutate.cpp + FuzzerSHA1.cpp + FuzzerTracePC.cpp + FuzzerTraceState.cpp + FuzzerUtil.cpp + FuzzerUtilDarwin.cpp + FuzzerUtilLinux.cpp + FuzzerUtilPosix.cpp + FuzzerUtilWindows.cpp + ) + add_library(LLVMFuzzerNoMain STATIC + $<TARGET_OBJECTS:LLVMFuzzerNoMainObjects> + ) + target_link_libraries(LLVMFuzzerNoMain ${PTHREAD_LIB}) + add_library(LLVMFuzzer STATIC + FuzzerMain.cpp + $<TARGET_OBJECTS:LLVMFuzzerNoMainObjects> + ) + target_link_libraries(LLVMFuzzer ${PTHREAD_LIB}) + + if( LLVM_INCLUDE_TESTS ) + add_subdirectory(test) + endif() +endif() diff --git a/test/fuzz_test/Fuzzer/FuzzerCorpus.h b/test/fuzz_test/Fuzzer/FuzzerCorpus.h new file mode 100644 index 00000000..663c5854 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerCorpus.h @@ -0,0 +1,217 @@ +//===- FuzzerCorpus.h - Internal header for the Fuzzer ----------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// fuzzer::InputCorpus +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_CORPUS +#define LLVM_FUZZER_CORPUS + +#include "FuzzerDefs.h" +#include "FuzzerIO.h" +#include "FuzzerRandom.h" +#include "FuzzerSHA1.h" +#include "FuzzerTracePC.h" +#include <numeric> +#include <random> +#include <unordered_set> + +namespace fuzzer { + +struct InputInfo { + Unit U; // The actual input data. + uint8_t Sha1[kSHA1NumBytes]; // Checksum. + // Number of features that this input has and no smaller input has. + size_t NumFeatures = 0; + size_t Tmp = 0; // Used by ValidateFeatureSet. + // Stats. + size_t NumExecutedMutations = 0; + size_t NumSuccessfullMutations = 0; + bool MayDeleteFile = false; +}; + +class InputCorpus { + public: + static const size_t kFeatureSetSize = 1 << 16; + InputCorpus(const std::string &OutputCorpus) : OutputCorpus(OutputCorpus) { + memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature)); + memset(SmallestElementPerFeature, 0, sizeof(SmallestElementPerFeature)); + } + ~InputCorpus() { + for (auto II : Inputs) + delete II; + } + size_t size() const { return Inputs.size(); } + size_t SizeInBytes() const { + size_t Res = 0; + for (auto II : Inputs) + Res += II->U.size(); + return Res; + } + size_t NumActiveUnits() const { + size_t Res = 0; + for (auto II : Inputs) + Res += !II->U.empty(); + return Res; + } + bool empty() const { return Inputs.empty(); } + const Unit &operator[] (size_t Idx) const { return Inputs[Idx]->U; } + void AddToCorpus(const Unit &U, size_t NumFeatures, bool MayDeleteFile = false) { + assert(!U.empty()); + uint8_t Hash[kSHA1NumBytes]; + if (FeatureDebug) + Printf("ADD_TO_CORPUS %zd NF %zd\n", Inputs.size(), NumFeatures); + ComputeSHA1(U.data(), U.size(), Hash); + Hashes.insert(Sha1ToString(Hash)); + Inputs.push_back(new InputInfo()); + InputInfo &II = *Inputs.back(); + II.U = U; + II.NumFeatures = NumFeatures; + II.MayDeleteFile = MayDeleteFile; + memcpy(II.Sha1, Hash, kSHA1NumBytes); + UpdateCorpusDistribution(); + ValidateFeatureSet(); + } + + bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); } + bool HasUnit(const std::string &H) { return Hashes.count(H); } + InputInfo &ChooseUnitToMutate(Random &Rand) { + InputInfo &II = *Inputs[ChooseUnitIdxToMutate(Rand)]; + assert(!II.U.empty()); + return II; + }; + + // Returns an index of random unit from the corpus to mutate. + // Hypothesis: units added to the corpus last are more likely to be + // interesting. This function gives more weight to the more recent units. + size_t ChooseUnitIdxToMutate(Random &Rand) { + size_t Idx = static_cast<size_t>(CorpusDistribution(Rand.Get_mt19937())); + assert(Idx < Inputs.size()); + return Idx; + } + + void PrintStats() { + for (size_t i = 0; i < Inputs.size(); i++) { + const auto &II = *Inputs[i]; + Printf(" [%zd %s]\tsz: %zd\truns: %zd\tsucc: %zd\n", i, + Sha1ToString(II.Sha1).c_str(), II.U.size(), + II.NumExecutedMutations, II.NumSuccessfullMutations); + } + } + + void PrintFeatureSet() { + for (size_t i = 0; i < kFeatureSetSize; i++) { + if(size_t Sz = GetFeature(i)) + Printf("[%zd: id %zd sz%zd] ", i, SmallestElementPerFeature[i], Sz); + } + Printf("\n\t"); + for (size_t i = 0; i < Inputs.size(); i++) + if (size_t N = Inputs[i]->NumFeatures) + Printf(" %zd=>%zd ", i, N); + Printf("\n"); + } + + void DeleteInput(size_t Idx) { + InputInfo &II = *Inputs[Idx]; + if (!OutputCorpus.empty() && II.MayDeleteFile) + RemoveFile(DirPlusFile(OutputCorpus, Sha1ToString(II.Sha1))); + Unit().swap(II.U); + if (FeatureDebug) + Printf("EVICTED %zd\n", Idx); + } + + bool AddFeature(size_t Idx, uint32_t NewSize, bool Shrink) { + assert(NewSize); + Idx = Idx % kFeatureSetSize; + uint32_t OldSize = GetFeature(Idx); + if (OldSize == 0 || (Shrink && OldSize > NewSize)) { + if (OldSize > 0) { + size_t OldIdx = SmallestElementPerFeature[Idx]; + InputInfo &II = *Inputs[OldIdx]; + assert(II.NumFeatures > 0); + II.NumFeatures--; + if (II.NumFeatures == 0) + DeleteInput(OldIdx); + } + if (FeatureDebug) + Printf("ADD FEATURE %zd sz %d\n", Idx, NewSize); + SmallestElementPerFeature[Idx] = Inputs.size(); + InputSizesPerFeature[Idx] = NewSize; + CountingFeatures = true; + return true; + } + return false; + } + + size_t NumFeatures() const { + size_t Res = 0; + for (size_t i = 0; i < kFeatureSetSize; i++) + Res += GetFeature(i) != 0; + return Res; + } + + void ResetFeatureSet() { + assert(Inputs.empty()); + memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature)); + memset(SmallestElementPerFeature, 0, sizeof(SmallestElementPerFeature)); + } + +private: + + static const bool FeatureDebug = false; + + size_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; } + + void ValidateFeatureSet() { + if (!CountingFeatures) return; + if (FeatureDebug) + PrintFeatureSet(); + for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++) + if (GetFeature(Idx)) + Inputs[SmallestElementPerFeature[Idx]]->Tmp++; + for (auto II: Inputs) { + if (II->Tmp != II->NumFeatures) + Printf("ZZZ %zd %zd\n", II->Tmp, II->NumFeatures); + assert(II->Tmp == II->NumFeatures); + II->Tmp = 0; + } + } + + // Updates the probability distribution for the units in the corpus. + // Must be called whenever the corpus or unit weights are changed. + void UpdateCorpusDistribution() { + size_t N = Inputs.size(); + Intervals.resize(N + 1); + Weights.resize(N); + std::iota(Intervals.begin(), Intervals.end(), 0); + if (CountingFeatures) + for (size_t i = 0; i < N; i++) + Weights[i] = Inputs[i]->NumFeatures * (i + 1); + else + std::iota(Weights.begin(), Weights.end(), 1); + CorpusDistribution = std::piecewise_constant_distribution<double>( + Intervals.begin(), Intervals.end(), Weights.begin()); + } + std::piecewise_constant_distribution<double> CorpusDistribution; + + std::vector<double> Intervals; + std::vector<double> Weights; + + std::unordered_set<std::string> Hashes; + std::vector<InputInfo*> Inputs; + + bool CountingFeatures = false; + uint32_t InputSizesPerFeature[kFeatureSetSize]; + uint32_t SmallestElementPerFeature[kFeatureSetSize]; + + std::string OutputCorpus; +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_CORPUS diff --git a/test/fuzz_test/Fuzzer/FuzzerCrossOver.cpp b/test/fuzz_test/Fuzzer/FuzzerCrossOver.cpp new file mode 100644 index 00000000..8b0fd7d5 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerCrossOver.cpp @@ -0,0 +1,52 @@ +//===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Cross over test inputs. +//===----------------------------------------------------------------------===// + +#include "FuzzerDefs.h" +#include "FuzzerMutate.h" +#include "FuzzerRandom.h" +#include <cstring> + +namespace fuzzer { + +// Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out. +size_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1, + const uint8_t *Data2, size_t Size2, + uint8_t *Out, size_t MaxOutSize) { + assert(Size1 || Size2); + MaxOutSize = Rand(MaxOutSize) + 1; + size_t OutPos = 0; + size_t Pos1 = 0; + size_t Pos2 = 0; + size_t *InPos = &Pos1; + size_t InSize = Size1; + const uint8_t *Data = Data1; + bool CurrentlyUsingFirstData = true; + while (OutPos < MaxOutSize && (Pos1 < Size1 || Pos2 < Size2)) { + // Merge a part of Data into Out. + size_t OutSizeLeft = MaxOutSize - OutPos; + if (*InPos < InSize) { + size_t InSizeLeft = InSize - *InPos; + size_t MaxExtraSize = std::min(OutSizeLeft, InSizeLeft); + size_t ExtraSize = Rand(MaxExtraSize) + 1; + memcpy(Out + OutPos, Data + *InPos, ExtraSize); + OutPos += ExtraSize; + (*InPos) += ExtraSize; + } + // Use the other input data on the next iteration. + InPos = CurrentlyUsingFirstData ? &Pos2 : &Pos1; + InSize = CurrentlyUsingFirstData ? Size2 : Size1; + Data = CurrentlyUsingFirstData ? Data2 : Data1; + CurrentlyUsingFirstData = !CurrentlyUsingFirstData; + } + return OutPos; +} + +} // namespace fuzzer diff --git a/test/fuzz_test/Fuzzer/FuzzerDefs.h b/test/fuzz_test/Fuzzer/FuzzerDefs.h new file mode 100644 index 00000000..0f5b8a7c --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerDefs.h @@ -0,0 +1,89 @@ +//===- FuzzerDefs.h - Internal header for the Fuzzer ------------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Basic definitions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_DEFS_H +#define LLVM_FUZZER_DEFS_H + +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <string> +#include <vector> + +// Platform detection. +#ifdef __linux__ +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_LINUX 1 +#define LIBFUZZER_WINDOWS 0 +#elif __APPLE__ +#define LIBFUZZER_APPLE 1 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_WINDOWS 0 +#elif _WIN32 +#define LIBFUZZER_APPLE 0 +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_WINDOWS 1 +#else +#error "Support for your platform has not been implemented" +#endif + +#define LIBFUZZER_POSIX LIBFUZZER_APPLE || LIBFUZZER_LINUX + +#ifdef __x86_64 +#define ATTRIBUTE_TARGET_POPCNT __attribute__((target("popcnt"))) +#else +#define ATTRIBUTE_TARGET_POPCNT +#endif + + +#ifdef __clang__ // avoid gcc warning. +# define ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) +#else +# define ATTRIBUTE_NO_SANITIZE_MEMORY +#endif + +namespace fuzzer { + +template <class T> T Min(T a, T b) { return a < b ? a : b; } +template <class T> T Max(T a, T b) { return a > b ? a : b; } + +class Random; +class Dictionary; +class DictionaryEntry; +class MutationDispatcher; +struct FuzzingOptions; +class InputCorpus; +struct InputInfo; +struct ExternalFunctions; + +// Global interface to functions that may or may not be available. +extern ExternalFunctions *EF; + +typedef std::vector<uint8_t> Unit; +typedef std::vector<Unit> UnitVector; +typedef int (*UserCallback)(const uint8_t *Data, size_t Size); + +int FuzzerDriver(int *argc, char ***argv, UserCallback Callback); + +struct ScopedDoingMyOwnMemmem { + ScopedDoingMyOwnMemmem(); + ~ScopedDoingMyOwnMemmem(); +}; + +inline uint8_t Bswap(uint8_t x) { return x; } +inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); } +inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); } +inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); } + +} // namespace fuzzer + +#endif // LLVM_FUZZER_DEFS_H diff --git a/test/fuzz_test/Fuzzer/FuzzerDictionary.h b/test/fuzz_test/Fuzzer/FuzzerDictionary.h new file mode 100644 index 00000000..eba0eabb --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerDictionary.h @@ -0,0 +1,124 @@ +//===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// fuzzer::Dictionary +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_DICTIONARY_H +#define LLVM_FUZZER_DICTIONARY_H + +#include "FuzzerDefs.h" +#include "FuzzerIO.h" +#include "FuzzerUtil.h" +#include <algorithm> +#include <limits> + +namespace fuzzer { +// A simple POD sized array of bytes. +template <size_t kMaxSize> class FixedWord { +public: + FixedWord() {} + FixedWord(const uint8_t *B, uint8_t S) { Set(B, S); } + + void Set(const uint8_t *B, uint8_t S) { + assert(S <= kMaxSize); + memcpy(Data, B, S); + Size = S; + } + + bool operator==(const FixedWord<kMaxSize> &w) const { + return Size == w.Size && 0 == memcmp(Data, w.Data, Size); + } + + bool operator<(const FixedWord<kMaxSize> &w) const { + if (Size != w.Size) + return Size < w.Size; + return memcmp(Data, w.Data, Size) < 0; + } + + static size_t GetMaxSize() { return kMaxSize; } + const uint8_t *data() const { return Data; } + uint8_t size() const { return Size; } + +private: + uint8_t Size = 0; + uint8_t Data[kMaxSize]; +}; + +typedef FixedWord<27> Word; // 28 bytes. + +class DictionaryEntry { + public: + DictionaryEntry() {} + DictionaryEntry(Word W) : W(W) {} + DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {} + const Word &GetW() const { return W; } + + bool HasPositionHint() const { return PositionHint != std::numeric_limits<size_t>::max(); } + size_t GetPositionHint() const { + assert(HasPositionHint()); + return PositionHint; + } + void IncUseCount() { UseCount++; } + void IncSuccessCount() { SuccessCount++; } + size_t GetUseCount() const { return UseCount; } + size_t GetSuccessCount() const {return SuccessCount; } + + void Print(const char *PrintAfter = "\n") { + PrintASCII(W.data(), W.size()); + if (HasPositionHint()) + Printf("@%zd", GetPositionHint()); + Printf("%s", PrintAfter); + } + +private: + Word W; + size_t PositionHint = std::numeric_limits<size_t>::max(); + size_t UseCount = 0; + size_t SuccessCount = 0; +}; + +class Dictionary { + public: + static const size_t kMaxDictSize = 1 << 14; + + bool ContainsWord(const Word &W) const { + return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) { + return DE.GetW() == W; + }); + } + const DictionaryEntry *begin() const { return &DE[0]; } + const DictionaryEntry *end() const { return begin() + Size; } + DictionaryEntry & operator[] (size_t Idx) { + assert(Idx < Size); + return DE[Idx]; + } + void push_back(DictionaryEntry DE) { + if (Size < kMaxDictSize) + this->DE[Size++] = DE; + } + void clear() { Size = 0; } + bool empty() const { return Size == 0; } + size_t size() const { return Size; } + +private: + DictionaryEntry DE[kMaxDictSize]; + size_t Size = 0; +}; + +// Parses one dictionary entry. +// If successfull, write the enty to Unit and returns true, +// otherwise returns false. +bool ParseOneDictionaryEntry(const std::string &Str, Unit *U); +// Parses the dictionary file, fills Units, returns true iff all lines +// were parsed succesfully. +bool ParseDictionaryFile(const std::string &Text, std::vector<Unit> *Units); + +} // namespace fuzzer + +#endif // LLVM_FUZZER_DICTIONARY_H diff --git a/test/fuzz_test/Fuzzer/FuzzerDriver.cpp b/test/fuzz_test/Fuzzer/FuzzerDriver.cpp new file mode 100644 index 00000000..95b0721c --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerDriver.cpp @@ -0,0 +1,545 @@ +//===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// FuzzerDriver and flag parsing. +//===----------------------------------------------------------------------===// + +#include "FuzzerCorpus.h" +#include "FuzzerInterface.h" +#include "FuzzerInternal.h" +#include "FuzzerIO.h" +#include "FuzzerMutate.h" +#include "FuzzerRandom.h" +#include "FuzzerTracePC.h" +#include <algorithm> +#include <atomic> +#include <chrono> +#include <cstring> +#include <mutex> +#include <string> +#include <thread> + +// This function should be present in the libFuzzer so that the client +// binary can test for its existence. +extern "C" __attribute__((used)) void __libfuzzer_is_present() {} + +namespace fuzzer { + +// Program arguments. +struct FlagDescription { + const char *Name; + const char *Description; + int Default; + int *IntFlag; + const char **StrFlag; + unsigned int *UIntFlag; +}; + +struct { +#define FUZZER_DEPRECATED_FLAG(Name) +#define FUZZER_FLAG_INT(Name, Default, Description) int Name; +#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) unsigned int Name; +#define FUZZER_FLAG_STRING(Name, Description) const char *Name; +#include "FuzzerFlags.def" +#undef FUZZER_DEPRECATED_FLAG +#undef FUZZER_FLAG_INT +#undef FUZZER_FLAG_UNSIGNED +#undef FUZZER_FLAG_STRING +} Flags; + +static const FlagDescription FlagDescriptions [] { +#define FUZZER_DEPRECATED_FLAG(Name) \ + {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr}, +#define FUZZER_FLAG_INT(Name, Default, Description) \ + {#Name, Description, Default, &Flags.Name, nullptr, nullptr}, +#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) \ + {#Name, Description, static_cast<int>(Default), \ + nullptr, nullptr, &Flags.Name}, +#define FUZZER_FLAG_STRING(Name, Description) \ + {#Name, Description, 0, nullptr, &Flags.Name, nullptr}, +#include "FuzzerFlags.def" +#undef FUZZER_DEPRECATED_FLAG +#undef FUZZER_FLAG_INT +#undef FUZZER_FLAG_UNSIGNED +#undef FUZZER_FLAG_STRING +}; + +static const size_t kNumFlags = + sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]); + +static std::vector<std::string> *Inputs; +static std::string *ProgName; + +static void PrintHelp() { + Printf("Usage:\n"); + auto Prog = ProgName->c_str(); + Printf("\nTo run fuzzing pass 0 or more directories.\n"); + Printf("%s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n", Prog); + + Printf("\nTo run individual tests without fuzzing pass 1 or more files:\n"); + Printf("%s [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]\n", Prog); + + Printf("\nFlags: (strictly in form -flag=value)\n"); + size_t MaxFlagLen = 0; + for (size_t F = 0; F < kNumFlags; F++) + MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen); + + for (size_t F = 0; F < kNumFlags; F++) { + const auto &D = FlagDescriptions[F]; + if (strstr(D.Description, "internal flag") == D.Description) continue; + Printf(" %s", D.Name); + for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++) + Printf(" "); + Printf("\t"); + Printf("%d\t%s\n", D.Default, D.Description); + } + Printf("\nFlags starting with '--' will be ignored and " + "will be passed verbatim to subprocesses.\n"); +} + +static const char *FlagValue(const char *Param, const char *Name) { + size_t Len = strlen(Name); + if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 && + Param[Len + 1] == '=') + return &Param[Len + 2]; + return nullptr; +} + +// Avoid calling stol as it triggers a bug in clang/glibc build. +static long MyStol(const char *Str) { + long Res = 0; + long Sign = 1; + if (*Str == '-') { + Str++; + Sign = -1; + } + for (size_t i = 0; Str[i]; i++) { + char Ch = Str[i]; + if (Ch < '0' || Ch > '9') + return Res; + Res = Res * 10 + (Ch - '0'); + } + return Res * Sign; +} + +static bool ParseOneFlag(const char *Param) { + if (Param[0] != '-') return false; + if (Param[1] == '-') { + static bool PrintedWarning = false; + if (!PrintedWarning) { + PrintedWarning = true; + Printf("INFO: libFuzzer ignores flags that start with '--'\n"); + } + for (size_t F = 0; F < kNumFlags; F++) + if (FlagValue(Param + 1, FlagDescriptions[F].Name)) + Printf("WARNING: did you mean '%s' (single dash)?\n", Param + 1); + return true; + } + for (size_t F = 0; F < kNumFlags; F++) { + const char *Name = FlagDescriptions[F].Name; + const char *Str = FlagValue(Param, Name); + if (Str) { + if (FlagDescriptions[F].IntFlag) { + int Val = MyStol(Str); + *FlagDescriptions[F].IntFlag = Val; + if (Flags.verbosity >= 2) + Printf("Flag: %s %d\n", Name, Val);; + return true; + } else if (FlagDescriptions[F].UIntFlag) { + unsigned int Val = std::stoul(Str); + *FlagDescriptions[F].UIntFlag = Val; + if (Flags.verbosity >= 2) + Printf("Flag: %s %u\n", Name, Val); + return true; + } else if (FlagDescriptions[F].StrFlag) { + *FlagDescriptions[F].StrFlag = Str; + if (Flags.verbosity >= 2) + Printf("Flag: %s %s\n", Name, Str); + return true; + } else { // Deprecated flag. + Printf("Flag: %s: deprecated, don't use\n", Name); + return true; + } + } + } + Printf("\n\nWARNING: unrecognized flag '%s'; " + "use -help=1 to list all flags\n\n", Param); + return true; +} + +// We don't use any library to minimize dependencies. +static void ParseFlags(const std::vector<std::string> &Args) { + for (size_t F = 0; F < kNumFlags; F++) { + if (FlagDescriptions[F].IntFlag) + *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default; + if (FlagDescriptions[F].UIntFlag) + *FlagDescriptions[F].UIntFlag = + static_cast<unsigned int>(FlagDescriptions[F].Default); + if (FlagDescriptions[F].StrFlag) + *FlagDescriptions[F].StrFlag = nullptr; + } + Inputs = new std::vector<std::string>; + for (size_t A = 1; A < Args.size(); A++) { + if (ParseOneFlag(Args[A].c_str())) continue; + Inputs->push_back(Args[A]); + } +} + +static std::mutex Mu; + +static void PulseThread() { + while (true) { + SleepSeconds(600); + std::lock_guard<std::mutex> Lock(Mu); + Printf("pulse...\n"); + } +} + +static void WorkerThread(const std::string &Cmd, std::atomic<unsigned> *Counter, + unsigned NumJobs, std::atomic<bool> *HasErrors) { + while (true) { + unsigned C = (*Counter)++; + if (C >= NumJobs) break; + std::string Log = "fuzz-" + std::to_string(C) + ".log"; + std::string ToRun = Cmd + " > " + Log + " 2>&1\n"; + if (Flags.verbosity) + Printf("%s", ToRun.c_str()); + int ExitCode = ExecuteCommand(ToRun); + if (ExitCode != 0) + *HasErrors = true; + std::lock_guard<std::mutex> Lock(Mu); + Printf("================== Job %u exited with exit code %d ============\n", + C, ExitCode); + fuzzer::CopyFileToErr(Log); + } +} + +std::string CloneArgsWithoutX(const std::vector<std::string> &Args, + const char *X1, const char *X2) { + std::string Cmd; + for (auto &S : Args) { + if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2)) + continue; + Cmd += S + " "; + } + return Cmd; +} + +static int RunInMultipleProcesses(const std::vector<std::string> &Args, + unsigned NumWorkers, unsigned NumJobs) { + std::atomic<unsigned> Counter(0); + std::atomic<bool> HasErrors(false); + std::string Cmd = CloneArgsWithoutX(Args, "jobs", "workers"); + std::vector<std::thread> V; + std::thread Pulse(PulseThread); + Pulse.detach(); + for (unsigned i = 0; i < NumWorkers; i++) + V.push_back(std::thread(WorkerThread, Cmd, &Counter, NumJobs, &HasErrors)); + for (auto &T : V) + T.join(); + return HasErrors ? 1 : 0; +} + +static void RssThread(Fuzzer *F, size_t RssLimitMb) { + while (true) { + SleepSeconds(1); + size_t Peak = GetPeakRSSMb(); + if (Peak > RssLimitMb) + F->RssLimitCallback(); + } +} + +static void StartRssThread(Fuzzer *F, size_t RssLimitMb) { + if (!RssLimitMb) return; + std::thread T(RssThread, F, RssLimitMb); + T.detach(); +} + +int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) { + Unit U = FileToVector(InputFilePath); + if (MaxLen && MaxLen < U.size()) + U.resize(MaxLen); + F->RunOne(U.data(), U.size()); + F->TryDetectingAMemoryLeak(U.data(), U.size(), true); + return 0; +} + +static bool AllInputsAreFiles() { + if (Inputs->empty()) return false; + for (auto &Path : *Inputs) + if (!IsFile(Path)) + return false; + return true; +} + +int MinimizeCrashInput(const std::vector<std::string> &Args) { + if (Inputs->size() != 1) { + Printf("ERROR: -minimize_crash should be given one input file\n"); + exit(1); + } + std::string InputFilePath = Inputs->at(0); + std::string BaseCmd = + CloneArgsWithoutX(Args, "minimize_crash", "exact_artifact_path"); + auto InputPos = BaseCmd.find(" " + InputFilePath + " "); + assert(InputPos != std::string::npos); + BaseCmd.erase(InputPos, InputFilePath.size() + 1); + if (Flags.runs <= 0 && Flags.max_total_time == 0) { + Printf("INFO: you need to specify -runs=N or " + "-max_total_time=N with -minimize_crash=1\n" + "INFO: defaulting to -max_total_time=600\n"); + BaseCmd += " -max_total_time=600"; + } + // BaseCmd += " > /dev/null 2>&1 "; + + std::string CurrentFilePath = InputFilePath; + while (true) { + Unit U = FileToVector(CurrentFilePath); + if (U.size() < 2) { + Printf("CRASH_MIN: '%s' is small enough\n", CurrentFilePath.c_str()); + return 0; + } + Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n", + CurrentFilePath.c_str(), U.size()); + + auto Cmd = BaseCmd + " " + CurrentFilePath; + + Printf("CRASH_MIN: executing: %s\n", Cmd.c_str()); + int ExitCode = ExecuteCommand(Cmd); + if (ExitCode == 0) { + Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str()); + exit(1); + } + Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize " + "it further\n", + CurrentFilePath.c_str(), U.size()); + + std::string ArtifactPath = "minimized-from-" + Hash(U); + Cmd += " -minimize_crash_internal_step=1 -exact_artifact_path=" + + ArtifactPath; + Printf("CRASH_MIN: executing: %s\n", Cmd.c_str()); + ExitCode = ExecuteCommand(Cmd); + if (ExitCode == 0) { + if (Flags.exact_artifact_path) { + CurrentFilePath = Flags.exact_artifact_path; + WriteToFile(U, CurrentFilePath); + } + Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n", + CurrentFilePath.c_str(), U.size()); + return 0; + } + CurrentFilePath = ArtifactPath; + Printf("\n\n\n\n\n\n*********************************\n"); + } + return 0; +} + +int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) { + assert(Inputs->size() == 1); + std::string InputFilePath = Inputs->at(0); + Unit U = FileToVector(InputFilePath); + assert(U.size() > 2); + Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size()); + Corpus->AddToCorpus(U, 0); + F->SetMaxInputLen(U.size()); + F->SetMaxMutationLen(U.size() - 1); + F->MinimizeCrashLoop(U); + Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n"); + exit(0); + return 0; +} + +int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { + using namespace fuzzer; + assert(argc && argv && "Argument pointers cannot be nullptr"); + EF = new ExternalFunctions(); + if (EF->LLVMFuzzerInitialize) + EF->LLVMFuzzerInitialize(argc, argv); + const std::vector<std::string> Args(*argv, *argv + *argc); + assert(!Args.empty()); + ProgName = new std::string(Args[0]); + ParseFlags(Args); + if (Flags.help) { + PrintHelp(); + return 0; + } + + if (Flags.minimize_crash) + return MinimizeCrashInput(Args); + + if (Flags.close_fd_mask & 2) + DupAndCloseStderr(); + if (Flags.close_fd_mask & 1) + CloseStdout(); + + if (Flags.jobs > 0 && Flags.workers == 0) { + Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs); + if (Flags.workers > 1) + Printf("Running %u workers\n", Flags.workers); + } + + if (Flags.workers > 0 && Flags.jobs > 0) + return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs); + + const size_t kMaxSaneLen = 1 << 20; + const size_t kMinDefaultLen = 64; + FuzzingOptions Options; + Options.Verbosity = Flags.verbosity; + Options.MaxLen = Flags.max_len; + Options.UnitTimeoutSec = Flags.timeout; + Options.ErrorExitCode = Flags.error_exitcode; + Options.TimeoutExitCode = Flags.timeout_exitcode; + Options.MaxTotalTimeSec = Flags.max_total_time; + Options.DoCrossOver = Flags.cross_over; + Options.MutateDepth = Flags.mutate_depth; + Options.UseCounters = Flags.use_counters; + Options.UseIndirCalls = Flags.use_indir_calls; + Options.UseMemcmp = Flags.use_memcmp; + Options.UseMemmem = Flags.use_memmem; + Options.UseCmp = Flags.use_cmp; + Options.UseValueProfile = Flags.use_value_profile; + Options.Shrink = Flags.shrink; + Options.ShuffleAtStartUp = Flags.shuffle; + Options.PreferSmall = Flags.prefer_small; + Options.ReloadIntervalSec = Flags.reload; + Options.OnlyASCII = Flags.only_ascii; + Options.OutputCSV = Flags.output_csv; + Options.DetectLeaks = Flags.detect_leaks; + Options.TraceMalloc = Flags.trace_malloc; + Options.RssLimitMb = Flags.rss_limit_mb; + if (Flags.runs >= 0) + Options.MaxNumberOfRuns = Flags.runs; + if (!Inputs->empty() && !Flags.minimize_crash_internal_step) + Options.OutputCorpus = (*Inputs)[0]; + Options.ReportSlowUnits = Flags.report_slow_units; + if (Flags.artifact_prefix) + Options.ArtifactPrefix = Flags.artifact_prefix; + if (Flags.exact_artifact_path) + Options.ExactArtifactPath = Flags.exact_artifact_path; + std::vector<Unit> Dictionary; + if (Flags.dict) + if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary)) + return 1; + if (Flags.verbosity > 0 && !Dictionary.empty()) + Printf("Dictionary: %zd entries\n", Dictionary.size()); + bool DoPlainRun = AllInputsAreFiles(); + Options.SaveArtifacts = + !DoPlainRun || Flags.minimize_crash_internal_step; + Options.PrintNewCovPcs = Flags.print_pcs; + Options.PrintFinalStats = Flags.print_final_stats; + Options.PrintCorpusStats = Flags.print_corpus_stats; + Options.PrintCoverage = Flags.print_coverage; + Options.DumpCoverage = Flags.dump_coverage; + if (Flags.exit_on_src_pos) + Options.ExitOnSrcPos = Flags.exit_on_src_pos; + if (Flags.exit_on_item) + Options.ExitOnItem = Flags.exit_on_item; + + unsigned Seed = Flags.seed; + // Initialize Seed. + if (Seed == 0) + Seed = (std::chrono::system_clock::now().time_since_epoch().count() << 10) + + GetPid(); + if (Flags.verbosity) + Printf("INFO: Seed: %u\n", Seed); + + Random Rand(Seed); + auto *MD = new MutationDispatcher(Rand, Options); + auto *Corpus = new InputCorpus(Options.OutputCorpus); + auto *F = new Fuzzer(Callback, *Corpus, *MD, Options); + + for (auto &U: Dictionary) + if (U.size() <= Word::GetMaxSize()) + MD->AddWordToManualDictionary(Word(U.data(), U.size())); + + StartRssThread(F, Flags.rss_limit_mb); + + Options.HandleAbrt = Flags.handle_abrt; + Options.HandleBus = Flags.handle_bus; + Options.HandleFpe = Flags.handle_fpe; + Options.HandleIll = Flags.handle_ill; + Options.HandleInt = Flags.handle_int; + Options.HandleSegv = Flags.handle_segv; + Options.HandleTerm = Flags.handle_term; + SetSignalHandler(Options); + + if (Flags.minimize_crash_internal_step) + return MinimizeCrashInputInternalStep(F, Corpus); + + if (DoPlainRun) { + Options.SaveArtifacts = false; + int Runs = std::max(1, Flags.runs); + Printf("%s: Running %zd inputs %d time(s) each.\n", ProgName->c_str(), + Inputs->size(), Runs); + for (auto &Path : *Inputs) { + auto StartTime = system_clock::now(); + Printf("Running: %s\n", Path.c_str()); + for (int Iter = 0; Iter < Runs; Iter++) + RunOneTest(F, Path.c_str(), Options.MaxLen); + auto StopTime = system_clock::now(); + auto MS = duration_cast<milliseconds>(StopTime - StartTime).count(); + Printf("Executed %s in %zd ms\n", Path.c_str(), (long)MS); + } + Printf("***\n" + "*** NOTE: fuzzing was not performed, you have only\n" + "*** executed the target code on a fixed set of inputs.\n" + "***\n"); + F->PrintFinalStats(); + exit(0); + } + + if (Flags.merge) { + if (Options.MaxLen == 0) + F->SetMaxInputLen(kMaxSaneLen); + if (TPC.UsingTracePcGuard()) { + if (Flags.merge_control_file) + F->CrashResistantMergeInternalStep(Flags.merge_control_file); + else + F->CrashResistantMerge(Args, *Inputs); + } else { + F->Merge(*Inputs); + } + exit(0); + } + + size_t TemporaryMaxLen = Options.MaxLen ? Options.MaxLen : kMaxSaneLen; + + UnitVector InitialCorpus; + for (auto &Inp : *Inputs) { + Printf("Loading corpus dir: %s\n", Inp.c_str()); + ReadDirToVectorOfUnits(Inp.c_str(), &InitialCorpus, nullptr, + TemporaryMaxLen, /*ExitOnError=*/false); + } + + if (Options.MaxLen == 0) { + size_t MaxLen = 0; + for (auto &U : InitialCorpus) + MaxLen = std::max(U.size(), MaxLen); + F->SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxLen), kMaxSaneLen)); + } + + if (InitialCorpus.empty()) { + InitialCorpus.push_back(Unit({'\n'})); // Valid ASCII input. + if (Options.Verbosity) + Printf("INFO: A corpus is not provided, starting from an empty corpus\n"); + } + F->ShuffleAndMinimize(&InitialCorpus); + InitialCorpus.clear(); // Don't need this memory any more. + F->Loop(); + + if (Flags.verbosity) + Printf("Done %d runs in %zd second(s)\n", F->getTotalNumberOfRuns(), + F->secondsSinceProcessStartUp()); + F->PrintFinalStats(); + + exit(0); // Don't let F destroy itself. +} + +// Storage for global ExternalFunctions object. +ExternalFunctions *EF = nullptr; + +} // namespace fuzzer diff --git a/test/fuzz_test/Fuzzer/FuzzerExtFunctions.def b/test/fuzz_test/Fuzzer/FuzzerExtFunctions.def new file mode 100644 index 00000000..61c72e4a --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerExtFunctions.def @@ -0,0 +1,50 @@ +//===- FuzzerExtFunctions.def - External functions --------------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This defines the external function pointers that +// ``fuzzer::ExternalFunctions`` should contain and try to initialize. The +// EXT_FUNC macro must be defined at the point of inclusion. The signature of +// the macro is: +// +// EXT_FUNC(<name>, <return_type>, <function_signature>, <warn_if_missing>) +//===----------------------------------------------------------------------===// + +// Optional user functions +EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false); +EXT_FUNC(LLVMFuzzerCustomMutator, size_t, + (uint8_t * Data, size_t Size, size_t MaxSize, unsigned int Seed), + false); +EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t, + (const uint8_t * Data1, size_t Size1, + const uint8_t * Data2, size_t Size2, + uint8_t * Out, size_t MaxOutSize, unsigned int Seed), + false); + +// Sanitizer functions +EXT_FUNC(__lsan_enable, void, (), false); +EXT_FUNC(__lsan_disable, void, (), false); +EXT_FUNC(__lsan_do_recoverable_leak_check, int, (), false); +EXT_FUNC(__sanitizer_get_number_of_counters, size_t, (), false); +EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int, + (void (*malloc_hook)(const volatile void *, size_t), + void (*free_hook)(const volatile void *)), + false); +EXT_FUNC(__sanitizer_get_total_unique_caller_callee_pairs, size_t, (), false); +EXT_FUNC(__sanitizer_get_total_unique_coverage, size_t, (), true); +EXT_FUNC(__sanitizer_print_memory_profile, int, (size_t), false); +EXT_FUNC(__sanitizer_print_stack_trace, void, (), true); +EXT_FUNC(__sanitizer_symbolize_pc, void, + (void *, const char *fmt, char *out_buf, size_t out_buf_size), false); +EXT_FUNC(__sanitizer_get_module_and_offset_for_pc, int, + (void *pc, char *module_path, + size_t module_path_len,void **pc_offset), false); +EXT_FUNC(__sanitizer_reset_coverage, void, (), true); +EXT_FUNC(__sanitizer_set_death_callback, void, (void (*)(void)), true); +EXT_FUNC(__sanitizer_set_report_fd, void, (void*), false); +EXT_FUNC(__sanitizer_update_counter_bitset_and_clear_counters, uintptr_t, + (uint8_t*), false); diff --git a/test/fuzz_test/Fuzzer/FuzzerExtFunctions.h b/test/fuzz_test/Fuzzer/FuzzerExtFunctions.h new file mode 100644 index 00000000..2672a385 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerExtFunctions.h @@ -0,0 +1,35 @@ +//===- FuzzerExtFunctions.h - Interface to external functions ---*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Defines an interface to (possibly optional) functions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_EXT_FUNCTIONS_H +#define LLVM_FUZZER_EXT_FUNCTIONS_H + +#include <stddef.h> +#include <stdint.h> + +namespace fuzzer { + +struct ExternalFunctions { + // Initialize function pointers. Functions that are not available will be set + // to nullptr. Do not call this constructor before ``main()`` has been + // entered. + ExternalFunctions(); + +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + RETURN_TYPE(*NAME) FUNC_SIG = nullptr + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +}; +} // namespace fuzzer + +#endif diff --git a/test/fuzz_test/Fuzzer/FuzzerExtFunctionsDlsym.cpp b/test/fuzz_test/Fuzzer/FuzzerExtFunctionsDlsym.cpp new file mode 100644 index 00000000..06bddd5d --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerExtFunctionsDlsym.cpp @@ -0,0 +1,52 @@ +//===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Implementation for operating systems that support dlsym(). We only use it on +// Apple platforms for now. We don't use this approach on Linux because it +// requires that clients of LibFuzzer pass ``--export-dynamic`` to the linker. +// That is a complication we don't wish to expose to clients right now. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_APPLE + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include <dlfcn.h> + +using namespace fuzzer; + +template <typename T> +static T GetFnPtr(const char *FnName, bool WarnIfMissing) { + dlerror(); // Clear any previous errors. + void *Fn = dlsym(RTLD_DEFAULT, FnName); + if (Fn == nullptr) { + if (WarnIfMissing) { + const char *ErrorMsg = dlerror(); + Printf("WARNING: Failed to find function \"%s\".", FnName); + if (ErrorMsg) + Printf(" Reason %s.", ErrorMsg); + Printf("\n"); + } + } + return reinterpret_cast<T>(Fn); +} + +namespace fuzzer { + +ExternalFunctions::ExternalFunctions() { +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + this->NAME = GetFnPtr<decltype(ExternalFunctions::NAME)>(#NAME, WARN) + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +} // namespace fuzzer + +#endif // LIBFUZZER_APPLE diff --git a/test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeak.cpp b/test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeak.cpp new file mode 100644 index 00000000..7b02b6f0 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeak.cpp @@ -0,0 +1,53 @@ +//===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Implementation for Linux. This relies on the linker's support for weak +// symbols. We don't use this approach on Apple platforms because it requires +// clients of LibFuzzer to pass ``-U _<symbol_name>`` to the linker to allow +// weak symbols to be undefined. That is a complication we don't want to expose +// to clients right now. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_LINUX + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" + +extern "C" { +// Declare these symbols as weak to allow them to be optionally defined. +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + __attribute__((weak)) RETURN_TYPE NAME FUNC_SIG + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +using namespace fuzzer; + +static void CheckFnPtr(void *FnPtr, const char *FnName, bool WarnIfMissing) { + if (FnPtr == nullptr && WarnIfMissing) { + Printf("WARNING: Failed to find function \"%s\".\n", FnName); + } +} + +namespace fuzzer { + +ExternalFunctions::ExternalFunctions() { +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + this->NAME = ::NAME; \ + CheckFnPtr((void *)::NAME, #NAME, WARN); + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +} // namespace fuzzer + +#endif // LIBFUZZER_LINUX diff --git a/test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp b/test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp new file mode 100644 index 00000000..e10f7b4d --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp @@ -0,0 +1,56 @@ +//===- FuzzerExtFunctionsWeakAlias.cpp - Interface to external functions --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Implementation using weak aliases. Works for Windows. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_WINDOWS + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" + +using namespace fuzzer; + +extern "C" { +// Declare these symbols as weak to allow them to be optionally defined. +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + RETURN_TYPE NAME##Def FUNC_SIG { \ + Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \ + exit(1); \ + } \ + RETURN_TYPE NAME FUNC_SIG __attribute__((weak, alias(#NAME "Def"))); + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +template <typename T> +static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) { + if (Fun == FunDef) { + if (WarnIfMissing) + Printf("WARNING: Failed to find function \"%s\".\n", FnName); + return nullptr; + } + return Fun; +} + +namespace fuzzer { + +ExternalFunctions::ExternalFunctions() { +#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ + this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN); + +#include "FuzzerExtFunctions.def" + +#undef EXT_FUNC +} + +} // namespace fuzzer + +#endif // LIBFUZZER_WINDOWS diff --git a/test/fuzz_test/Fuzzer/FuzzerFlags.def b/test/fuzz_test/Fuzzer/FuzzerFlags.def new file mode 100644 index 00000000..25ef1741 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerFlags.def @@ -0,0 +1,115 @@ +//===- FuzzerFlags.def - Run-time flags -------------------------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Flags. FUZZER_FLAG_INT/FUZZER_FLAG_STRING macros should be defined at the +// point of inclusion. We are not using any flag parsing library for better +// portability and independence. +//===----------------------------------------------------------------------===// +FUZZER_FLAG_INT(verbosity, 1, "Verbosity level.") +FUZZER_FLAG_UNSIGNED(seed, 0, "Random seed. If 0, seed is generated.") +FUZZER_FLAG_INT(runs, -1, + "Number of individual test runs (-1 for infinite runs).") +FUZZER_FLAG_INT(max_len, 0, "Maximum length of the test input. " + "If 0, libFuzzer tries to guess a good value based on the corpus " + "and reports it. ") +FUZZER_FLAG_INT(cross_over, 1, "If 1, cross over inputs.") +FUZZER_FLAG_INT(mutate_depth, 5, + "Apply this number of consecutive mutations to each input.") +FUZZER_FLAG_INT(shuffle, 1, "Shuffle inputs at startup") +FUZZER_FLAG_INT(prefer_small, 1, + "If 1, always prefer smaller inputs during the corpus shuffle.") +FUZZER_FLAG_INT( + timeout, 1200, + "Timeout in seconds (if positive). " + "If one unit runs more than this number of seconds the process will abort.") +FUZZER_FLAG_INT(error_exitcode, 77, "When libFuzzer itself reports a bug " + "this exit code will be used.") +FUZZER_FLAG_INT(timeout_exitcode, 77, "When libFuzzer reports a timeout " + "this exit code will be used.") +FUZZER_FLAG_INT(max_total_time, 0, "If positive, indicates the maximal total " + "time in seconds to run the fuzzer.") +FUZZER_FLAG_INT(help, 0, "Print help.") +FUZZER_FLAG_INT(merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be " + "merged into the 1-st corpus. Only interesting units will be taken. " + "This flag can be used to minimize a corpus.") +FUZZER_FLAG_STRING(merge_control_file, "internal flag") +FUZZER_FLAG_INT(minimize_crash, 0, "If 1, minimizes the provided" + " crash input. Use with -runs=N or -max_total_time=N to limit " + "the number attempts") +FUZZER_FLAG_INT(minimize_crash_internal_step, 0, "internal flag") +FUZZER_FLAG_INT(use_counters, 1, "Use coverage counters") +FUZZER_FLAG_INT(use_indir_calls, 1, "Use indirect caller-callee counters") +FUZZER_FLAG_INT(use_memcmp, 1, + "Use hints from intercepting memcmp, strcmp, etc") +FUZZER_FLAG_INT(use_memmem, 1, + "Use hints from intercepting memmem, strstr, etc") +FUZZER_FLAG_INT(use_value_profile, 0, + "Experimental. Use value profile to guide fuzzing.") +FUZZER_FLAG_INT(use_cmp, 1, "Use CMP traces to guide mutations") +FUZZER_FLAG_INT(shrink, 0, "Experimental. Try to shrink corpus elements.") +FUZZER_FLAG_UNSIGNED(jobs, 0, "Number of jobs to run. If jobs >= 1 we spawn" + " this number of jobs in separate worker processes" + " with stdout/stderr redirected to fuzz-JOB.log.") +FUZZER_FLAG_UNSIGNED(workers, 0, + "Number of simultaneous worker processes to run the jobs." + " If zero, \"min(jobs,NumberOfCpuCores()/2)\" is used.") +FUZZER_FLAG_INT(reload, 1, + "Reload the main corpus every <N> seconds to get new units" + " discovered by other processes. If 0, disabled") +FUZZER_FLAG_INT(report_slow_units, 10, + "Report slowest units if they run for more than this number of seconds.") +FUZZER_FLAG_INT(only_ascii, 0, + "If 1, generate only ASCII (isprint+isspace) inputs.") +FUZZER_FLAG_STRING(dict, "Experimental. Use the dictionary file.") +FUZZER_FLAG_STRING(artifact_prefix, "Write fuzzing artifacts (crash, " + "timeout, or slow inputs) as " + "$(artifact_prefix)file") +FUZZER_FLAG_STRING(exact_artifact_path, + "Write the single artifact on failure (crash, timeout) " + "as $(exact_artifact_path). This overrides -artifact_prefix " + "and will not use checksum in the file name. Do not " + "use the same path for several parallel processes.") +FUZZER_FLAG_INT(output_csv, 0, "Enable pulse output in CSV format.") +FUZZER_FLAG_INT(print_pcs, 0, "If 1, print out newly covered PCs.") +FUZZER_FLAG_INT(print_final_stats, 0, "If 1, print statistics at exit.") +FUZZER_FLAG_INT(print_corpus_stats, 0, + "If 1, print statistics on corpus elements at exit.") +FUZZER_FLAG_INT(print_coverage, 0, "If 1, print coverage information at exit." + " Experimental, only with trace-pc-guard") +FUZZER_FLAG_INT(dump_coverage, 0, "If 1, dump coverage information at exit." + " Experimental, only with trace-pc-guard") +FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.") +FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGSEGV.") +FUZZER_FLAG_INT(handle_abrt, 1, "If 1, try to intercept SIGABRT.") +FUZZER_FLAG_INT(handle_ill, 1, "If 1, try to intercept SIGILL.") +FUZZER_FLAG_INT(handle_fpe, 1, "If 1, try to intercept SIGFPE.") +FUZZER_FLAG_INT(handle_int, 1, "If 1, try to intercept SIGINT.") +FUZZER_FLAG_INT(handle_term, 1, "If 1, try to intercept SIGTERM.") +FUZZER_FLAG_INT(close_fd_mask, 0, "If 1, close stdout at startup; " + "if 2, close stderr; if 3, close both. " + "Be careful, this will also close e.g. asan's stderr/stdout.") +FUZZER_FLAG_INT(detect_leaks, 1, "If 1, and if LeakSanitizer is enabled " + "try to detect memory leaks during fuzzing (i.e. not only at shut down).") +FUZZER_FLAG_INT(trace_malloc, 0, "If >= 1 will print all mallocs/frees. " + "If >= 2 will also print stack traces.") +FUZZER_FLAG_INT(rss_limit_mb, 2048, "If non-zero, the fuzzer will exit upon" + "reaching this limit of RSS memory usage.") +FUZZER_FLAG_STRING(exit_on_src_pos, "Exit if a newly found PC originates" + " from the given source location. Example: -exit_on_src_pos=foo.cc:123. " + "Used primarily for testing libFuzzer itself.") +FUZZER_FLAG_STRING(exit_on_item, "Exit if an item with a given sha1 sum" + " was added to the corpus. " + "Used primarily for testing libFuzzer itself.") + +FUZZER_DEPRECATED_FLAG(exit_on_first) +FUZZER_DEPRECATED_FLAG(save_minimized_corpus) +FUZZER_DEPRECATED_FLAG(sync_command) +FUZZER_DEPRECATED_FLAG(sync_timeout) +FUZZER_DEPRECATED_FLAG(test_single_input) +FUZZER_DEPRECATED_FLAG(drill) +FUZZER_DEPRECATED_FLAG(truncate_units) diff --git a/test/fuzz_test/Fuzzer/FuzzerIO.cpp b/test/fuzz_test/Fuzzer/FuzzerIO.cpp new file mode 100644 index 00000000..eda8e877 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerIO.cpp @@ -0,0 +1,117 @@ +//===- FuzzerIO.cpp - IO utils. -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// IO functions. +//===----------------------------------------------------------------------===// + +#include "FuzzerIO.h" +#include "FuzzerDefs.h" +#include "FuzzerExtFunctions.h" +#include <algorithm> +#include <cstdarg> +#include <fstream> +#include <iterator> +#include <sys/stat.h> +#include <sys/types.h> + +namespace fuzzer { + +static FILE *OutputFile = stderr; + +long GetEpoch(const std::string &Path) { + struct stat St; + if (stat(Path.c_str(), &St)) + return 0; // Can't stat, be conservative. + return St.st_mtime; +} + +Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) { + std::ifstream T(Path); + if (ExitOnError && !T) { + Printf("No such directory: %s; exiting\n", Path.c_str()); + exit(1); + } + + T.seekg(0, T.end); + size_t FileLen = T.tellg(); + if (MaxSize) + FileLen = std::min(FileLen, MaxSize); + + T.seekg(0, T.beg); + Unit Res(FileLen); + T.read(reinterpret_cast<char *>(Res.data()), FileLen); + return Res; +} + +std::string FileToString(const std::string &Path) { + std::ifstream T(Path); + return std::string((std::istreambuf_iterator<char>(T)), + std::istreambuf_iterator<char>()); +} + +void CopyFileToErr(const std::string &Path) { + Printf("%s", FileToString(Path).c_str()); +} + +void WriteToFile(const Unit &U, const std::string &Path) { + // Use raw C interface because this function may be called from a sig handler. + FILE *Out = fopen(Path.c_str(), "w"); + if (!Out) return; + fwrite(U.data(), sizeof(U[0]), U.size(), Out); + fclose(Out); +} + +void ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V, + long *Epoch, size_t MaxSize, bool ExitOnError) { + long E = Epoch ? *Epoch : 0; + std::vector<std::string> Files; + ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true); + size_t NumLoaded = 0; + for (size_t i = 0; i < Files.size(); i++) { + auto &X = Files[i]; + if (Epoch && GetEpoch(X) < E) continue; + NumLoaded++; + if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024) + Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path); + auto S = FileToVector(X, MaxSize, ExitOnError); + if (!S.empty()) + V->push_back(S); + } +} + +std::string DirPlusFile(const std::string &DirPath, + const std::string &FileName) { + return DirPath + GetSeparator() + FileName; +} + +void DupAndCloseStderr() { + int OutputFd = DuplicateFile(2); + if (OutputFd > 0) { + FILE *NewOutputFile = OpenFile(OutputFd, "w"); + if (NewOutputFile) { + OutputFile = NewOutputFile; + if (EF->__sanitizer_set_report_fd) + EF->__sanitizer_set_report_fd(reinterpret_cast<void *>(OutputFd)); + CloseFile(2); + } + } +} + +void CloseStdout() { + CloseFile(1); +} + +void Printf(const char *Fmt, ...) { + va_list ap; + va_start(ap, Fmt); + vfprintf(OutputFile, Fmt, ap); + va_end(ap); + fflush(OutputFile); +} + +} // namespace fuzzer diff --git a/test/fuzz_test/Fuzzer/FuzzerIO.h b/test/fuzz_test/Fuzzer/FuzzerIO.h new file mode 100644 index 00000000..741fecf4 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerIO.h @@ -0,0 +1,64 @@ +//===- FuzzerIO.h - Internal header for IO utils ----------------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// IO interface. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_IO_H +#define LLVM_FUZZER_IO_H + +#include "FuzzerDefs.h" + +namespace fuzzer { + +long GetEpoch(const std::string &Path); + +Unit FileToVector(const std::string &Path, size_t MaxSize = 0, + bool ExitOnError = true); + +std::string FileToString(const std::string &Path); + +void CopyFileToErr(const std::string &Path); + +void WriteToFile(const Unit &U, const std::string &Path); + +void ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V, + long *Epoch, size_t MaxSize, bool ExitOnError); + +// Returns "Dir/FileName" or equivalent for the current OS. +std::string DirPlusFile(const std::string &DirPath, + const std::string &FileName); + +// Returns the name of the dir, similar to the 'dirname' utility. +std::string DirName(const std::string &FileName); + +void DupAndCloseStderr(); + +void CloseStdout(); + +void Printf(const char *Fmt, ...); + +// Platform specific functions: +bool IsFile(const std::string &Path); + +void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, + std::vector<std::string> *V, bool TopDir); + +char GetSeparator(); + +FILE* OpenFile(int Fd, const char *Mode); + +int CloseFile(int Fd); + +int DuplicateFile(int Fd); + +void RemoveFile(const std::string &Path); + +} // namespace fuzzer + +#endif // LLVM_FUZZER_IO_H diff --git a/test/fuzz_test/Fuzzer/FuzzerIOPosix.cpp b/test/fuzz_test/Fuzzer/FuzzerIOPosix.cpp new file mode 100644 index 00000000..720bc130 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerIOPosix.cpp @@ -0,0 +1,88 @@ +//===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// IO functions implementation using Posix API. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_POSIX + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include <cstdarg> +#include <cstdio> +#include <dirent.h> +#include <fstream> +#include <iterator> +#include <libgen.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +namespace fuzzer { + +bool IsFile(const std::string &Path) { + struct stat St; + if (stat(Path.c_str(), &St)) + return false; + return S_ISREG(St.st_mode); +} + +void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, + std::vector<std::string> *V, bool TopDir) { + auto E = GetEpoch(Dir); + if (Epoch) + if (E && *Epoch >= E) return; + + DIR *D = opendir(Dir.c_str()); + if (!D) { + Printf("No such directory: %s; exiting\n", Dir.c_str()); + exit(1); + } + while (auto E = readdir(D)) { + std::string Path = DirPlusFile(Dir, E->d_name); + if (E->d_type == DT_REG || E->d_type == DT_LNK) + V->push_back(Path); + else if (E->d_type == DT_DIR && *E->d_name != '.') + ListFilesInDirRecursive(Path, Epoch, V, false); + } + closedir(D); + if (Epoch && TopDir) + *Epoch = E; +} + +char GetSeparator() { + return '/'; +} + +FILE* OpenFile(int Fd, const char* Mode) { + return fdopen(Fd, Mode); +} + +int CloseFile(int fd) { + return close(fd); +} + +int DuplicateFile(int Fd) { + return dup(Fd); +} + +void RemoveFile(const std::string &Path) { + unlink(Path.c_str()); +} + +std::string DirName(const std::string &FileName) { + char *Tmp = new char[FileName.size() + 1]; + memcpy(Tmp, FileName.c_str(), FileName.size() + 1); + std::string Res = dirname(Tmp); + delete [] Tmp; + return Res; +} + +} // namespace fuzzer + +#endif // LIBFUZZER_POSIX diff --git a/test/fuzz_test/Fuzzer/FuzzerIOWindows.cpp b/test/fuzz_test/Fuzzer/FuzzerIOWindows.cpp new file mode 100644 index 00000000..a4738eb9 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerIOWindows.cpp @@ -0,0 +1,282 @@ +//===- FuzzerIOWindows.cpp - IO utils for Windows. ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// IO functions implementation for Windows. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_WINDOWS + +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include <cstdarg> +#include <cstdio> +#include <fstream> +#include <io.h> +#include <iterator> +#include <sys/stat.h> +#include <sys/types.h> +#include <windows.h> + +namespace fuzzer { + +static bool IsFile(const std::string &Path, const DWORD &FileAttributes) { + + if (FileAttributes & FILE_ATTRIBUTE_NORMAL) + return true; + + if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) + return false; + + HANDLE FileHandle( + CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0)); + + if (FileHandle == INVALID_HANDLE_VALUE) { + Printf("CreateFileA() failed for \"%s\" (Error code: %lu).\n", Path.c_str(), + GetLastError()); + return false; + } + + DWORD FileType = GetFileType(FileHandle); + + if (FileType == FILE_TYPE_UNKNOWN) { + Printf("GetFileType() failed for \"%s\" (Error code: %lu).\n", Path.c_str(), + GetLastError()); + CloseHandle(FileHandle); + return false; + } + + if (FileType != FILE_TYPE_DISK) { + CloseHandle(FileHandle); + return false; + } + + CloseHandle(FileHandle); + return true; +} + +bool IsFile(const std::string &Path) { + DWORD Att = GetFileAttributesA(Path.c_str()); + + if (Att == INVALID_FILE_ATTRIBUTES) { + Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n", + Path.c_str(), GetLastError()); + return false; + } + + return IsFile(Path, Att); +} + +void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, + std::vector<std::string> *V, bool TopDir) { + auto E = GetEpoch(Dir); + if (Epoch) + if (E && *Epoch >= E) return; + + std::string Path(Dir); + assert(!Path.empty()); + if (Path.back() != '\\') + Path.push_back('\\'); + Path.push_back('*'); + + // Get the first directory entry. + WIN32_FIND_DATAA FindInfo; + HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FindInfo)); + if (FindHandle == INVALID_HANDLE_VALUE) + { + Printf("No file found in: %s.\n", Dir.c_str()); + return; + } + + do { + std::string FileName = DirPlusFile(Dir, FindInfo.cFileName); + + if (FindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + size_t FilenameLen = strlen(FindInfo.cFileName); + if ((FilenameLen == 1 && FindInfo.cFileName[0] == '.') || + (FilenameLen == 2 && FindInfo.cFileName[0] == '.' && + FindInfo.cFileName[1] == '.')) + continue; + + ListFilesInDirRecursive(FileName, Epoch, V, false); + } + else if (IsFile(FileName, FindInfo.dwFileAttributes)) + V->push_back(FileName); + } while (FindNextFileA(FindHandle, &FindInfo)); + + DWORD LastError = GetLastError(); + if (LastError != ERROR_NO_MORE_FILES) + Printf("FindNextFileA failed (Error code: %lu).\n", LastError); + + FindClose(FindHandle); + + if (Epoch && TopDir) + *Epoch = E; +} + +char GetSeparator() { + return '\\'; +} + +FILE* OpenFile(int Fd, const char* Mode) { + return _fdopen(Fd, Mode); +} + +int CloseFile(int Fd) { + return _close(Fd); +} + +int DuplicateFile(int Fd) { + return _dup(Fd); +} + +void RemoveFile(const std::string &Path) { + _unlink(Path.c_str()); +} + +static bool IsSeparator(char C) { + return C == '\\' || C == '/'; +} + +// Parse disk designators, like "C:\". If Relative == true, also accepts: "C:". +// Returns number of characters considered if successful. +static size_t ParseDrive(const std::string &FileName, const size_t Offset, + bool Relative = true) { + if (Offset + 1 >= FileName.size() || FileName[Offset + 1] != ':') + return 0; + if (Offset + 2 >= FileName.size() || !IsSeparator(FileName[Offset + 2])) { + if (!Relative) // Accept relative path? + return 0; + else + return 2; + } + return 3; +} + +// Parse a file name, like: SomeFile.txt +// Returns number of characters considered if successful. +static size_t ParseFileName(const std::string &FileName, const size_t Offset) { + size_t Pos = Offset; + const size_t End = FileName.size(); + for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos) + ; + return Pos - Offset; +} + +// Parse a directory ending in separator, like: SomeDir\ +// Returns number of characters considered if successful. +static size_t ParseDir(const std::string &FileName, const size_t Offset) { + size_t Pos = Offset; + const size_t End = FileName.size(); + if (Pos >= End || IsSeparator(FileName[Pos])) + return 0; + for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos) + ; + if (Pos >= End) + return 0; + ++Pos; // Include separator. + return Pos - Offset; +} + +// Parse a servername and share, like: SomeServer\SomeShare\ +// Returns number of characters considered if successful. +static size_t ParseServerAndShare(const std::string &FileName, + const size_t Offset) { + size_t Pos = Offset, Res; + if (!(Res = ParseDir(FileName, Pos))) + return 0; + Pos += Res; + if (!(Res = ParseDir(FileName, Pos))) + return 0; + Pos += Res; + return Pos - Offset; +} + +// Parse the given Ref string from the position Offset, to exactly match the given +// string Patt. +// Returns number of characters considered if successful. +static size_t ParseCustomString(const std::string &Ref, size_t Offset, + const char *Patt) { + size_t Len = strlen(Patt); + if (Offset + Len > Ref.size()) + return 0; + return Ref.compare(Offset, Len, Patt) == 0 ? Len : 0; +} + +// Parse a location, like: +// \\?\UNC\Server\Share\ \\?\C:\ \\Server\Share\ \ C:\ C: +// Returns number of characters considered if successful. +static size_t ParseLocation(const std::string &FileName) { + size_t Pos = 0, Res; + + if ((Res = ParseCustomString(FileName, Pos, R"(\\?\)"))) { + Pos += Res; + if ((Res = ParseCustomString(FileName, Pos, R"(UNC\)"))) { + Pos += Res; + if ((Res = ParseServerAndShare(FileName, Pos))) + return Pos + Res; + return 0; + } + if ((Res = ParseDrive(FileName, Pos, false))) + return Pos + Res; + return 0; + } + + if (Pos < FileName.size() && IsSeparator(FileName[Pos])) { + ++Pos; + if (Pos < FileName.size() && IsSeparator(FileName[Pos])) { + ++Pos; + if ((Res = ParseServerAndShare(FileName, Pos))) + return Pos + Res; + return 0; + } + return Pos; + } + + if ((Res = ParseDrive(FileName, Pos))) + return Pos + Res; + + return Pos; +} + +std::string DirName(const std::string &FileName) { + size_t LocationLen = ParseLocation(FileName); + size_t DirLen = 0, Res; + while ((Res = ParseDir(FileName, LocationLen + DirLen))) + DirLen += Res; + size_t FileLen = ParseFileName(FileName, LocationLen + DirLen); + + if (LocationLen + DirLen + FileLen != FileName.size()) { + Printf("DirName() failed for \"%s\", invalid path.\n", FileName.c_str()); + exit(1); + } + + if (DirLen) { + --DirLen; // Remove trailing separator. + if (!FileLen) { // Path ended in separator. + assert(DirLen); + // Remove file name from Dir. + while (DirLen && !IsSeparator(FileName[LocationLen + DirLen - 1])) + --DirLen; + if (DirLen) // Remove trailing separator. + --DirLen; + } + } + + if (!LocationLen) { // Relative path. + if (!DirLen) + return "."; + return std::string(".\\").append(FileName, 0, DirLen); + } + + return FileName.substr(0, LocationLen + DirLen); +} + +} // namespace fuzzer + +#endif // LIBFUZZER_WINDOWS diff --git a/test/fuzz_test/Fuzzer/FuzzerInterface.h b/test/fuzz_test/Fuzzer/FuzzerInterface.h new file mode 100644 index 00000000..d47e20e3 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerInterface.h @@ -0,0 +1,67 @@ +//===- FuzzerInterface.h - Interface header for the Fuzzer ------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Define the interface between libFuzzer and the library being tested. +//===----------------------------------------------------------------------===// + +// NOTE: the libFuzzer interface is thin and in the majority of cases +// you should not include this file into your target. In 95% of cases +// all you need is to define the following function in your file: +// extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); + +// WARNING: keep the interface in C. + +#ifndef LLVM_FUZZER_INTERFACE_H +#define LLVM_FUZZER_INTERFACE_H + +#include <stddef.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Mandatory user-provided target function. +// Executes the code under test with [Data, Data+Size) as the input. +// libFuzzer will invoke this function *many* times with different inputs. +// Must return 0. +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); + +// Optional user-provided initialization function. +// If provided, this function will be called by libFuzzer once at startup. +// It may read and modify argc/argv. +// Must return 0. +int LLVMFuzzerInitialize(int *argc, char ***argv); + +// Optional user-provided custom mutator. +// Mutates raw data in [Data, Data+Size) inplace. +// Returns the new size, which is not greater than MaxSize. +// Given the same Seed produces the same mutation. +size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, + unsigned int Seed); + +// Optional user-provided custom cross-over function. +// Combines pieces of Data1 & Data2 together into Out. +// Returns the new size, which is not greater than MaxOutSize. +// Should produce the same mutation given the same Seed. +size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1, + const uint8_t *Data2, size_t Size2, + uint8_t *Out, size_t MaxOutSize, + unsigned int Seed); + +// Experimental, may go away in future. +// libFuzzer-provided function to be used inside LLVMFuzzerTestOneInput. +// Mutates raw data in [Data, Data+Size) inplace. +// Returns the new size, which is not greater than MaxSize. +size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // LLVM_FUZZER_INTERFACE_H diff --git a/test/fuzz_test/Fuzzer/FuzzerInternal.h b/test/fuzz_test/Fuzzer/FuzzerInternal.h new file mode 100644 index 00000000..c0417060 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerInternal.h @@ -0,0 +1,182 @@ +//===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Define the main class fuzzer::Fuzzer and most functions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_INTERNAL_H +#define LLVM_FUZZER_INTERNAL_H + +#include "FuzzerDefs.h" +#include "FuzzerExtFunctions.h" +#include "FuzzerInterface.h" +#include "FuzzerOptions.h" +#include "FuzzerSHA1.h" +#include "FuzzerValueBitMap.h" +#include <algorithm> +#include <atomic> +#include <chrono> +#include <climits> +#include <cstdlib> +#include <string.h> + +namespace fuzzer { + +using namespace std::chrono; + +class Fuzzer { +public: + + // Aggregates all available coverage measurements. + struct Coverage { + Coverage() { Reset(); } + + void Reset() { + BlockCoverage = 0; + CallerCalleeCoverage = 0; + CounterBitmapBits = 0; + CounterBitmap.clear(); + VPMap.Reset(); + } + + size_t BlockCoverage; + size_t CallerCalleeCoverage; + // Precalculated number of bits in CounterBitmap. + size_t CounterBitmapBits; + std::vector<uint8_t> CounterBitmap; + ValueBitMap VPMap; + }; + + Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, + FuzzingOptions Options); + ~Fuzzer(); + void Loop(); + void MinimizeCrashLoop(const Unit &U); + void ShuffleAndMinimize(UnitVector *V); + void InitializeTraceState(); + void RereadOutputCorpus(size_t MaxSize); + + size_t secondsSinceProcessStartUp() { + return duration_cast<seconds>(system_clock::now() - ProcessStartTime) + .count(); + } + + bool TimedOut() { + return Options.MaxTotalTimeSec > 0 && + secondsSinceProcessStartUp() > + static_cast<size_t>(Options.MaxTotalTimeSec); + } + + size_t execPerSec() { + size_t Seconds = secondsSinceProcessStartUp(); + return Seconds ? TotalNumberOfRuns / Seconds : 0; + } + + size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; } + + static void StaticAlarmCallback(); + static void StaticCrashSignalCallback(); + static void StaticInterruptCallback(); + + void ExecuteCallback(const uint8_t *Data, size_t Size); + size_t RunOne(const uint8_t *Data, size_t Size); + + // Merge Corpora[1:] into Corpora[0]. + void Merge(const std::vector<std::string> &Corpora); + void CrashResistantMerge(const std::vector<std::string> &Args, + const std::vector<std::string> &Corpora); + void CrashResistantMergeInternalStep(const std::string &ControlFilePath); + // Returns a subset of 'Extra' that adds coverage to 'Initial'. + UnitVector FindExtraUnits(const UnitVector &Initial, const UnitVector &Extra); + MutationDispatcher &GetMD() { return MD; } + void PrintFinalStats(); + void SetMaxInputLen(size_t MaxInputLen); + void SetMaxMutationLen(size_t MaxMutationLen); + void RssLimitCallback(); + + // Public for tests. + void ResetCoverage(); + + bool InFuzzingThread() const { return IsMyThread; } + size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const; + void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, + bool DuringInitialCorpusExecution); + + void HandleMalloc(size_t Size); + +private: + void AlarmCallback(); + void CrashCallback(); + void InterruptCallback(); + void MutateAndTestOne(); + void ReportNewCoverage(InputInfo *II, const Unit &U); + size_t RunOne(const Unit &U) { return RunOne(U.data(), U.size()); } + void WriteToOutputCorpus(const Unit &U); + void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); + void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0); + void PrintStatusForNewUnit(const Unit &U); + void ShuffleCorpus(UnitVector *V); + void AddToCorpus(const Unit &U); + void CheckExitOnSrcPosOrItem(); + + // Trace-based fuzzing: we run a unit with some kind of tracing + // enabled and record potentially useful mutations. Then + // We apply these mutations one by one to the unit and run it again. + + // Start tracing; forget all previously proposed mutations. + void StartTraceRecording(); + // Stop tracing. + void StopTraceRecording(); + + void SetDeathCallback(); + static void StaticDeathCallback(); + void DumpCurrentUnit(const char *Prefix); + void DeathCallback(); + + void ResetEdgeCoverage(); + void ResetCounters(); + void PrepareCounters(Fuzzer::Coverage *C); + bool RecordMaxCoverage(Fuzzer::Coverage *C); + + void AllocateCurrentUnitData(); + uint8_t *CurrentUnitData = nullptr; + std::atomic<size_t> CurrentUnitSize; + uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit. + bool RunningCB = false; + + size_t TotalNumberOfRuns = 0; + size_t NumberOfNewUnitsAdded = 0; + + bool HasMoreMallocsThanFrees = false; + size_t NumberOfLeakDetectionAttempts = 0; + + UserCallback CB; + InputCorpus &Corpus; + MutationDispatcher &MD; + FuzzingOptions Options; + + system_clock::time_point ProcessStartTime = system_clock::now(); + system_clock::time_point UnitStartTime, UnitStopTime; + long TimeOfLongestUnitInSeconds = 0; + long EpochOfLastReadOfOutputCorpus = 0; + + // Maximum recorded coverage. + Coverage MaxCoverage; + + size_t MaxInputLen = 0; + size_t MaxMutationLen = 0; + + // Need to know our own thread. + static thread_local bool IsMyThread; + + bool InMergeMode = false; +}; + +}; // namespace fuzzer + +#endif // LLVM_FUZZER_INTERNAL_H diff --git a/test/fuzz_test/Fuzzer/FuzzerLoop.cpp b/test/fuzz_test/Fuzzer/FuzzerLoop.cpp new file mode 100644 index 00000000..73e058ff --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerLoop.cpp @@ -0,0 +1,792 @@ +//===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Fuzzer's main loop. +//===----------------------------------------------------------------------===// + +#include "FuzzerCorpus.h" +#include "FuzzerInternal.h" +#include "FuzzerIO.h" +#include "FuzzerMutate.h" +#include "FuzzerRandom.h" +#include "FuzzerTracePC.h" +#include <algorithm> +#include <cstring> +#include <memory> +#include <set> + +#if defined(__has_include) +#if __has_include(<sanitizer / coverage_interface.h>) +#include <sanitizer/coverage_interface.h> +#endif +#if __has_include(<sanitizer / lsan_interface.h>) +#include <sanitizer/lsan_interface.h> +#endif +#endif + +#define NO_SANITIZE_MEMORY +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#undef NO_SANITIZE_MEMORY +#define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +#endif +#endif + +namespace fuzzer { +static const size_t kMaxUnitSizeToPrint = 256; + +thread_local bool Fuzzer::IsMyThread; + +static void MissingExternalApiFunction(const char *FnName) { + Printf("ERROR: %s is not defined. Exiting.\n" + "Did you use -fsanitize-coverage=... to build your code?\n", + FnName); + exit(1); +} + +#define CHECK_EXTERNAL_FUNCTION(fn) \ + do { \ + if (!(EF->fn)) \ + MissingExternalApiFunction(#fn); \ + } while (false) + +// Only one Fuzzer per process. +static Fuzzer *F; + +void Fuzzer::ResetEdgeCoverage() { + CHECK_EXTERNAL_FUNCTION(__sanitizer_reset_coverage); + EF->__sanitizer_reset_coverage(); +} + +void Fuzzer::ResetCounters() { + if (Options.UseCounters) + EF->__sanitizer_update_counter_bitset_and_clear_counters(0); +} + +void Fuzzer::PrepareCounters(Fuzzer::Coverage *C) { + if (Options.UseCounters) { + size_t NumCounters = EF->__sanitizer_get_number_of_counters(); + C->CounterBitmap.resize(NumCounters); + } +} + +// Records data to a maximum coverage tracker. Returns true if additional +// coverage was discovered. +bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) { + bool Res = false; + + uint64_t NewBlockCoverage = EF->__sanitizer_get_total_unique_coverage(); + if (NewBlockCoverage > C->BlockCoverage) { + Res = true; + C->BlockCoverage = NewBlockCoverage; + } + + if (Options.UseIndirCalls && + EF->__sanitizer_get_total_unique_caller_callee_pairs) { + uint64_t NewCallerCalleeCoverage = + EF->__sanitizer_get_total_unique_caller_callee_pairs(); + if (NewCallerCalleeCoverage > C->CallerCalleeCoverage) { + Res = true; + C->CallerCalleeCoverage = NewCallerCalleeCoverage; + } + } + + if (Options.UseCounters) { + uint64_t CounterDelta = + EF->__sanitizer_update_counter_bitset_and_clear_counters( + C->CounterBitmap.data()); + if (CounterDelta > 0) { + Res = true; + C->CounterBitmapBits += CounterDelta; + } + } + + return Res; +} + +// Leak detection is expensive, so we first check if there were more mallocs +// than frees (using the sanitizer malloc hooks) and only then try to call lsan. +struct MallocFreeTracer { + void Start(int TraceLevel) { + this->TraceLevel = TraceLevel; + if (TraceLevel) + Printf("MallocFreeTracer: START\n"); + Mallocs = 0; + Frees = 0; + } + // Returns true if there were more mallocs than frees. + bool Stop() { + if (TraceLevel) + Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(), + Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT"); + bool Result = Mallocs > Frees; + Mallocs = 0; + Frees = 0; + TraceLevel = 0; + return Result; + } + std::atomic<size_t> Mallocs; + std::atomic<size_t> Frees; + int TraceLevel = 0; +}; + +static MallocFreeTracer AllocTracer; + +ATTRIBUTE_NO_SANITIZE_MEMORY +void MallocHook(const volatile void *ptr, size_t size) { + size_t N = AllocTracer.Mallocs++; + F->HandleMalloc(size); + if (int TraceLevel = AllocTracer.TraceLevel) { + Printf("MALLOC[%zd] %p %zd\n", N, ptr, size); + if (TraceLevel >= 2 && EF) + EF->__sanitizer_print_stack_trace(); + } +} + +ATTRIBUTE_NO_SANITIZE_MEMORY +void FreeHook(const volatile void *ptr) { + size_t N = AllocTracer.Frees++; + if (int TraceLevel = AllocTracer.TraceLevel) { + Printf("FREE[%zd] %p\n", N, ptr); + if (TraceLevel >= 2 && EF) + EF->__sanitizer_print_stack_trace(); + } +} + +// Crash on a single malloc that exceeds the rss limit. +void Fuzzer::HandleMalloc(size_t Size) { + if (!Options.RssLimitMb || (Size >> 20) < (size_t)Options.RssLimitMb) + return; + Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(), + Size); + Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); + if (EF->__sanitizer_print_stack_trace) + EF->__sanitizer_print_stack_trace(); + DumpCurrentUnit("oom-"); + Printf("SUMMARY: libFuzzer: out-of-memory\n"); + PrintFinalStats(); + _Exit(Options.ErrorExitCode); // Stop right now. +} + +Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, + FuzzingOptions Options) + : CB(CB), Corpus(Corpus), MD(MD), Options(Options) { + SetDeathCallback(); + InitializeTraceState(); + assert(!F); + F = this; + TPC.ResetMaps(); + ResetCoverage(); + IsMyThread = true; + if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks) + EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook); + TPC.SetUseCounters(Options.UseCounters); + TPC.SetUseValueProfile(Options.UseValueProfile); + TPC.SetPrintNewPCs(Options.PrintNewCovPcs); + + if (Options.Verbosity) + TPC.PrintModuleInfo(); + if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec) + EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus); + MaxInputLen = MaxMutationLen = Options.MaxLen; + AllocateCurrentUnitData(); + CurrentUnitSize = 0; + memset(BaseSha1, 0, sizeof(BaseSha1)); +} + +Fuzzer::~Fuzzer() { } + +void Fuzzer::AllocateCurrentUnitData() { + if (CurrentUnitData || MaxInputLen == 0) return; + CurrentUnitData = new uint8_t[MaxInputLen]; +} + +void Fuzzer::SetDeathCallback() { + CHECK_EXTERNAL_FUNCTION(__sanitizer_set_death_callback); + EF->__sanitizer_set_death_callback(StaticDeathCallback); +} + +void Fuzzer::StaticDeathCallback() { + assert(F); + F->DeathCallback(); +} + +static void WarnOnUnsuccessfullMerge(bool DoWarn) { + if (!DoWarn) return; + Printf( + "***\n" + "***\n" + "***\n" + "*** NOTE: merge did not succeed due to a failure on one of the inputs.\n" + "*** You will need to filter out crashes from the corpus, e.g. like this:\n" + "*** for f in WITH_CRASHES/*; do ./fuzzer $f && cp $f NO_CRASHES; done\n" + "*** Future versions may have crash-resistant merge, stay tuned.\n" + "***\n" + "***\n" + "***\n"); +} + +void Fuzzer::DumpCurrentUnit(const char *Prefix) { + WarnOnUnsuccessfullMerge(InMergeMode); + if (!CurrentUnitData) return; // Happens when running individual inputs. + MD.PrintMutationSequence(); + Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str()); + size_t UnitSize = CurrentUnitSize; + if (UnitSize <= kMaxUnitSizeToPrint) { + PrintHexArray(CurrentUnitData, UnitSize, "\n"); + PrintASCII(CurrentUnitData, UnitSize, "\n"); + } + WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize}, + Prefix); +} + +NO_SANITIZE_MEMORY +void Fuzzer::DeathCallback() { + DumpCurrentUnit("crash-"); + PrintFinalStats(); +} + +void Fuzzer::StaticAlarmCallback() { + assert(F); + F->AlarmCallback(); +} + +void Fuzzer::StaticCrashSignalCallback() { + assert(F); + F->CrashCallback(); +} + +void Fuzzer::StaticInterruptCallback() { + assert(F); + F->InterruptCallback(); +} + +void Fuzzer::CrashCallback() { + Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid()); + if (EF->__sanitizer_print_stack_trace) + EF->__sanitizer_print_stack_trace(); + Printf("NOTE: libFuzzer has rudimentary signal handlers.\n" + " Combine libFuzzer with AddressSanitizer or similar for better " + "crash reports.\n"); + Printf("SUMMARY: libFuzzer: deadly signal\n"); + DumpCurrentUnit("crash-"); + PrintFinalStats(); + exit(Options.ErrorExitCode); +} + +void Fuzzer::InterruptCallback() { + Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid()); + PrintFinalStats(); + _Exit(0); // Stop right now, don't perform any at-exit actions. +} + +NO_SANITIZE_MEMORY +void Fuzzer::AlarmCallback() { + assert(Options.UnitTimeoutSec > 0); + if (!InFuzzingThread()) return; + if (!RunningCB) + return; // We have not started running units yet. + size_t Seconds = + duration_cast<seconds>(system_clock::now() - UnitStartTime).count(); + if (Seconds == 0) + return; + if (Options.Verbosity >= 2) + Printf("AlarmCallback %zd\n", Seconds); + if (Seconds >= (size_t)Options.UnitTimeoutSec) { + Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds); + Printf(" and the timeout value is %d (use -timeout=N to change)\n", + Options.UnitTimeoutSec); + DumpCurrentUnit("timeout-"); + Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(), + Seconds); + if (EF->__sanitizer_print_stack_trace) + EF->__sanitizer_print_stack_trace(); + Printf("SUMMARY: libFuzzer: timeout\n"); + PrintFinalStats(); + _Exit(Options.TimeoutExitCode); // Stop right now. + } +} + +void Fuzzer::RssLimitCallback() { + Printf( + "==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n", + GetPid(), GetPeakRSSMb(), Options.RssLimitMb); + Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); + if (EF->__sanitizer_print_memory_profile) + EF->__sanitizer_print_memory_profile(95); + DumpCurrentUnit("oom-"); + Printf("SUMMARY: libFuzzer: out-of-memory\n"); + PrintFinalStats(); + _Exit(Options.ErrorExitCode); // Stop right now. +} + +void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) { + size_t ExecPerSec = execPerSec(); + if (Options.OutputCSV) { + static bool csvHeaderPrinted = false; + if (!csvHeaderPrinted) { + csvHeaderPrinted = true; + Printf("runs,block_cov,bits,cc_cov,corpus,execs_per_sec,tbms,reason\n"); + } + Printf("%zd,%zd,%zd,%zd,%zd,%zd,%s\n", TotalNumberOfRuns, + MaxCoverage.BlockCoverage, MaxCoverage.CounterBitmapBits, + MaxCoverage.CallerCalleeCoverage, Corpus.size(), ExecPerSec, Where); + } + + if (!Options.Verbosity) + return; + Printf("#%zd\t%s", TotalNumberOfRuns, Where); + if (MaxCoverage.BlockCoverage) + Printf(" cov: %zd", MaxCoverage.BlockCoverage); + if (size_t N = MaxCoverage.VPMap.GetNumBitsSinceLastMerge()) + Printf(" vp: %zd", N); + if (size_t N = TPC.GetTotalPCCoverage()) + Printf(" cov: %zd", N); + if (auto TB = MaxCoverage.CounterBitmapBits) + Printf(" bits: %zd", TB); + if (size_t N = Corpus.NumFeatures()) + Printf( " ft: %zd", N); + if (MaxCoverage.CallerCalleeCoverage) + Printf(" indir: %zd", MaxCoverage.CallerCalleeCoverage); + if (!Corpus.empty()) { + Printf(" corp: %zd", Corpus.NumActiveUnits()); + if (size_t N = Corpus.SizeInBytes()) { + if (N < (1<<14)) + Printf("/%zdb", N); + else if (N < (1 << 24)) + Printf("/%zdKb", N >> 10); + else + Printf("/%zdMb", N >> 20); + } + } + if (Units) + Printf(" units: %zd", Units); + + Printf(" exec/s: %zd", ExecPerSec); + Printf(" rss: %zdMb", GetPeakRSSMb()); + Printf("%s", End); +} + +void Fuzzer::PrintFinalStats() { + if (Options.PrintCoverage) + TPC.PrintCoverage(); + if (Options.DumpCoverage) + TPC.DumpCoverage(); + if (Options.PrintCorpusStats) + Corpus.PrintStats(); + if (!Options.PrintFinalStats) return; + size_t ExecPerSec = execPerSec(); + Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns); + Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec); + Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded); + Printf("stat::slowest_unit_time_sec: %zd\n", TimeOfLongestUnitInSeconds); + Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb()); +} + +void Fuzzer::SetMaxInputLen(size_t MaxInputLen) { + assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0. + assert(MaxInputLen); + this->MaxInputLen = MaxInputLen; + this->MaxMutationLen = MaxInputLen; + AllocateCurrentUnitData(); + Printf("INFO: -max_len is not provided, using %zd\n", MaxInputLen); +} + +void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { + assert(MaxMutationLen && MaxMutationLen <= MaxInputLen); + this->MaxMutationLen = MaxMutationLen; +} + +void Fuzzer::CheckExitOnSrcPosOrItem() { + if (!Options.ExitOnSrcPos.empty()) { + static auto *PCsSet = new std::set<uintptr_t>; + for (size_t i = 1, N = TPC.GetNumPCs(); i < N; i++) { + uintptr_t PC = TPC.GetPC(i); + if (!PC) continue; + if (!PCsSet->insert(PC).second) continue; + std::string Descr = DescribePC("%L", PC); + if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) { + Printf("INFO: found line matching '%s', exiting.\n", + Options.ExitOnSrcPos.c_str()); + _Exit(0); + } + } + } + if (!Options.ExitOnItem.empty()) { + if (Corpus.HasUnit(Options.ExitOnItem)) { + Printf("INFO: found item with checksum '%s', exiting.\n", + Options.ExitOnItem.c_str()); + _Exit(0); + } + } +} + +void Fuzzer::RereadOutputCorpus(size_t MaxSize) { + if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec) return; + std::vector<Unit> AdditionalCorpus; + ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus, + &EpochOfLastReadOfOutputCorpus, MaxSize, + /*ExitOnError*/ false); + if (Options.Verbosity >= 2) + Printf("Reload: read %zd new units.\n", AdditionalCorpus.size()); + bool Reloaded = false; + for (auto &U : AdditionalCorpus) { + if (U.size() > MaxSize) + U.resize(MaxSize); + if (!Corpus.HasUnit(U)) { + if (size_t NumFeatures = RunOne(U)) { + CheckExitOnSrcPosOrItem(); + Corpus.AddToCorpus(U, NumFeatures); + Reloaded = true; + } + } + } + if (Reloaded) + PrintStats("RELOAD"); +} + +void Fuzzer::ShuffleCorpus(UnitVector *V) { + std::random_shuffle(V->begin(), V->end(), MD.GetRand()); + if (Options.PreferSmall) + std::stable_sort(V->begin(), V->end(), [](const Unit &A, const Unit &B) { + return A.size() < B.size(); + }); +} + +void Fuzzer::ShuffleAndMinimize(UnitVector *InitialCorpus) { + Printf("#0\tREAD units: %zd\n", InitialCorpus->size()); + if (Options.ShuffleAtStartUp) + ShuffleCorpus(InitialCorpus); + + // Test the callback with empty input and never try it again. + uint8_t dummy; + ExecuteCallback(&dummy, 0); + + for (const auto &U : *InitialCorpus) { + if (size_t NumFeatures = RunOne(U)) { + CheckExitOnSrcPosOrItem(); + Corpus.AddToCorpus(U, NumFeatures); + if (Options.Verbosity >= 2) + Printf("NEW0: %zd L %zd\n", MaxCoverage.BlockCoverage, U.size()); + } + TryDetectingAMemoryLeak(U.data(), U.size(), + /*DuringInitialCorpusExecution*/ true); + } + PrintStats("INITED"); + if (Corpus.empty()) { + Printf("ERROR: no interesting inputs were found. " + "Is the code instrumented for coverage? Exiting.\n"); + exit(1); + } +} + +size_t Fuzzer::RunOne(const uint8_t *Data, size_t Size) { + if (!Size) return 0; + TotalNumberOfRuns++; + + ExecuteCallback(Data, Size); + + size_t Res = 0; + if (size_t NumFeatures = TPC.CollectFeatures([&](size_t Feature) -> bool { + return Corpus.AddFeature(Feature, Size, Options.Shrink); + })) + Res = NumFeatures; + + if (!TPC.UsingTracePcGuard()) { + if (TPC.UpdateValueProfileMap(&MaxCoverage.VPMap)) + Res = 1; + if (!Res && RecordMaxCoverage(&MaxCoverage)) + Res = 1; + } + + auto TimeOfUnit = + duration_cast<seconds>(UnitStopTime - UnitStartTime).count(); + if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && + secondsSinceProcessStartUp() >= 2) + PrintStats("pulse "); + if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 && + TimeOfUnit >= Options.ReportSlowUnits) { + TimeOfLongestUnitInSeconds = TimeOfUnit; + Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds); + WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-"); + } + return Res; +} + +size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const { + assert(InFuzzingThread()); + *Data = CurrentUnitData; + return CurrentUnitSize; +} + +void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) { + assert(InFuzzingThread()); + // We copy the contents of Unit into a separate heap buffer + // so that we reliably find buffer overflows in it. + uint8_t *DataCopy = new uint8_t[Size]; + memcpy(DataCopy, Data, Size); + if (CurrentUnitData && CurrentUnitData != Data) + memcpy(CurrentUnitData, Data, Size); + CurrentUnitSize = Size; + AllocTracer.Start(Options.TraceMalloc); + UnitStartTime = system_clock::now(); + ResetCounters(); // Reset coverage right before the callback. + TPC.ResetMaps(); + RunningCB = true; + int Res = CB(DataCopy, Size); + RunningCB = false; + UnitStopTime = system_clock::now(); + (void)Res; + assert(Res == 0); + HasMoreMallocsThanFrees = AllocTracer.Stop(); + CurrentUnitSize = 0; + delete[] DataCopy; +} + +void Fuzzer::WriteToOutputCorpus(const Unit &U) { + if (Options.OnlyASCII) + assert(IsASCII(U)); + if (Options.OutputCorpus.empty()) + return; + std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U)); + WriteToFile(U, Path); + if (Options.Verbosity >= 2) + Printf("Written to %s\n", Path.c_str()); +} + +void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { + if (!Options.SaveArtifacts) + return; + std::string Path = Options.ArtifactPrefix + Prefix + Hash(U); + if (!Options.ExactArtifactPath.empty()) + Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix. + WriteToFile(U, Path); + Printf("artifact_prefix='%s'; Test unit written to %s\n", + Options.ArtifactPrefix.c_str(), Path.c_str()); + if (U.size() <= kMaxUnitSizeToPrint) + Printf("Base64: %s\n", Base64(U).c_str()); +} + +void Fuzzer::PrintStatusForNewUnit(const Unit &U) { + if (!Options.PrintNEW) + return; + PrintStats("NEW ", ""); + if (Options.Verbosity) { + Printf(" L: %zd ", U.size()); + MD.PrintMutationSequence(); + Printf("\n"); + } +} + +void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) { + II->NumSuccessfullMutations++; + MD.RecordSuccessfulMutationSequence(); + PrintStatusForNewUnit(U); + WriteToOutputCorpus(U); + NumberOfNewUnitsAdded++; + TPC.PrintNewPCs(); +} + +// Finds minimal number of units in 'Extra' that add coverage to 'Initial'. +// We do it by actually executing the units, sometimes more than once, +// because we may be using different coverage-like signals and the only +// common thing between them is that we can say "this unit found new stuff". +UnitVector Fuzzer::FindExtraUnits(const UnitVector &Initial, + const UnitVector &Extra) { + UnitVector Res = Extra; + UnitVector Tmp; + size_t OldSize = Res.size(); + for (int Iter = 0; Iter < 10; Iter++) { + ShuffleCorpus(&Res); + TPC.ResetMaps(); + Corpus.ResetFeatureSet(); + ResetCoverage(); + + for (auto &U : Initial) { + TPC.ResetMaps(); + RunOne(U); + } + + Tmp.clear(); + for (auto &U : Res) { + TPC.ResetMaps(); + if (RunOne(U)) + Tmp.push_back(U); + } + + char Stat[7] = "MIN "; + Stat[3] = '0' + Iter; + PrintStats(Stat, "\n", Tmp.size()); + + size_t NewSize = Tmp.size(); + assert(NewSize <= OldSize); + Res.swap(Tmp); + + if (NewSize + 5 >= OldSize) + break; + OldSize = NewSize; + } + return Res; +} + +void Fuzzer::Merge(const std::vector<std::string> &Corpora) { + if (Corpora.size() <= 1) { + Printf("Merge requires two or more corpus dirs\n"); + return; + } + InMergeMode = true; + std::vector<std::string> ExtraCorpora(Corpora.begin() + 1, Corpora.end()); + + assert(MaxInputLen > 0); + UnitVector Initial, Extra; + ReadDirToVectorOfUnits(Corpora[0].c_str(), &Initial, nullptr, MaxInputLen, + true); + for (auto &C : ExtraCorpora) + ReadDirToVectorOfUnits(C.c_str(), &Extra, nullptr, MaxInputLen, true); + + if (!Initial.empty()) { + Printf("=== Minimizing the initial corpus of %zd units\n", Initial.size()); + Initial = FindExtraUnits({}, Initial); + } + + Printf("=== Merging extra %zd units\n", Extra.size()); + auto Res = FindExtraUnits(Initial, Extra); + + for (auto &U: Res) + WriteToOutputCorpus(U); + + Printf("=== Merge: written %zd units\n", Res.size()); +} + +// Tries detecting a memory leak on the particular input that we have just +// executed before calling this function. +void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, + bool DuringInitialCorpusExecution) { + if (!HasMoreMallocsThanFrees) return; // mallocs==frees, a leak is unlikely. + if (!Options.DetectLeaks) return; + if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) || + !(EF->__lsan_do_recoverable_leak_check)) + return; // No lsan. + // Run the target once again, but with lsan disabled so that if there is + // a real leak we do not report it twice. + EF->__lsan_disable(); + ExecuteCallback(Data, Size); + EF->__lsan_enable(); + if (!HasMoreMallocsThanFrees) return; // a leak is unlikely. + if (NumberOfLeakDetectionAttempts++ > 1000) { + Options.DetectLeaks = false; + Printf("INFO: libFuzzer disabled leak detection after every mutation.\n" + " Most likely the target function accumulates allocated\n" + " memory in a global state w/o actually leaking it.\n" + " You may try running this binary with -trace_malloc=[12]" + " to get a trace of mallocs and frees.\n" + " If LeakSanitizer is enabled in this process it will still\n" + " run on the process shutdown.\n"); + return; + } + // Now perform the actual lsan pass. This is expensive and we must ensure + // we don't call it too often. + if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it. + if (DuringInitialCorpusExecution) + Printf("\nINFO: a leak has been found in the initial corpus.\n\n"); + Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n"); + CurrentUnitSize = Size; + DumpCurrentUnit("leak-"); + PrintFinalStats(); + _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on. + } +} + +void Fuzzer::MutateAndTestOne() { + MD.StartMutationSequence(); + + auto &II = Corpus.ChooseUnitToMutate(MD.GetRand()); + const auto &U = II.U; + memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1)); + assert(CurrentUnitData); + size_t Size = U.size(); + assert(Size <= MaxInputLen && "Oversized Unit"); + memcpy(CurrentUnitData, U.data(), Size); + + assert(MaxMutationLen > 0); + + for (int i = 0; i < Options.MutateDepth; i++) { + if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) + break; + size_t NewSize = 0; + NewSize = MD.Mutate(CurrentUnitData, Size, MaxMutationLen); + assert(NewSize > 0 && "Mutator returned empty unit"); + assert(NewSize <= MaxMutationLen && "Mutator return overisized unit"); + Size = NewSize; + if (i == 0) + StartTraceRecording(); + II.NumExecutedMutations++; + if (size_t NumFeatures = RunOne(CurrentUnitData, Size)) { + Corpus.AddToCorpus({CurrentUnitData, CurrentUnitData + Size}, NumFeatures, + /*MayDeleteFile=*/true); + ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size}); + CheckExitOnSrcPosOrItem(); + } + StopTraceRecording(); + TryDetectingAMemoryLeak(CurrentUnitData, Size, + /*DuringInitialCorpusExecution*/ false); + } +} + +void Fuzzer::ResetCoverage() { + ResetEdgeCoverage(); + MaxCoverage.Reset(); + PrepareCounters(&MaxCoverage); +} + +void Fuzzer::Loop() { + system_clock::time_point LastCorpusReload = system_clock::now(); + if (Options.DoCrossOver) + MD.SetCorpus(&Corpus); + while (true) { + auto Now = system_clock::now(); + if (duration_cast<seconds>(Now - LastCorpusReload).count() >= + Options.ReloadIntervalSec) { + RereadOutputCorpus(MaxInputLen); + LastCorpusReload = system_clock::now(); + } + if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) + break; + if (TimedOut()) break; + // Perform several mutations and runs. + MutateAndTestOne(); + } + + PrintStats("DONE ", "\n"); + MD.PrintRecommendedDictionary(); +} + +void Fuzzer::MinimizeCrashLoop(const Unit &U) { + if (U.size() <= 2) return; + while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) { + MD.StartMutationSequence(); + memcpy(CurrentUnitData, U.data(), U.size()); + for (int i = 0; i < Options.MutateDepth; i++) { + size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen); + assert(NewSize > 0 && NewSize <= MaxMutationLen); + RunOne(CurrentUnitData, NewSize); + TryDetectingAMemoryLeak(CurrentUnitData, NewSize, + /*DuringInitialCorpusExecution*/ false); + } + } +} + +} // namespace fuzzer + +extern "C" { + +size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { + assert(fuzzer::F); + return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize); +} +} // extern "C" diff --git a/test/fuzz_test/Fuzzer/FuzzerMain.cpp b/test/fuzz_test/Fuzzer/FuzzerMain.cpp new file mode 100644 index 00000000..af865720 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerMain.cpp @@ -0,0 +1,21 @@ +//===- FuzzerMain.cpp - main() function and flags -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// main() and flags. +//===----------------------------------------------------------------------===// + +#include "FuzzerDefs.h" + +extern "C" { +// This function should be defined by the user. +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); +} // extern "C" + +int main(int argc, char **argv) { + return fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput); +} diff --git a/test/fuzz_test/Fuzzer/FuzzerMerge.cpp b/test/fuzz_test/Fuzzer/FuzzerMerge.cpp new file mode 100644 index 00000000..84660e0f --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerMerge.cpp @@ -0,0 +1,261 @@ +//===- FuzzerMerge.cpp - merging corpora ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Merging corpora. +//===----------------------------------------------------------------------===// + +#include "FuzzerInternal.h" +#include "FuzzerIO.h" +#include "FuzzerMerge.h" +#include "FuzzerTracePC.h" +#include "FuzzerUtil.h" + +#include <fstream> +#include <iterator> +#include <sstream> + +namespace fuzzer { + +bool Merger::Parse(const std::string &Str, bool ParseCoverage) { + std::istringstream SS(Str); + return Parse(SS, ParseCoverage); +} + +void Merger::ParseOrExit(std::istream &IS, bool ParseCoverage) { + if (!Parse(IS, ParseCoverage)) { + Printf("MERGE: failed to parse the control file (unexpected error)\n"); + exit(1); + } +} + +// The control file example: +// +// 3 # The number of inputs +// 1 # The number of inputs in the first corpus, <= the previous number +// file0 +// file1 +// file2 # One file name per line. +// STARTED 0 123 # FileID, file size +// DONE 0 1 4 6 8 # FileID COV1 COV2 ... +// STARTED 1 456 # If DONE is missing, the input crashed while processing. +// STARTED 2 567 +// DONE 2 8 9 +bool Merger::Parse(std::istream &IS, bool ParseCoverage) { + LastFailure.clear(); + std::string Line; + + // Parse NumFiles. + if (!std::getline(IS, Line, '\n')) return false; + std::istringstream L1(Line); + size_t NumFiles = 0; + L1 >> NumFiles; + if (NumFiles == 0 || NumFiles > 10000000) return false; + + // Parse NumFilesInFirstCorpus. + if (!std::getline(IS, Line, '\n')) return false; + std::istringstream L2(Line); + NumFilesInFirstCorpus = NumFiles + 1; + L2 >> NumFilesInFirstCorpus; + if (NumFilesInFirstCorpus > NumFiles) return false; + + // Parse file names. + Files.resize(NumFiles); + for (size_t i = 0; i < NumFiles; i++) + if (!std::getline(IS, Files[i].Name, '\n')) + return false; + + // Parse STARTED and DONE lines. + size_t ExpectedStartMarker = 0; + const size_t kInvalidStartMarker = -1; + size_t LastSeenStartMarker = kInvalidStartMarker; + while (std::getline(IS, Line, '\n')) { + std::istringstream ISS1(Line); + std::string Marker; + size_t N; + ISS1 >> Marker; + ISS1 >> N; + if (Marker == "STARTED") { + // STARTED FILE_ID FILE_SIZE + if (ExpectedStartMarker != N) + return false; + ISS1 >> Files[ExpectedStartMarker].Size; + LastSeenStartMarker = ExpectedStartMarker; + assert(ExpectedStartMarker < Files.size()); + ExpectedStartMarker++; + } else if (Marker == "DONE") { + // DONE FILE_SIZE COV1 COV2 COV3 ... + size_t CurrentFileIdx = N; + if (CurrentFileIdx != LastSeenStartMarker) + return false; + LastSeenStartMarker = kInvalidStartMarker; + if (ParseCoverage) { + auto &V = Files[CurrentFileIdx].Features; + V.clear(); + while (ISS1 >> std::hex >> N) + V.push_back(N); + std::sort(V.begin(), V.end()); + } + } else { + return false; + } + } + if (LastSeenStartMarker != kInvalidStartMarker) + LastFailure = Files[LastSeenStartMarker].Name; + + FirstNotProcessedFile = ExpectedStartMarker; + return true; +} + +// Decides which files need to be merged (add thost to NewFiles). +// Returns the number of new features added. +size_t Merger::Merge(std::vector<std::string> *NewFiles) { + NewFiles->clear(); + assert(NumFilesInFirstCorpus <= Files.size()); + std::set<uint32_t> AllFeatures; + + // What features are in the initial corpus? + for (size_t i = 0; i < NumFilesInFirstCorpus; i++) { + auto &Cur = Files[i].Features; + AllFeatures.insert(Cur.begin(), Cur.end()); + } + size_t InitialNumFeatures = AllFeatures.size(); + + // Remove all features that we already know from all other inputs. + for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) { + auto &Cur = Files[i].Features; + std::vector<uint32_t> Tmp; + std::set_difference(Cur.begin(), Cur.end(), AllFeatures.begin(), + AllFeatures.end(), std::inserter(Tmp, Tmp.begin())); + Cur.swap(Tmp); + } + + // Sort. Give preference to + // * smaller files + // * files with more features. + std::sort(Files.begin() + NumFilesInFirstCorpus, Files.end(), + [&](const MergeFileInfo &a, const MergeFileInfo &b) -> bool { + if (a.Size != b.Size) + return a.Size < b.Size; + return a.Features.size() > b.Features.size(); + }); + + // One greedy pass: add the file's features to AllFeatures. + // If new features were added, add this file to NewFiles. + for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) { + auto &Cur = Files[i].Features; + // Printf("%s -> sz %zd ft %zd\n", Files[i].Name.c_str(), + // Files[i].Size, Cur.size()); + size_t OldSize = AllFeatures.size(); + AllFeatures.insert(Cur.begin(), Cur.end()); + if (AllFeatures.size() > OldSize) + NewFiles->push_back(Files[i].Name); + } + return AllFeatures.size() - InitialNumFeatures; +} + +// Inner process. May crash if the target crashes. +void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) { + Printf("MERGE-INNER: using the control file '%s'\n", CFPath.c_str()); + Merger M; + std::ifstream IF(CFPath); + M.ParseOrExit(IF, false); + IF.close(); + if (!M.LastFailure.empty()) + Printf("MERGE-INNER: '%s' caused a failure at the previous merge step\n", + M.LastFailure.c_str()); + + Printf("MERGE-INNER: %zd total files;" + " %zd processed earlier; will process %zd files now\n", + M.Files.size(), M.FirstNotProcessedFile, + M.Files.size() - M.FirstNotProcessedFile); + + std::ofstream OF(CFPath, std::ofstream::out | std::ofstream::app); + for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) { + auto U = FileToVector(M.Files[i].Name); + if (U.size() > MaxInputLen) { + U.resize(MaxInputLen); + U.shrink_to_fit(); + } + std::ostringstream StartedLine; + // Write the pre-run marker. + OF << "STARTED " << std::dec << i << " " << U.size() << "\n"; + OF.flush(); // Flush is important since ExecuteCommand may crash. + // Run. + TPC.ResetMaps(); + ExecuteCallback(U.data(), U.size()); + // Collect coverage. + std::set<size_t> Features; + TPC.CollectFeatures([&](size_t Feature) -> bool { + Features.insert(Feature); + return true; + }); + // Show stats. + TotalNumberOfRuns++; + if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1))) + PrintStats("pulse "); + // Write the post-run marker and the coverage. + OF << "DONE " << i; + for (size_t F : Features) + OF << " " << std::hex << F; + OF << "\n"; + } +} + +// Outer process. Does not call the target code and thus sohuld not fail. +void Fuzzer::CrashResistantMerge(const std::vector<std::string> &Args, + const std::vector<std::string> &Corpora) { + if (Corpora.size() <= 1) { + Printf("Merge requires two or more corpus dirs\n"); + return; + } + std::vector<std::string> AllFiles; + ListFilesInDirRecursive(Corpora[0], nullptr, &AllFiles, /*TopDir*/true); + size_t NumFilesInFirstCorpus = AllFiles.size(); + for (size_t i = 1; i < Corpora.size(); i++) + ListFilesInDirRecursive(Corpora[i], nullptr, &AllFiles, /*TopDir*/true); + Printf("MERGE-OUTER: %zd files, %zd in the initial corpus\n", + AllFiles.size(), NumFilesInFirstCorpus); + std::string CFPath = + "libFuzzerTemp." + std::to_string(GetPid()) + ".txt"; + // Write the control file. + RemoveFile(CFPath); + std::ofstream ControlFile(CFPath); + ControlFile << AllFiles.size() << "\n"; + ControlFile << NumFilesInFirstCorpus << "\n"; + for (auto &Path: AllFiles) + ControlFile << Path << "\n"; + ControlFile.close(); + + // Execute the inner process untill it passes. + // Every inner process should execute at least one input. + std::string BaseCmd = CloneArgsWithoutX(Args, "keep-all-flags"); + for (size_t i = 1; i <= AllFiles.size(); i++) { + Printf("MERGE-OUTER: attempt %zd\n", i); + auto ExitCode = + ExecuteCommand(BaseCmd + " -merge_control_file=" + CFPath); + if (!ExitCode) { + Printf("MERGE-OUTER: succesfull in %zd attempt(s)\n", i); + break; + } + } + // Read the control file and do the merge. + Merger M; + std::ifstream IF(CFPath); + M.ParseOrExit(IF, true); + IF.close(); + std::vector<std::string> NewFiles; + size_t NumNewFeatures = M.Merge(&NewFiles); + Printf("MERGE-OUTER: %zd new files with %zd new features added\n", + NewFiles.size(), NumNewFeatures); + for (auto &F: NewFiles) + WriteToOutputCorpus(FileToVector(F)); + // We are done, delete the control file. + RemoveFile(CFPath); +} + +} // namespace fuzzer diff --git a/test/fuzz_test/Fuzzer/FuzzerMerge.h b/test/fuzz_test/Fuzzer/FuzzerMerge.h new file mode 100644 index 00000000..8a2fe5d7 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerMerge.h @@ -0,0 +1,70 @@ +//===- FuzzerMerge.h - merging corpa ----------------------------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Merging Corpora. +// +// The task: +// Take the existing corpus (possibly empty) and merge new inputs into +// it so that only inputs with new coverage ('features') are added. +// The process should tolerate the crashes, OOMs, leaks, etc. +// +// Algorithm: +// The outter process collects the set of files and writes their names +// into a temporary "control" file, then repeatedly launches the inner +// process until all inputs are processed. +// The outer process does not actually execute the target code. +// +// The inner process reads the control file and sees a) list of all the inputs +// and b) the last processed input. Then it starts processing the inputs one +// by one. Before processing every input it writes one line to control file: +// STARTED INPUT_ID INPUT_SIZE +// After processing an input it write another line: +// DONE INPUT_ID Feature1 Feature2 Feature3 ... +// If a crash happens while processing an input the last line in the control +// file will be "STARTED INPUT_ID" and so the next process will know +// where to resume. +// +// Once all inputs are processed by the innner process(es) the outer process +// reads the control files and does the merge based entirely on the contents +// of control file. +// It uses a single pass greedy algorithm choosing first the smallest inputs +// within the same size the inputs that have more new features. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_MERGE_H +#define LLVM_FUZZER_MERGE_H + +#include "FuzzerDefs.h" + +#include <istream> +#include <set> + +namespace fuzzer { + +struct MergeFileInfo { + std::string Name; + size_t Size = 0; + std::vector<uint32_t> Features; +}; + +struct Merger { + std::vector<MergeFileInfo> Files; + size_t NumFilesInFirstCorpus = 0; + size_t FirstNotProcessedFile = 0; + std::string LastFailure; + + bool Parse(std::istream &IS, bool ParseCoverage); + bool Parse(const std::string &Str, bool ParseCoverage); + void ParseOrExit(std::istream &IS, bool ParseCoverage); + size_t Merge(std::vector<std::string> *NewFiles); +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_MERGE_H diff --git a/test/fuzz_test/Fuzzer/FuzzerMutate.cpp b/test/fuzz_test/Fuzzer/FuzzerMutate.cpp new file mode 100644 index 00000000..80b7a5f9 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerMutate.cpp @@ -0,0 +1,527 @@ +//===- FuzzerMutate.cpp - Mutate a test input -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Mutate a test input. +//===----------------------------------------------------------------------===// + +#include "FuzzerCorpus.h" +#include "FuzzerDefs.h" +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include "FuzzerMutate.h" +#include "FuzzerOptions.h" + +namespace fuzzer { + +const size_t Dictionary::kMaxDictSize; + +static void PrintASCII(const Word &W, const char *PrintAfter) { + PrintASCII(W.data(), W.size(), PrintAfter); +} + +MutationDispatcher::MutationDispatcher(Random &Rand, + const FuzzingOptions &Options) + : Rand(Rand), Options(Options) { + DefaultMutators.insert( + DefaultMutators.begin(), + { + {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"}, + {&MutationDispatcher::Mutate_InsertByte, "InsertByte"}, + {&MutationDispatcher::Mutate_InsertRepeatedBytes, + "InsertRepeatedBytes"}, + {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"}, + {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"}, + {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"}, + {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"}, + {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"}, + {&MutationDispatcher::Mutate_CopyPart, "CopyPart"}, + {&MutationDispatcher::Mutate_CrossOver, "CrossOver"}, + {&MutationDispatcher::Mutate_AddWordFromManualDictionary, + "ManualDict"}, + {&MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary, + "TempAutoDict"}, + {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary, + "PersAutoDict"}, + }); + if(Options.UseCmp) + DefaultMutators.push_back( + {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"}); + + if (EF->LLVMFuzzerCustomMutator) + Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"}); + else + Mutators = DefaultMutators; + + if (EF->LLVMFuzzerCustomCrossOver) + Mutators.push_back( + {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"}); +} + +static char RandCh(Random &Rand) { + if (Rand.RandBool()) return Rand(256); + const char *Special = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00"; + return Special[Rand(sizeof(Special) - 1)]; +} + +size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size, + size_t MaxSize) { + return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.Rand()); +} + +size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (!Corpus || Corpus->size() < 2 || Size == 0) + return 0; + size_t Idx = Rand(Corpus->size()); + const Unit &Other = (*Corpus)[Idx]; + if (Other.empty()) + return 0; + MutateInPlaceHere.resize(MaxSize); + auto &U = MutateInPlaceHere; + size_t NewSize = EF->LLVMFuzzerCustomCrossOver( + Data, Size, Other.data(), Other.size(), U.data(), U.size(), Rand.Rand()); + if (!NewSize) + return 0; + assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit"); + memcpy(Data, U.data(), NewSize); + return NewSize; +} + +size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + assert(Size); + size_t ShuffleAmount = + Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size. + size_t ShuffleStart = Rand(Size - ShuffleAmount); + assert(ShuffleStart + ShuffleAmount <= Size); + std::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, + Rand); + return Size; +} + +size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size, + size_t MaxSize) { + assert(Size); + if (Size == 1) return 0; + size_t N = Rand(Size / 2) + 1; + assert(N < Size); + size_t Idx = Rand(Size - N + 1); + // Erase Data[Idx:Idx+N]. + memmove(Data + Idx, Data + Idx + N, Size - Idx - N); + // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx); + return Size - N; +} + +size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size >= MaxSize) return 0; + size_t Idx = Rand(Size + 1); + // Insert new value at Data[Idx]. + memmove(Data + Idx + 1, Data + Idx, Size - Idx); + Data[Idx] = RandCh(Rand); + return Size + 1; +} + +size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data, + size_t Size, + size_t MaxSize) { + const size_t kMinBytesToInsert = 3; + if (Size + kMinBytesToInsert >= MaxSize) return 0; + size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128); + size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert; + assert(Size + N <= MaxSize && N); + size_t Idx = Rand(Size + 1); + // Insert new values at Data[Idx]. + memmove(Data + Idx + N, Data + Idx, Size - Idx); + // Give preference to 0x00 and 0xff. + uint8_t Byte = Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255); + for (size_t i = 0; i < N; i++) + Data[Idx + i] = Byte; + return Size + N; +} + +size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + size_t Idx = Rand(Size); + Data[Idx] = RandCh(Rand); + return Size; +} + +size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + size_t Idx = Rand(Size); + Data[Idx] ^= 1 << Rand(8); + return Size; +} + +size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data, + size_t Size, + size_t MaxSize) { + return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize); +} + +size_t MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary( + uint8_t *Data, size_t Size, size_t MaxSize) { + return AddWordFromDictionary(TempAutoDictionary, Data, Size, MaxSize); +} + +size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size, + size_t MaxSize, + DictionaryEntry &DE) { + const Word &W = DE.GetW(); + bool UsePositionHint = DE.HasPositionHint() && + DE.GetPositionHint() + W.size() < Size && + Rand.RandBool(); + if (Rand.RandBool()) { // Insert W. + if (Size + W.size() > MaxSize) return 0; + size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1); + memmove(Data + Idx + W.size(), Data + Idx, Size - Idx); + memcpy(Data + Idx, W.data(), W.size()); + Size += W.size(); + } else { // Overwrite some bytes with W. + if (W.size() > Size) return 0; + size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size - W.size()); + memcpy(Data + Idx, W.data(), W.size()); + } + return Size; +} + +// Somewhere in the past we have observed a comparison instructions +// with arguments Arg1 Arg2. This function tries to guess a dictionary +// entry that will satisfy that comparison. +// It first tries to find one of the arguments (possibly swapped) in the +// input and if it succeeds it creates a DE with a position hint. +// Otherwise it creates a DE with one of the arguments w/o a position hint. +template <class T> +DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP( + T Arg1, T Arg2, const uint8_t *Data, size_t Size) { + ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem; + bool HandleFirst = Rand.RandBool(); + T ExistingBytes, DesiredBytes; + Word W; + const uint8_t *End = Data + Size; + for (int Arg = 0; Arg < 2; Arg++) { + ExistingBytes = HandleFirst ? Arg1 : Arg2; + DesiredBytes = HandleFirst ? Arg2 : Arg1; + DesiredBytes += Rand(-1, 1); + if (Rand.RandBool()) ExistingBytes = Bswap(ExistingBytes); + if (Rand.RandBool()) DesiredBytes = Bswap(DesiredBytes); + HandleFirst = !HandleFirst; + W.Set(reinterpret_cast<uint8_t*>(&DesiredBytes), sizeof(T)); + const size_t kMaxNumPositions = 8; + size_t Positions[kMaxNumPositions]; + size_t NumPositions = 0; + for (const uint8_t *Cur = Data; + Cur < End && NumPositions < kMaxNumPositions; Cur++) { + Cur = (uint8_t *)SearchMemory(Cur, End - Cur, &ExistingBytes, sizeof(T)); + if (!Cur) break; + Positions[NumPositions++] = Cur - Data; + } + if (!NumPositions) break; + return DictionaryEntry(W, Positions[Rand(NumPositions)]); + } + DictionaryEntry DE(W); + return DE; +} + +size_t MutationDispatcher::Mutate_AddWordFromTORC( + uint8_t *Data, size_t Size, size_t MaxSize) { + Word W; + DictionaryEntry DE; + if (Rand.RandBool()) { + auto X = TPC.TORC8.Get(Rand.Rand()); + DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); + } else { + auto X = TPC.TORC4.Get(Rand.Rand()); + if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool()) + DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, + Size); + else + DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); + } + Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE); + if (!Size) return 0; + DictionaryEntry &DERef = + CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ % + kCmpDictionaryEntriesDequeSize]; + DERef = DE; + CurrentDictionaryEntrySequence.push_back(&DERef); + return Size; +} + +size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary( + uint8_t *Data, size_t Size, size_t MaxSize) { + return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize); +} + +size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data, + size_t Size, size_t MaxSize) { + if (Size > MaxSize) return 0; + if (D.empty()) return 0; + DictionaryEntry &DE = D[Rand(D.size())]; + Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE); + if (!Size) return 0; + DE.IncUseCount(); + CurrentDictionaryEntrySequence.push_back(&DE); + return Size; +} + +// Overwrites part of To[0,ToSize) with a part of From[0,FromSize). +// Returns ToSize. +size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize, + uint8_t *To, size_t ToSize) { + // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize). + size_t ToBeg = Rand(ToSize); + size_t CopySize = Rand(ToSize - ToBeg) + 1; + assert(ToBeg + CopySize <= ToSize); + CopySize = std::min(CopySize, FromSize); + size_t FromBeg = Rand(FromSize - CopySize + 1); + assert(FromBeg + CopySize <= FromSize); + memmove(To + ToBeg, From + FromBeg, CopySize); + return ToSize; +} + +// Inserts part of From[0,ToSize) into To. +// Returns new size of To on success or 0 on failure. +size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize, + uint8_t *To, size_t ToSize, + size_t MaxToSize) { + if (ToSize >= MaxToSize) return 0; + size_t AvailableSpace = MaxToSize - ToSize; + size_t MaxCopySize = std::min(AvailableSpace, FromSize); + size_t CopySize = Rand(MaxCopySize) + 1; + size_t FromBeg = Rand(FromSize - CopySize + 1); + assert(FromBeg + CopySize <= FromSize); + size_t ToInsertPos = Rand(ToSize + 1); + assert(ToInsertPos + CopySize <= MaxToSize); + size_t TailSize = ToSize - ToInsertPos; + if (To == From) { + MutateInPlaceHere.resize(MaxToSize); + memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize); + memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize); + memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize); + } else { + memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize); + memmove(To + ToInsertPos, From + FromBeg, CopySize); + } + return ToSize + CopySize; +} + +size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + if (Rand.RandBool()) + return CopyPartOf(Data, Size, Data, Size); + else + return InsertPartOf(Data, Size, Data, Size, MaxSize); +} + +size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + size_t B = Rand(Size); + while (B < Size && !isdigit(Data[B])) B++; + if (B == Size) return 0; + size_t E = B; + while (E < Size && isdigit(Data[E])) E++; + assert(B < E); + // now we have digits in [B, E). + // strtol and friends don't accept non-zero-teminated data, parse it manually. + uint64_t Val = Data[B] - '0'; + for (size_t i = B + 1; i < E; i++) + Val = Val * 10 + Data[i] - '0'; + + // Mutate the integer value. + switch(Rand(5)) { + case 0: Val++; break; + case 1: Val--; break; + case 2: Val /= 2; break; + case 3: Val *= 2; break; + case 4: Val = Rand(Val * Val); break; + default: assert(0); + } + // Just replace the bytes with the new ones, don't bother moving bytes. + for (size_t i = B; i < E; i++) { + size_t Idx = E + B - i - 1; + assert(Idx >= B && Idx < E); + Data[Idx] = (Val % 10) + '0'; + Val /= 10; + } + return Size; +} + +template<class T> +size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) { + if (Size < sizeof(T)) return 0; + size_t Off = Rand(Size - sizeof(T) + 1); + assert(Off + sizeof(T) <= Size); + T Val; + if (Off < 64 && !Rand(4)) { + Val = Size; + if (Rand.RandBool()) + Val = Bswap(Val); + } else { + memcpy(&Val, Data + Off, sizeof(Val)); + T Add = Rand(21); + Add -= 10; + if (Rand.RandBool()) + Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes. + else + Val = Val + Add; // Add assuming current endiannes. + if (Add == 0 || Rand.RandBool()) // Maybe negate. + Val = -Val; + } + memcpy(Data + Off, &Val, sizeof(Val)); + return Size; +} + +size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data, + size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + switch (Rand(4)) { + case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand); + case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand); + case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand); + case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand); + default: assert(0); + } + return 0; +} + +size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size, + size_t MaxSize) { + if (Size > MaxSize) return 0; + if (!Corpus || Corpus->size() < 2 || Size == 0) return 0; + size_t Idx = Rand(Corpus->size()); + const Unit &O = (*Corpus)[Idx]; + if (O.empty()) return 0; + MutateInPlaceHere.resize(MaxSize); + auto &U = MutateInPlaceHere; + size_t NewSize = 0; + switch(Rand(3)) { + case 0: + NewSize = CrossOver(Data, Size, O.data(), O.size(), U.data(), U.size()); + break; + case 1: + NewSize = InsertPartOf(O.data(), O.size(), U.data(), U.size(), MaxSize); + if (NewSize) + break; + // LLVM_FALLTHROUGH; + case 2: + NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size()); + break; + default: assert(0); + } + assert(NewSize > 0 && "CrossOver returned empty unit"); + assert(NewSize <= MaxSize && "CrossOver returned overisized unit"); + memcpy(Data, U.data(), NewSize); + return NewSize; +} + +void MutationDispatcher::StartMutationSequence() { + CurrentMutatorSequence.clear(); + CurrentDictionaryEntrySequence.clear(); +} + +// Copy successful dictionary entries to PersistentAutoDictionary. +void MutationDispatcher::RecordSuccessfulMutationSequence() { + for (auto DE : CurrentDictionaryEntrySequence) { + // PersistentAutoDictionary.AddWithSuccessCountOne(DE); + DE->IncSuccessCount(); + // Linear search is fine here as this happens seldom. + if (!PersistentAutoDictionary.ContainsWord(DE->GetW())) + PersistentAutoDictionary.push_back({DE->GetW(), 1}); + } +} + +void MutationDispatcher::PrintRecommendedDictionary() { + std::vector<DictionaryEntry> V; + for (auto &DE : PersistentAutoDictionary) + if (!ManualDictionary.ContainsWord(DE.GetW())) + V.push_back(DE); + if (V.empty()) return; + Printf("###### Recommended dictionary. ######\n"); + for (auto &DE: V) { + Printf("\""); + PrintASCII(DE.GetW(), "\""); + Printf(" # Uses: %zd\n", DE.GetUseCount()); + } + Printf("###### End of recommended dictionary. ######\n"); +} + +void MutationDispatcher::PrintMutationSequence() { + Printf("MS: %zd ", CurrentMutatorSequence.size()); + for (auto M : CurrentMutatorSequence) + Printf("%s-", M.Name); + if (!CurrentDictionaryEntrySequence.empty()) { + Printf(" DE: "); + for (auto DE : CurrentDictionaryEntrySequence) { + Printf("\""); + PrintASCII(DE->GetW(), "\"-"); + } + } +} + +size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { + return MutateImpl(Data, Size, MaxSize, Mutators); +} + +size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size, + size_t MaxSize) { + return MutateImpl(Data, Size, MaxSize, DefaultMutators); +} + +// Mutates Data in place, returns new size. +size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size, + size_t MaxSize, + const std::vector<Mutator> &Mutators) { + assert(MaxSize > 0); + if (Size == 0) { + for (size_t i = 0; i < MaxSize; i++) + Data[i] = RandCh(Rand); + if (Options.OnlyASCII) + ToASCII(Data, MaxSize); + return MaxSize; + } + assert(Size > 0); + // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize), + // in which case they will return 0. + // Try several times before returning un-mutated data. + for (int Iter = 0; Iter < 100; Iter++) { + auto M = Mutators[Rand(Mutators.size())]; + size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize); + if (NewSize && NewSize <= MaxSize) { + if (Options.OnlyASCII) + ToASCII(Data, NewSize); + CurrentMutatorSequence.push_back(M); + return NewSize; + } + } + return std::min(Size, MaxSize); +} + +void MutationDispatcher::AddWordToManualDictionary(const Word &W) { + ManualDictionary.push_back( + {W, std::numeric_limits<size_t>::max()}); +} + +void MutationDispatcher::AddWordToAutoDictionary(DictionaryEntry DE) { + static const size_t kMaxAutoDictSize = 1 << 14; + if (TempAutoDictionary.size() >= kMaxAutoDictSize) return; + TempAutoDictionary.push_back(DE); +} + +void MutationDispatcher::ClearAutoDictionary() { + TempAutoDictionary.clear(); +} + +} // namespace fuzzer diff --git a/test/fuzz_test/Fuzzer/FuzzerMutate.h b/test/fuzz_test/Fuzzer/FuzzerMutate.h new file mode 100644 index 00000000..d3c0b001 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerMutate.h @@ -0,0 +1,145 @@ +//===- FuzzerMutate.h - Internal header for the Fuzzer ----------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// fuzzer::MutationDispatcher +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_MUTATE_H +#define LLVM_FUZZER_MUTATE_H + +#include "FuzzerDefs.h" +#include "FuzzerDictionary.h" +#include "FuzzerRandom.h" + +namespace fuzzer { + +class MutationDispatcher { +public: + MutationDispatcher(Random &Rand, const FuzzingOptions &Options); + ~MutationDispatcher() {} + /// Indicate that we are about to start a new sequence of mutations. + void StartMutationSequence(); + /// Print the current sequence of mutations. + void PrintMutationSequence(); + /// Indicate that the current sequence of mutations was successfull. + void RecordSuccessfulMutationSequence(); + /// Mutates data by invoking user-provided mutator. + size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by invoking user-provided crossover. + size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by shuffling bytes. + size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by erasing bytes. + size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by inserting a byte. + size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by inserting several repeated bytes. + size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by chanding one byte. + size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by chanding one bit. + size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize); + /// Mutates data by copying/inserting a part of data into a different place. + size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize); + + /// Mutates data by adding a word from the manual dictionary. + size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size, + size_t MaxSize); + + /// Mutates data by adding a word from the temporary automatic dictionary. + size_t Mutate_AddWordFromTemporaryAutoDictionary(uint8_t *Data, size_t Size, + size_t MaxSize); + + /// Mutates data by adding a word from the TORC. + size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize); + + /// Mutates data by adding a word from the persistent automatic dictionary. + size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size, + size_t MaxSize); + + /// Tries to find an ASCII integer in Data, changes it to another ASCII int. + size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize); + /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways. + size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize); + + /// CrossOver Data with some other element of the corpus. + size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize); + + /// Applies one of the configured mutations. + /// Returns the new size of data which could be up to MaxSize. + size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize); + /// Applies one of the default mutations. Provided as a service + /// to mutation authors. + size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize); + + /// Creates a cross-over of two pieces of Data, returns its size. + size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, + size_t Size2, uint8_t *Out, size_t MaxOutSize); + + void AddWordToManualDictionary(const Word &W); + + void AddWordToAutoDictionary(DictionaryEntry DE); + void ClearAutoDictionary(); + void PrintRecommendedDictionary(); + + void SetCorpus(const InputCorpus *Corpus) { this->Corpus = Corpus; } + + Random &GetRand() { return Rand; } + +private: + + struct Mutator { + size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max); + const char *Name; + }; + + size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size, + size_t MaxSize); + size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize, + const std::vector<Mutator> &Mutators); + + size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, + size_t ToSize, size_t MaxToSize); + size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, + size_t ToSize); + size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize, + DictionaryEntry &DE); + + template <class T> + DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2, + const uint8_t *Data, size_t Size); + + Random &Rand; + const FuzzingOptions &Options; + + // Dictionary provided by the user via -dict=DICT_FILE. + Dictionary ManualDictionary; + // Temporary dictionary modified by the fuzzer itself, + // recreated periodically. + Dictionary TempAutoDictionary; + // Persistent dictionary modified by the fuzzer, consists of + // entries that led to successfull discoveries in the past mutations. + Dictionary PersistentAutoDictionary; + + std::vector<Mutator> CurrentMutatorSequence; + std::vector<DictionaryEntry *> CurrentDictionaryEntrySequence; + + static const size_t kCmpDictionaryEntriesDequeSize = 16; + DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize]; + size_t CmpDictionaryEntriesDequeIdx = 0; + + const InputCorpus *Corpus = nullptr; + std::vector<uint8_t> MutateInPlaceHere; + + std::vector<Mutator> Mutators; + std::vector<Mutator> DefaultMutators; +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_MUTATE_H diff --git a/test/fuzz_test/Fuzzer/FuzzerOptions.h b/test/fuzz_test/Fuzzer/FuzzerOptions.h new file mode 100644 index 00000000..34e93fc3 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerOptions.h @@ -0,0 +1,68 @@ +//===- FuzzerOptions.h - Internal header for the Fuzzer ---------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// fuzzer::FuzzingOptions +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_OPTIONS_H +#define LLVM_FUZZER_OPTIONS_H + +#include "FuzzerDefs.h" + +namespace fuzzer { + +struct FuzzingOptions { + int Verbosity = 1; + size_t MaxLen = 0; + int UnitTimeoutSec = 300; + int TimeoutExitCode = 77; + int ErrorExitCode = 77; + int MaxTotalTimeSec = 0; + int RssLimitMb = 0; + bool DoCrossOver = true; + int MutateDepth = 5; + bool UseCounters = false; + bool UseIndirCalls = true; + bool UseMemcmp = true; + bool UseMemmem = true; + bool UseCmp = false; + bool UseValueProfile = false; + bool Shrink = false; + int ReloadIntervalSec = 1; + bool ShuffleAtStartUp = true; + bool PreferSmall = true; + size_t MaxNumberOfRuns = -1L; + int ReportSlowUnits = 10; + bool OnlyASCII = false; + std::string OutputCorpus; + std::string ArtifactPrefix = "./"; + std::string ExactArtifactPath; + std::string ExitOnSrcPos; + std::string ExitOnItem; + bool SaveArtifacts = true; + bool PrintNEW = true; // Print a status line when new units are found; + bool OutputCSV = false; + bool PrintNewCovPcs = false; + bool PrintFinalStats = false; + bool PrintCorpusStats = false; + bool PrintCoverage = false; + bool DumpCoverage = false; + bool DetectLeaks = true; + int TraceMalloc = 0; + bool HandleAbrt = false; + bool HandleBus = false; + bool HandleFpe = false; + bool HandleIll = false; + bool HandleInt = false; + bool HandleSegv = false; + bool HandleTerm = false; +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_OPTIONS_H diff --git a/test/fuzz_test/Fuzzer/FuzzerRandom.h b/test/fuzz_test/Fuzzer/FuzzerRandom.h new file mode 100644 index 00000000..b1be0bb9 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerRandom.h @@ -0,0 +1,36 @@ +//===- FuzzerRandom.h - Internal header for the Fuzzer ----------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// fuzzer::Random +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_RANDOM_H +#define LLVM_FUZZER_RANDOM_H + +#include <random> + +namespace fuzzer { +class Random { + public: + Random(unsigned int seed) : R(seed) {} + size_t Rand() { return R(); } + size_t RandBool() { return Rand() % 2; } + size_t operator()(size_t n) { return n ? Rand() % n : 0; } + intptr_t operator()(intptr_t From, intptr_t To) { + assert(From < To); + intptr_t RangeSize = To - From + 1; + return operator()(RangeSize) + From; + } + std::mt19937 &Get_mt19937() { return R; } + private: + std::mt19937 R; +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_RANDOM_H diff --git a/test/fuzz_test/Fuzzer/FuzzerSHA1.cpp b/test/fuzz_test/Fuzzer/FuzzerSHA1.cpp new file mode 100644 index 00000000..d2f8e811 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerSHA1.cpp @@ -0,0 +1,222 @@ +//===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This code is taken from public domain +// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c) +// and modified by adding anonymous namespace, adding an interface +// function fuzzer::ComputeSHA1() and removing unnecessary code. +// +// lib/Fuzzer can not use SHA1 implementation from openssl because +// openssl may not be available and because we may be fuzzing openssl itself. +// For the same reason we do not want to depend on SHA1 from LLVM tree. +//===----------------------------------------------------------------------===// + +#include "FuzzerSHA1.h" +#include "FuzzerDefs.h" + +/* This code is public-domain - it is based on libcrypt + * placed in the public domain by Wei Dai and other contributors. + */ + +#include <iomanip> +#include <sstream> +#include <stdint.h> +#include <string.h> + +namespace { // Added for LibFuzzer + +#ifdef __BIG_ENDIAN__ +# define SHA_BIG_ENDIAN +#elif defined __LITTLE_ENDIAN__ +/* override */ +#elif defined __BYTE_ORDER +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define SHA_BIG_ENDIAN +# endif +#else // ! defined __LITTLE_ENDIAN__ +# include <endian.h> // machine/endian.h +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define SHA_BIG_ENDIAN +# endif +#endif + + +/* header */ + +#define HASH_LENGTH 20 +#define BLOCK_LENGTH 64 + +typedef struct sha1nfo { + uint32_t buffer[BLOCK_LENGTH/4]; + uint32_t state[HASH_LENGTH/4]; + uint32_t byteCount; + uint8_t bufferOffset; + uint8_t keyBuffer[BLOCK_LENGTH]; + uint8_t innerHash[HASH_LENGTH]; +} sha1nfo; + +/* public API - prototypes - TODO: doxygen*/ + +/** + */ +void sha1_init(sha1nfo *s); +/** + */ +void sha1_writebyte(sha1nfo *s, uint8_t data); +/** + */ +void sha1_write(sha1nfo *s, const char *data, size_t len); +/** + */ +uint8_t* sha1_result(sha1nfo *s); + + +/* code */ +#define SHA1_K0 0x5a827999 +#define SHA1_K20 0x6ed9eba1 +#define SHA1_K40 0x8f1bbcdc +#define SHA1_K60 0xca62c1d6 + +void sha1_init(sha1nfo *s) { + s->state[0] = 0x67452301; + s->state[1] = 0xefcdab89; + s->state[2] = 0x98badcfe; + s->state[3] = 0x10325476; + s->state[4] = 0xc3d2e1f0; + s->byteCount = 0; + s->bufferOffset = 0; +} + +uint32_t sha1_rol32(uint32_t number, uint8_t bits) { + return ((number << bits) | (number >> (32-bits))); +} + +void sha1_hashBlock(sha1nfo *s) { + uint8_t i; + uint32_t a,b,c,d,e,t; + + a=s->state[0]; + b=s->state[1]; + c=s->state[2]; + d=s->state[3]; + e=s->state[4]; + for (i=0; i<80; i++) { + if (i>=16) { + t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; + s->buffer[i&15] = sha1_rol32(t,1); + } + if (i<20) { + t = (d ^ (b & (c ^ d))) + SHA1_K0; + } else if (i<40) { + t = (b ^ c ^ d) + SHA1_K20; + } else if (i<60) { + t = ((b & c) | (d & (b | c))) + SHA1_K40; + } else { + t = (b ^ c ^ d) + SHA1_K60; + } + t+=sha1_rol32(a,5) + e + s->buffer[i&15]; + e=d; + d=c; + c=sha1_rol32(b,30); + b=a; + a=t; + } + s->state[0] += a; + s->state[1] += b; + s->state[2] += c; + s->state[3] += d; + s->state[4] += e; +} + +void sha1_addUncounted(sha1nfo *s, uint8_t data) { + uint8_t * const b = (uint8_t*) s->buffer; +#ifdef SHA_BIG_ENDIAN + b[s->bufferOffset] = data; +#else + b[s->bufferOffset ^ 3] = data; +#endif + s->bufferOffset++; + if (s->bufferOffset == BLOCK_LENGTH) { + sha1_hashBlock(s); + s->bufferOffset = 0; + } +} + +void sha1_writebyte(sha1nfo *s, uint8_t data) { + ++s->byteCount; + sha1_addUncounted(s, data); +} + +void sha1_write(sha1nfo *s, const char *data, size_t len) { + for (;len--;) sha1_writebyte(s, (uint8_t) *data++); +} + +void sha1_pad(sha1nfo *s) { + // Implement SHA-1 padding (fips180-2 §5.1.1) + + // Pad with 0x80 followed by 0x00 until the end of the block + sha1_addUncounted(s, 0x80); + while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); + + // Append length in the last 8 bytes + sha1_addUncounted(s, 0); // We're only using 32 bit lengths + sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths + sha1_addUncounted(s, 0); // So zero pad the top bits + sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 + sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as + sha1_addUncounted(s, s->byteCount >> 13); // byte. + sha1_addUncounted(s, s->byteCount >> 5); + sha1_addUncounted(s, s->byteCount << 3); +} + +uint8_t* sha1_result(sha1nfo *s) { + // Pad to complete the last block + sha1_pad(s); + +#ifndef SHA_BIG_ENDIAN + // Swap byte order back + int i; + for (i=0; i<5; i++) { + s->state[i]= + (((s->state[i])<<24)& 0xff000000) + | (((s->state[i])<<8) & 0x00ff0000) + | (((s->state[i])>>8) & 0x0000ff00) + | (((s->state[i])>>24)& 0x000000ff); + } +#endif + + // Return pointer to hash (20 characters) + return (uint8_t*) s->state; +} + +} // namespace; Added for LibFuzzer + +namespace fuzzer { + +// The rest is added for LibFuzzer +void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) { + sha1nfo s; + sha1_init(&s); + sha1_write(&s, (const char*)Data, Len); + memcpy(Out, sha1_result(&s), HASH_LENGTH); +} + +std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) { + std::stringstream SS; + for (int i = 0; i < kSHA1NumBytes; i++) + SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i]; + return SS.str(); +} + +std::string Hash(const Unit &U) { + uint8_t Hash[kSHA1NumBytes]; + ComputeSHA1(U.data(), U.size(), Hash); + return Sha1ToString(Hash); +} + +} diff --git a/test/fuzz_test/Fuzzer/FuzzerSHA1.h b/test/fuzz_test/Fuzzer/FuzzerSHA1.h new file mode 100644 index 00000000..3b5e6e80 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerSHA1.h @@ -0,0 +1,33 @@ +//===- FuzzerSHA1.h - Internal header for the SHA1 utils --------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// SHA1 utils. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_SHA1_H +#define LLVM_FUZZER_SHA1_H + +#include "FuzzerDefs.h" +#include <cstddef> +#include <stdint.h> + +namespace fuzzer { + +// Private copy of SHA1 implementation. +static const int kSHA1NumBytes = 20; + +// Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'. +void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out); + +std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]); + +std::string Hash(const Unit &U); + +} // namespace fuzzer + +#endif // LLVM_FUZZER_SHA1_H diff --git a/test/fuzz_test/Fuzzer/FuzzerTracePC.cpp b/test/fuzz_test/Fuzzer/FuzzerTracePC.cpp new file mode 100644 index 00000000..81c084b5 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerTracePC.cpp @@ -0,0 +1,339 @@ +//===- FuzzerTracePC.cpp - PC tracing--------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Trace PCs. +// This module implements __sanitizer_cov_trace_pc_guard[_init], +// the callback required for -fsanitize-coverage=trace-pc-guard instrumentation. +// +//===----------------------------------------------------------------------===// + +#include "FuzzerCorpus.h" +#include "FuzzerDefs.h" +#include "FuzzerDictionary.h" +#include "FuzzerExtFunctions.h" +#include "FuzzerIO.h" +#include "FuzzerTracePC.h" +#include "FuzzerValueBitMap.h" +#include <map> +#include <sanitizer/coverage_interface.h> +#include <set> +#include <sstream> + +namespace fuzzer { + +TracePC TPC; + +void TracePC::HandleTrace(uint32_t *Guard, uintptr_t PC) { + uint32_t Idx = *Guard; + if (!Idx) return; + PCs[Idx % kNumPCs] = PC; + Counters[Idx % kNumCounters]++; +} + +size_t TracePC::GetTotalPCCoverage() { + size_t Res = 0; + for (size_t i = 1; i < GetNumPCs(); i++) + if (PCs[i]) + Res++; + return Res; +} + +void TracePC::HandleInit(uint32_t *Start, uint32_t *Stop) { + if (Start == Stop || *Start) return; + assert(NumModules < sizeof(Modules) / sizeof(Modules[0])); + for (uint32_t *P = Start; P < Stop; P++) + *P = ++NumGuards; + Modules[NumModules].Start = Start; + Modules[NumModules].Stop = Stop; + NumModules++; +} + +void TracePC::PrintModuleInfo() { + Printf("INFO: Loaded %zd modules (%zd guards): ", NumModules, NumGuards); + for (size_t i = 0; i < NumModules; i++) + Printf("[%p, %p), ", Modules[i].Start, Modules[i].Stop); + Printf("\n"); +} + +void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) { + const uintptr_t kBits = 12; + const uintptr_t kMask = (1 << kBits) - 1; + uintptr_t Idx = (Caller & kMask) | ((Callee & kMask) << kBits); + HandleValueProfile(Idx); +} + +static bool IsInterestingCoverageFile(std::string &File) { + if (File.find("compiler-rt/lib/") != std::string::npos) + return false; // sanitizer internal. + if (File.find("/usr/lib/") != std::string::npos) + return false; + if (File.find("/usr/include/") != std::string::npos) + return false; + if (File == "<null>") + return false; + return true; +} + +void TracePC::PrintNewPCs() { + if (DoPrintNewPCs) { + if (!PrintedPCs) + PrintedPCs = new std::set<uintptr_t>; + for (size_t i = 1; i < GetNumPCs(); i++) + if (PCs[i] && PrintedPCs->insert(PCs[i]).second) + PrintPC("\tNEW_PC: %p %F %L\n", "\tNEW_PC: %p\n", PCs[i]); + } +} + +void TracePC::PrintCoverage() { + if (!EF->__sanitizer_symbolize_pc || + !EF->__sanitizer_get_module_and_offset_for_pc) { + Printf("INFO: __sanitizer_symbolize_pc or " + "__sanitizer_get_module_and_offset_for_pc is not available," + " not printing coverage\n"); + return; + } + std::map<std::string, std::vector<uintptr_t>> CoveredPCsPerModule; + std::map<std::string, uintptr_t> ModuleOffsets; + std::set<std::string> CoveredDirs, CoveredFiles, CoveredFunctions, + CoveredLines; + Printf("COVERAGE:\n"); + for (size_t i = 1; i < GetNumPCs(); i++) { + if (!PCs[i]) continue; + std::string FileStr = DescribePC("%s", PCs[i]); + if (!IsInterestingCoverageFile(FileStr)) continue; + std::string FixedPCStr = DescribePC("%p", PCs[i]); + std::string FunctionStr = DescribePC("%F", PCs[i]); + std::string LineStr = DescribePC("%l", PCs[i]); + char ModulePathRaw[4096] = ""; // What's PATH_MAX in portable C++? + void *OffsetRaw = nullptr; + if (!EF->__sanitizer_get_module_and_offset_for_pc( + reinterpret_cast<void *>(PCs[i]), ModulePathRaw, + sizeof(ModulePathRaw), &OffsetRaw)) + continue; + std::string Module = ModulePathRaw; + uintptr_t FixedPC = std::stol(FixedPCStr, 0, 16); + uintptr_t PcOffset = reinterpret_cast<uintptr_t>(OffsetRaw); + ModuleOffsets[Module] = FixedPC - PcOffset; + CoveredPCsPerModule[Module].push_back(PcOffset); + CoveredFunctions.insert(FunctionStr); + CoveredFiles.insert(FileStr); + CoveredDirs.insert(DirName(FileStr)); + if (!CoveredLines.insert(FileStr + ":" + LineStr).second) + continue; + Printf("COVERED: %s %s:%s\n", FunctionStr.c_str(), + FileStr.c_str(), LineStr.c_str()); + } + + std::string CoveredDirsStr; + for (auto &Dir : CoveredDirs) { + if (!CoveredDirsStr.empty()) + CoveredDirsStr += ","; + CoveredDirsStr += Dir; + } + Printf("COVERED_DIRS: %s\n", CoveredDirsStr.c_str()); + + for (auto &M : CoveredPCsPerModule) { + std::set<std::string> UncoveredFiles, UncoveredFunctions; + std::map<std::string, std::set<int> > UncoveredLines; // Func+File => lines + auto &ModuleName = M.first; + auto &CoveredOffsets = M.second; + uintptr_t ModuleOffset = ModuleOffsets[ModuleName]; + std::sort(CoveredOffsets.begin(), CoveredOffsets.end()); + Printf("MODULE_WITH_COVERAGE: %s\n", ModuleName.c_str()); + // sancov does not yet fully support DSOs. + // std::string Cmd = "sancov -print-coverage-pcs " + ModuleName; + std::string Cmd = "objdump -d " + ModuleName + + " | grep 'call.*__sanitizer_cov_trace_pc_guard' | awk -F: '{print $1}'"; + std::string SanCovOutput; + if (!ExecuteCommandAndReadOutput(Cmd, &SanCovOutput)) { + Printf("INFO: Command failed: %s\n", Cmd.c_str()); + continue; + } + std::istringstream ISS(SanCovOutput); + std::string S; + while (std::getline(ISS, S, '\n')) { + uintptr_t PcOffset = std::stol(S, 0, 16); + if (!std::binary_search(CoveredOffsets.begin(), CoveredOffsets.end(), + PcOffset)) { + uintptr_t PC = ModuleOffset + PcOffset; + auto FileStr = DescribePC("%s", PC); + if (!IsInterestingCoverageFile(FileStr)) continue; + if (CoveredFiles.count(FileStr) == 0) { + UncoveredFiles.insert(FileStr); + continue; + } + auto FunctionStr = DescribePC("%F", PC); + if (CoveredFunctions.count(FunctionStr) == 0) { + UncoveredFunctions.insert(FunctionStr); + continue; + } + std::string LineStr = DescribePC("%l", PC); + uintptr_t Line = std::stoi(LineStr); + std::string FileLineStr = FileStr + ":" + LineStr; + if (CoveredLines.count(FileLineStr) == 0) + UncoveredLines[FunctionStr + " " + FileStr].insert(Line); + } + } + for (auto &FileLine: UncoveredLines) + for (int Line : FileLine.second) + Printf("UNCOVERED_LINE: %s:%d\n", FileLine.first.c_str(), Line); + for (auto &Func : UncoveredFunctions) + Printf("UNCOVERED_FUNC: %s\n", Func.c_str()); + for (auto &File : UncoveredFiles) + Printf("UNCOVERED_FILE: %s\n", File.c_str()); + } +} + +void TracePC::DumpCoverage() { + __sanitizer_dump_coverage(PCs, GetNumPCs()); +} + +// Value profile. +// We keep track of various values that affect control flow. +// These values are inserted into a bit-set-based hash map. +// Every new bit in the map is treated as a new coverage. +// +// For memcmp/strcmp/etc the interesting value is the length of the common +// prefix of the parameters. +// For cmp instructions the interesting value is a XOR of the parameters. +// The interesting value is mixed up with the PC and is then added to the map. + +ATTRIBUTE_NO_SANITIZE_MEMORY +void TracePC::AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2, + size_t n) { + if (!n) return; + size_t Len = std::min(n, (size_t)32); + const uint8_t *A1 = reinterpret_cast<const uint8_t *>(s1); + const uint8_t *A2 = reinterpret_cast<const uint8_t *>(s2); + size_t I = 0; + for (; I < Len; I++) + if (A1[I] != A2[I]) + break; + size_t PC = reinterpret_cast<size_t>(caller_pc); + size_t Idx = I; + // if (I < Len) + // Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1; + TPC.HandleValueProfile((PC & 4095) | (Idx << 12)); +} + +ATTRIBUTE_NO_SANITIZE_MEMORY +void TracePC::AddValueForStrcmp(void *caller_pc, const char *s1, const char *s2, + size_t n) { + if (!n) return; + size_t Len = std::min(n, (size_t)32); + const uint8_t *A1 = reinterpret_cast<const uint8_t *>(s1); + const uint8_t *A2 = reinterpret_cast<const uint8_t *>(s2); + size_t I = 0; + for (; I < Len; I++) + if (A1[I] != A2[I] || A1[I] == 0) + break; + size_t PC = reinterpret_cast<size_t>(caller_pc); + size_t Idx = I; + // if (I < Len && A1[I]) + // Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1; + TPC.HandleValueProfile((PC & 4095) | (Idx << 12)); +} + +template <class T> +ATTRIBUTE_TARGET_POPCNT +#ifdef __clang__ // g++ can't handle this __attribute__ here :( +__attribute__((always_inline)) +#endif // __clang__ +void TracePC::HandleCmp(void *PC, T Arg1, T Arg2) { + uintptr_t PCuint = reinterpret_cast<uintptr_t>(PC); + uint64_t ArgXor = Arg1 ^ Arg2; + uint64_t ArgDistance = __builtin_popcountl(ArgXor) + 1; // [1,65] + uintptr_t Idx = ((PCuint & 4095) + 1) * ArgDistance; + if (sizeof(T) == 4) + TORC4.Insert(ArgXor, Arg1, Arg2); + else if (sizeof(T) == 8) + TORC8.Insert(ArgXor, Arg1, Arg2); + HandleValueProfile(Idx); +} + +} // namespace fuzzer + +extern "C" { +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) { + uintptr_t PC = (uintptr_t)__builtin_return_address(0); + fuzzer::TPC.HandleTrace(Guard, PC); +} + +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) { + fuzzer::TPC.HandleInit(Start, Stop); +} + +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) { + uintptr_t PC = (uintptr_t)__builtin_return_address(0); + fuzzer::TPC.HandleCallerCallee(PC, Callee); +} + +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) { + fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2); +} +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) { + fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2); +} +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) { + fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2); +} +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) { + fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2); +} + +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) { + // Updates the value profile based on the relative position of Val and Cases. + // We want to handle one random case at every call (handling all is slow). + // Since none of the arguments contain any random bits we use a thread-local + // counter to choose the random case to handle. + static thread_local size_t Counter; + Counter++; + uint64_t N = Cases[0]; + uint64_t *Vals = Cases + 2; + char *PC = (char*)__builtin_return_address(0); + // We need a random number < N using Counter as a seed. But w/o DIV. + // * find a power of two >= N + // * mask Counter with this power of two. + // * maybe subtract N. + size_t Nlog = sizeof(long) * 8 - __builtin_clzl((long)N); + size_t PowerOfTwoGeN = 1U << Nlog; + assert(PowerOfTwoGeN >= N); + size_t Idx = Counter & (PowerOfTwoGeN - 1); + if (Idx >= N) + Idx -= N; + assert(Idx < N); + uint64_t TwoIn32 = 1ULL << 32; + if ((Val | Vals[Idx]) < TwoIn32) + fuzzer::TPC.HandleCmp(PC + Idx, static_cast<uint32_t>(Val), + static_cast<uint32_t>(Vals[Idx])); + else + fuzzer::TPC.HandleCmp(PC + Idx, Val, Vals[Idx]); +} + +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_div4(uint32_t Val) { + fuzzer::TPC.HandleCmp(__builtin_return_address(0), Val, (uint32_t)0); +} +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_div8(uint64_t Val) { + fuzzer::TPC.HandleCmp(__builtin_return_address(0), Val, (uint64_t)0); +} +__attribute__((visibility("default"))) +void __sanitizer_cov_trace_gep(uintptr_t Idx) { + fuzzer::TPC.HandleCmp(__builtin_return_address(0), Idx, (uintptr_t)0); +} + +} // extern "C" diff --git a/test/fuzz_test/Fuzzer/FuzzerTracePC.h b/test/fuzz_test/Fuzzer/FuzzerTracePC.h new file mode 100644 index 00000000..68827f80 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerTracePC.h @@ -0,0 +1,158 @@ +//===- FuzzerTracePC.h - Internal header for the Fuzzer ---------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// fuzzer::TracePC +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_TRACE_PC +#define LLVM_FUZZER_TRACE_PC + +#include "FuzzerDefs.h" +#include "FuzzerValueBitMap.h" +#include <set> + +namespace fuzzer { + +// TableOfRecentCompares (TORC) remembers the most recently performed +// comparisons of type T. +// We record the arguments of CMP instructions in this table unconditionally +// because it seems cheaper this way than to compute some expensive +// conditions inside __sanitizer_cov_trace_cmp*. +// After the unit has been executed we may decide to use the contents of +// this table to populate a Dictionary. +template<class T, size_t kSizeT> +struct TableOfRecentCompares { + static const size_t kSize = kSizeT; + struct Pair { + T A, B; + }; + void Insert(size_t Idx, T Arg1, T Arg2) { + Idx = Idx % kSize; + Table[Idx].A = Arg1; + Table[Idx].B = Arg2; + } + + Pair Get(size_t I) { return Table[I % kSize]; } + + Pair Table[kSize]; +}; + +class TracePC { + public: + static const size_t kFeatureSetSize = ValueBitMap::kNumberOfItems; + + void HandleTrace(uint32_t *guard, uintptr_t PC); + void HandleInit(uint32_t *start, uint32_t *stop); + void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee); + void HandleValueProfile(size_t Value) { ValueProfileMap.AddValue(Value); } + template <class T> void HandleCmp(void *PC, T Arg1, T Arg2); + size_t GetTotalPCCoverage(); + void SetUseCounters(bool UC) { UseCounters = UC; } + void SetUseValueProfile(bool VP) { UseValueProfile = VP; } + void SetPrintNewPCs(bool P) { DoPrintNewPCs = P; } + template <class Callback> size_t CollectFeatures(Callback CB); + bool UpdateValueProfileMap(ValueBitMap *MaxValueProfileMap) { + return UseValueProfile && MaxValueProfileMap->MergeFrom(ValueProfileMap); + } + + void ResetMaps() { + ValueProfileMap.Reset(); + memset(Counters, 0, sizeof(Counters)); + } + + void UpdateFeatureSet(size_t CurrentElementIdx, size_t CurrentElementSize); + void PrintFeatureSet(); + + void PrintModuleInfo(); + + void PrintCoverage(); + void DumpCoverage(); + + void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2, + size_t n); + void AddValueForStrcmp(void *caller_pc, const char *s1, const char *s2, + size_t n); + + bool UsingTracePcGuard() const {return NumModules; } + + static const size_t kTORCSize = 1 << 5; + TableOfRecentCompares<uint32_t, kTORCSize> TORC4; + TableOfRecentCompares<uint64_t, kTORCSize> TORC8; + + void PrintNewPCs(); + size_t GetNumPCs() const { return Min(kNumPCs, NumGuards + 1); } + uintptr_t GetPC(size_t Idx) { + assert(Idx < GetNumPCs()); + return PCs[Idx]; + } + +private: + bool UseCounters = false; + bool UseValueProfile = false; + bool DoPrintNewPCs = false; + + struct Module { + uint32_t *Start, *Stop; + }; + + Module Modules[4096]; + size_t NumModules; // linker-initialized. + size_t NumGuards; // linker-initialized. + + static const size_t kNumCounters = 1 << 14; + alignas(8) uint8_t Counters[kNumCounters]; + + static const size_t kNumPCs = 1 << 24; + uintptr_t PCs[kNumPCs]; + + std::set<uintptr_t> *PrintedPCs; + + ValueBitMap ValueProfileMap; +}; + +template <class Callback> +size_t TracePC::CollectFeatures(Callback CB) { + if (!UsingTracePcGuard()) return 0; + size_t Res = 0; + const size_t Step = 8; + assert(reinterpret_cast<uintptr_t>(Counters) % Step == 0); + size_t N = Min(kNumCounters, NumGuards + 1); + N = (N + Step - 1) & ~(Step - 1); // Round up. + for (size_t Idx = 0; Idx < N; Idx += Step) { + uint64_t Bundle = *reinterpret_cast<uint64_t*>(&Counters[Idx]); + if (!Bundle) continue; + for (size_t i = Idx; i < Idx + Step; i++) { + uint8_t Counter = (Bundle >> ((i - Idx) * 8)) & 0xff; + if (!Counter) continue; + Counters[i] = 0; + unsigned Bit = 0; + /**/ if (Counter >= 128) Bit = 7; + else if (Counter >= 32) Bit = 6; + else if (Counter >= 16) Bit = 5; + else if (Counter >= 8) Bit = 4; + else if (Counter >= 4) Bit = 3; + else if (Counter >= 3) Bit = 2; + else if (Counter >= 2) Bit = 1; + size_t Feature = (i * 8 + Bit); + if (CB(Feature)) + Res++; + } + } + if (UseValueProfile) + ValueProfileMap.ForEach([&](size_t Idx) { + if (CB(NumGuards * 8 + Idx)) + Res++; + }); + return Res; +} + +extern TracePC TPC; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_TRACE_PC diff --git a/test/fuzz_test/Fuzzer/FuzzerTraceState.cpp b/test/fuzz_test/Fuzzer/FuzzerTraceState.cpp new file mode 100644 index 00000000..be62a662 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerTraceState.cpp @@ -0,0 +1,325 @@ +//===- FuzzerTraceState.cpp - Trace-based fuzzer mutator ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Data tracing. +//===----------------------------------------------------------------------===// + +#include "FuzzerDictionary.h" +#include "FuzzerInternal.h" +#include "FuzzerIO.h" +#include "FuzzerMutate.h" +#include "FuzzerRandom.h" +#include "FuzzerTracePC.h" +#include <algorithm> +#include <cstring> +#include <map> +#include <set> +#include <thread> + +namespace fuzzer { + +// For now, very simple: put Size bytes of Data at position Pos. +struct TraceBasedMutation { + uint32_t Pos; + Word W; +}; + +// Declared as static globals for faster checks inside the hooks. +static bool RecordingMemcmp = false; +static bool RecordingMemmem = false; +static bool DoingMyOwnMemmem = false; + +ScopedDoingMyOwnMemmem::ScopedDoingMyOwnMemmem() { DoingMyOwnMemmem = true; } +ScopedDoingMyOwnMemmem::~ScopedDoingMyOwnMemmem() { DoingMyOwnMemmem = false; } + +class TraceState { +public: + TraceState(MutationDispatcher &MD, const FuzzingOptions &Options, + const Fuzzer *F) + : MD(MD), Options(Options), F(F) {} + + void TraceMemcmpCallback(size_t CmpSize, const uint8_t *Data1, + const uint8_t *Data2); + + void TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits, uint64_t Val, + size_t NumCases, uint64_t *Cases); + int TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData, + size_t DataSize); + int TryToAddDesiredData(const uint8_t *PresentData, + const uint8_t *DesiredData, size_t DataSize); + + void StartTraceRecording() { + if (!Options.UseMemcmp) + return; + RecordingMemcmp = Options.UseMemcmp; + RecordingMemmem = Options.UseMemmem; + NumMutations = 0; + InterestingWords.clear(); + MD.ClearAutoDictionary(); + } + + void StopTraceRecording() { + if (!RecordingMemcmp) + return; + RecordingMemcmp = false; + for (size_t i = 0; i < NumMutations; i++) { + auto &M = Mutations[i]; + if (Options.Verbosity >= 2) { + AutoDictUnitCounts[M.W]++; + AutoDictAdds++; + if ((AutoDictAdds & (AutoDictAdds - 1)) == 0) { + typedef std::pair<size_t, Word> CU; + std::vector<CU> CountedUnits; + for (auto &I : AutoDictUnitCounts) + CountedUnits.push_back(std::make_pair(I.second, I.first)); + std::sort(CountedUnits.begin(), CountedUnits.end(), + [](const CU &a, const CU &b) { return a.first > b.first; }); + Printf("AutoDict:\n"); + for (auto &I : CountedUnits) { + Printf(" %zd ", I.first); + PrintASCII(I.second.data(), I.second.size()); + Printf("\n"); + } + } + } + MD.AddWordToAutoDictionary({M.W, M.Pos}); + } + for (auto &W : InterestingWords) + MD.AddWordToAutoDictionary({W}); + } + + void AddMutation(uint32_t Pos, uint32_t Size, const uint8_t *Data) { + if (NumMutations >= kMaxMutations) return; + auto &M = Mutations[NumMutations++]; + M.Pos = Pos; + M.W.Set(Data, Size); + } + + void AddMutation(uint32_t Pos, uint32_t Size, uint64_t Data) { + assert(Size <= sizeof(Data)); + AddMutation(Pos, Size, reinterpret_cast<uint8_t*>(&Data)); + } + + void AddInterestingWord(const uint8_t *Data, size_t Size) { + if (!RecordingMemmem || !F->InFuzzingThread()) return; + if (Size <= 1) return; + Size = std::min(Size, Word::GetMaxSize()); + Word W(Data, Size); + InterestingWords.insert(W); + } + + private: + bool IsTwoByteData(uint64_t Data) { + int64_t Signed = static_cast<int64_t>(Data); + Signed >>= 16; + return Signed == 0 || Signed == -1L; + } + + // We don't want to create too many trace-based mutations as it is both + // expensive and useless. So after some number of mutations is collected, + // start rejecting some of them. The more there are mutations the more we + // reject. + bool WantToHandleOneMoreMutation() { + const size_t FirstN = 64; + // Gladly handle first N mutations. + if (NumMutations <= FirstN) return true; + size_t Diff = NumMutations - FirstN; + size_t DiffLog = sizeof(long) * 8 - __builtin_clzl((long)Diff); + assert(DiffLog > 0 && DiffLog < 64); + bool WantThisOne = MD.GetRand()(1 << DiffLog) == 0; // 1 out of DiffLog. + return WantThisOne; + } + + static const size_t kMaxMutations = 1 << 16; + size_t NumMutations; + TraceBasedMutation Mutations[kMaxMutations]; + // TODO: std::set is too inefficient, need to have a custom DS here. + std::set<Word> InterestingWords; + MutationDispatcher &MD; + const FuzzingOptions Options; + const Fuzzer *F; + std::map<Word, size_t> AutoDictUnitCounts; + size_t AutoDictAdds = 0; +}; + +int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData, + size_t DataSize) { + if (NumMutations >= kMaxMutations || !WantToHandleOneMoreMutation()) return 0; + ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem; + const uint8_t *UnitData; + auto UnitSize = F->GetCurrentUnitInFuzzingThead(&UnitData); + int Res = 0; + const uint8_t *Beg = UnitData; + const uint8_t *End = Beg + UnitSize; + for (const uint8_t *Cur = Beg; Cur < End; Cur++) { + Cur = (uint8_t *)SearchMemory(Cur, End - Cur, &PresentData, DataSize); + if (!Cur) + break; + size_t Pos = Cur - Beg; + assert(Pos < UnitSize); + AddMutation(Pos, DataSize, DesiredData); + AddMutation(Pos, DataSize, DesiredData + 1); + AddMutation(Pos, DataSize, DesiredData - 1); + Res++; + } + return Res; +} + +int TraceState::TryToAddDesiredData(const uint8_t *PresentData, + const uint8_t *DesiredData, + size_t DataSize) { + if (NumMutations >= kMaxMutations || !WantToHandleOneMoreMutation()) return 0; + ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem; + const uint8_t *UnitData; + auto UnitSize = F->GetCurrentUnitInFuzzingThead(&UnitData); + int Res = 0; + const uint8_t *Beg = UnitData; + const uint8_t *End = Beg + UnitSize; + for (const uint8_t *Cur = Beg; Cur < End; Cur++) { + Cur = (uint8_t *)SearchMemory(Cur, End - Cur, PresentData, DataSize); + if (!Cur) + break; + size_t Pos = Cur - Beg; + assert(Pos < UnitSize); + AddMutation(Pos, DataSize, DesiredData); + Res++; + } + return Res; +} + +void TraceState::TraceMemcmpCallback(size_t CmpSize, const uint8_t *Data1, + const uint8_t *Data2) { + if (!RecordingMemcmp || !F->InFuzzingThread()) return; + CmpSize = std::min(CmpSize, Word::GetMaxSize()); + int Added2 = TryToAddDesiredData(Data1, Data2, CmpSize); + int Added1 = TryToAddDesiredData(Data2, Data1, CmpSize); + if ((Added1 || Added2) && Options.Verbosity >= 3) { + Printf("MemCmp Added %d%d: ", Added1, Added2); + if (Added1) PrintASCII(Data1, CmpSize); + if (Added2) PrintASCII(Data2, CmpSize); + Printf("\n"); + } +} + +void TraceState::TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits, + uint64_t Val, size_t NumCases, + uint64_t *Cases) { + if (F->InFuzzingThread()) return; + size_t ValSize = ValSizeInBits / 8; + bool TryShort = IsTwoByteData(Val); + for (size_t i = 0; i < NumCases; i++) + TryShort &= IsTwoByteData(Cases[i]); + + if (Options.Verbosity >= 3) + Printf("TraceSwitch: %p %zd # %zd; TryShort %d\n", PC, Val, NumCases, + TryShort); + + for (size_t i = 0; i < NumCases; i++) { + TryToAddDesiredData(Val, Cases[i], ValSize); + if (TryShort) + TryToAddDesiredData(Val, Cases[i], 2); + } +} + +static TraceState *TS; + +void Fuzzer::StartTraceRecording() { + if (!TS) return; + TS->StartTraceRecording(); +} + +void Fuzzer::StopTraceRecording() { + if (!TS) return; + TS->StopTraceRecording(); +} + +void Fuzzer::InitializeTraceState() { + if (!Options.UseMemcmp) return; + TS = new TraceState(MD, Options, this); +} + +static size_t InternalStrnlen(const char *S, size_t MaxLen) { + size_t Len = 0; + for (; Len < MaxLen && S[Len]; Len++) {} + return Len; +} + +} // namespace fuzzer + +using fuzzer::TS; +using fuzzer::RecordingMemcmp; + +extern "C" { + +// We may need to avoid defining weak hooks to stay compatible with older clang. +#ifndef LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS +# define LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS 1 +#endif + +#if LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS +void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1, + const void *s2, size_t n, int result) { + fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n); + if (!RecordingMemcmp) return; + if (result == 0) return; // No reason to mutate. + if (n <= 1) return; // Not interesting. + TS->TraceMemcmpCallback(n, reinterpret_cast<const uint8_t *>(s1), + reinterpret_cast<const uint8_t *>(s2)); +} + +void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1, + const char *s2, size_t n, int result) { + fuzzer::TPC.AddValueForStrcmp(caller_pc, s1, s2, n); + if (!RecordingMemcmp) return; + if (result == 0) return; // No reason to mutate. + size_t Len1 = fuzzer::InternalStrnlen(s1, n); + size_t Len2 = fuzzer::InternalStrnlen(s2, n); + n = std::min(n, Len1); + n = std::min(n, Len2); + if (n <= 1) return; // Not interesting. + TS->TraceMemcmpCallback(n, reinterpret_cast<const uint8_t *>(s1), + reinterpret_cast<const uint8_t *>(s2)); +} + +void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1, + const char *s2, int result) { + fuzzer::TPC.AddValueForStrcmp(caller_pc, s1, s2, 64); + if (!RecordingMemcmp) return; + if (result == 0) return; // No reason to mutate. + size_t Len1 = strlen(s1); + size_t Len2 = strlen(s2); + size_t N = std::min(Len1, Len2); + if (N <= 1) return; // Not interesting. + TS->TraceMemcmpCallback(N, reinterpret_cast<const uint8_t *>(s1), + reinterpret_cast<const uint8_t *>(s2)); +} + +void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, + const char *s2, size_t n, int result) { + return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result); +} +void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, + const char *s2, int result) { + return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result); +} +void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, + const char *s2, char *result) { + TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); +} +void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, + const char *s2, char *result) { + TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); +} +void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, + const void *s2, size_t len2, void *result) { + if (fuzzer::DoingMyOwnMemmem) return; + TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), len2); +} + +#endif // LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS +} // extern "C" diff --git a/test/fuzz_test/Fuzzer/FuzzerUtil.cpp b/test/fuzz_test/Fuzzer/FuzzerUtil.cpp new file mode 100644 index 00000000..f5fd3a85 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerUtil.cpp @@ -0,0 +1,218 @@ +//===- FuzzerUtil.cpp - Misc utils ----------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Misc utils. +//===----------------------------------------------------------------------===// + +#include "FuzzerUtil.h" +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include <cassert> +#include <chrono> +#include <cstring> +#include <errno.h> +#include <signal.h> +#include <sstream> +#include <stdio.h> +#include <sys/types.h> +#include <thread> + +namespace fuzzer { + +void PrintHexArray(const uint8_t *Data, size_t Size, + const char *PrintAfter) { + for (size_t i = 0; i < Size; i++) + Printf("0x%x,", (unsigned)Data[i]); + Printf("%s", PrintAfter); +} + +void Print(const Unit &v, const char *PrintAfter) { + PrintHexArray(v.data(), v.size(), PrintAfter); +} + +void PrintASCIIByte(uint8_t Byte) { + if (Byte == '\\') + Printf("\\\\"); + else if (Byte == '"') + Printf("\\\""); + else if (Byte >= 32 && Byte < 127) + Printf("%c", Byte); + else + Printf("\\x%02x", Byte); +} + +void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) { + for (size_t i = 0; i < Size; i++) + PrintASCIIByte(Data[i]); + Printf("%s", PrintAfter); +} + +void PrintASCII(const Unit &U, const char *PrintAfter) { + PrintASCII(U.data(), U.size(), PrintAfter); +} + +bool ToASCII(uint8_t *Data, size_t Size) { + bool Changed = false; + for (size_t i = 0; i < Size; i++) { + uint8_t &X = Data[i]; + auto NewX = X; + NewX &= 127; + if (!isspace(NewX) && !isprint(NewX)) + NewX = ' '; + Changed |= NewX != X; + X = NewX; + } + return Changed; +} + +bool IsASCII(const Unit &U) { return IsASCII(U.data(), U.size()); } + +bool IsASCII(const uint8_t *Data, size_t Size) { + for (size_t i = 0; i < Size; i++) + if (!(isprint(Data[i]) || isspace(Data[i]))) return false; + return true; +} + +bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) { + U->clear(); + if (Str.empty()) return false; + size_t L = 0, R = Str.size() - 1; // We are parsing the range [L,R]. + // Skip spaces from both sides. + while (L < R && isspace(Str[L])) L++; + while (R > L && isspace(Str[R])) R--; + if (R - L < 2) return false; + // Check the closing " + if (Str[R] != '"') return false; + R--; + // Find the opening " + while (L < R && Str[L] != '"') L++; + if (L >= R) return false; + assert(Str[L] == '\"'); + L++; + assert(L <= R); + for (size_t Pos = L; Pos <= R; Pos++) { + uint8_t V = (uint8_t)Str[Pos]; + if (!isprint(V) && !isspace(V)) return false; + if (V =='\\') { + // Handle '\\' + if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) { + U->push_back(Str[Pos + 1]); + Pos++; + continue; + } + // Handle '\xAB' + if (Pos + 3 <= R && Str[Pos + 1] == 'x' + && isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) { + char Hex[] = "0xAA"; + Hex[2] = Str[Pos + 2]; + Hex[3] = Str[Pos + 3]; + U->push_back(strtol(Hex, nullptr, 16)); + Pos += 3; + continue; + } + return false; // Invalid escape. + } else { + // Any other character. + U->push_back(V); + } + } + return true; +} + +bool ParseDictionaryFile(const std::string &Text, std::vector<Unit> *Units) { + if (Text.empty()) { + Printf("ParseDictionaryFile: file does not exist or is empty\n"); + return false; + } + std::istringstream ISS(Text); + Units->clear(); + Unit U; + int LineNo = 0; + std::string S; + while (std::getline(ISS, S, '\n')) { + LineNo++; + size_t Pos = 0; + while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces. + if (Pos == S.size()) continue; // Empty line. + if (S[Pos] == '#') continue; // Comment line. + if (ParseOneDictionaryEntry(S, &U)) { + Units->push_back(U); + } else { + Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo, + S.c_str()); + return false; + } + } + return true; +} + +std::string Base64(const Unit &U) { + static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + std::string Res; + size_t i; + for (i = 0; i + 2 < U.size(); i += 3) { + uint32_t x = (U[i] << 16) + (U[i + 1] << 8) + U[i + 2]; + Res += Table[(x >> 18) & 63]; + Res += Table[(x >> 12) & 63]; + Res += Table[(x >> 6) & 63]; + Res += Table[x & 63]; + } + if (i + 1 == U.size()) { + uint32_t x = (U[i] << 16); + Res += Table[(x >> 18) & 63]; + Res += Table[(x >> 12) & 63]; + Res += "=="; + } else if (i + 2 == U.size()) { + uint32_t x = (U[i] << 16) + (U[i + 1] << 8); + Res += Table[(x >> 18) & 63]; + Res += Table[(x >> 12) & 63]; + Res += Table[(x >> 6) & 63]; + Res += "="; + } + return Res; +} + +std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) { + if (!EF->__sanitizer_symbolize_pc) return "<can not symbolize>"; + char PcDescr[1024]; + EF->__sanitizer_symbolize_pc(reinterpret_cast<void*>(PC), + SymbolizedFMT, PcDescr, sizeof(PcDescr)); + PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case. + return PcDescr; +} + +void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC) { + if (EF->__sanitizer_symbolize_pc) + Printf("%s", DescribePC(SymbolizedFMT, PC).c_str()); + else + Printf(FallbackFMT, PC); +} + +unsigned NumberOfCpuCores() { + unsigned N = std::thread::hardware_concurrency(); + if (!N) { + Printf("WARNING: std::thread::hardware_concurrency not well defined for " + "your platform. Assuming CPU count of 1.\n"); + N = 1; + } + return N; +} + +bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out) { + FILE *Pipe = OpenProcessPipe(Command.c_str(), "r"); + if (!Pipe) return false; + char Buff[1024]; + size_t N; + while ((N = fread(Buff, 1, sizeof(Buff), Pipe)) > 0) + Out->append(Buff, N); + return true; +} + +} // namespace fuzzer diff --git a/test/fuzz_test/Fuzzer/FuzzerUtil.h b/test/fuzz_test/Fuzzer/FuzzerUtil.h new file mode 100644 index 00000000..08058c56 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerUtil.h @@ -0,0 +1,72 @@ +//===- FuzzerUtil.h - Internal header for the Fuzzer Utils ------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Util functions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_UTIL_H +#define LLVM_FUZZER_UTIL_H + +#include "FuzzerDefs.h" + +namespace fuzzer { + +void PrintHexArray(const Unit &U, const char *PrintAfter = ""); + +void PrintHexArray(const uint8_t *Data, size_t Size, + const char *PrintAfter = ""); + +void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = ""); + +void PrintASCII(const Unit &U, const char *PrintAfter = ""); + +// Changes U to contain only ASCII (isprint+isspace) characters. +// Returns true iff U has been changed. +bool ToASCII(uint8_t *Data, size_t Size); + +bool IsASCII(const Unit &U); + +bool IsASCII(const uint8_t *Data, size_t Size); + +std::string Base64(const Unit &U); + +void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC); + +std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC); + +unsigned NumberOfCpuCores(); + +bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out); + +// Platform specific functions. +void SetSignalHandler(const FuzzingOptions& Options); + +void SleepSeconds(int Seconds); + +unsigned long GetPid(); + +size_t GetPeakRSSMb(); + +int ExecuteCommand(const std::string &Command); + +FILE *OpenProcessPipe(const char *Command, const char *Mode); + +const void *SearchMemory(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); + +std::string CloneArgsWithoutX(const std::vector<std::string> &Args, + const char *X1, const char *X2); + +inline std::string CloneArgsWithoutX(const std::vector<std::string> &Args, + const char *X) { + return CloneArgsWithoutX(Args, X, X); +} + +} // namespace fuzzer + +#endif // LLVM_FUZZER_UTIL_H diff --git a/test/fuzz_test/Fuzzer/FuzzerUtilDarwin.cpp b/test/fuzz_test/Fuzzer/FuzzerUtilDarwin.cpp new file mode 100644 index 00000000..9674368c --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerUtilDarwin.cpp @@ -0,0 +1,152 @@ +//===- FuzzerUtilDarwin.cpp - Misc utils ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Misc utils for Darwin. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_APPLE + +#include "FuzzerIO.h" +#include <mutex> +#include <signal.h> +#include <spawn.h> +#include <sys/wait.h> + +// There is no header for this on macOS so declare here +extern "C" char **environ; + +namespace fuzzer { + +static std::mutex SignalMutex; +// Global variables used to keep track of how signal handling should be +// restored. They should **not** be accessed without holding `SignalMutex`. +static int ActiveThreadCount = 0; +static struct sigaction OldSigIntAction; +static struct sigaction OldSigQuitAction; +static sigset_t OldBlockedSignalsSet; + +// This is a reimplementation of Libc's `system()`. On Darwin the Libc +// implementation contains a mutex which prevents it from being used +// concurrently. This implementation **can** be used concurrently. It sets the +// signal handlers when the first thread enters and restores them when the last +// thread finishes execution of the function and ensures this is not racey by +// using a mutex. +int ExecuteCommand(const std::string &Command) { + posix_spawnattr_t SpawnAttributes; + if (posix_spawnattr_init(&SpawnAttributes)) + return -1; + // Block and ignore signals of the current process when the first thread + // enters. + { + std::lock_guard<std::mutex> Lock(SignalMutex); + if (ActiveThreadCount == 0) { + static struct sigaction IgnoreSignalAction; + sigset_t BlockedSignalsSet; + memset(&IgnoreSignalAction, 0, sizeof(IgnoreSignalAction)); + IgnoreSignalAction.sa_handler = SIG_IGN; + + if (sigaction(SIGINT, &IgnoreSignalAction, &OldSigIntAction) == -1) { + Printf("Failed to ignore SIGINT\n"); + (void)posix_spawnattr_destroy(&SpawnAttributes); + return -1; + } + if (sigaction(SIGQUIT, &IgnoreSignalAction, &OldSigQuitAction) == -1) { + Printf("Failed to ignore SIGQUIT\n"); + // Try our best to restore the signal handlers. + (void)sigaction(SIGINT, &OldSigIntAction, NULL); + (void)posix_spawnattr_destroy(&SpawnAttributes); + return -1; + } + + (void)sigemptyset(&BlockedSignalsSet); + (void)sigaddset(&BlockedSignalsSet, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &BlockedSignalsSet, &OldBlockedSignalsSet) == + -1) { + Printf("Failed to block SIGCHLD\n"); + // Try our best to restore the signal handlers. + (void)sigaction(SIGQUIT, &OldSigQuitAction, NULL); + (void)sigaction(SIGINT, &OldSigIntAction, NULL); + (void)posix_spawnattr_destroy(&SpawnAttributes); + return -1; + } + } + ++ActiveThreadCount; + } + + // NOTE: Do not introduce any new `return` statements past this + // point. It is important that `ActiveThreadCount` always be decremented + // when leaving this function. + + // Make sure the child process uses the default handlers for the + // following signals rather than inheriting what the parent has. + sigset_t DefaultSigSet; + (void)sigemptyset(&DefaultSigSet); + (void)sigaddset(&DefaultSigSet, SIGQUIT); + (void)sigaddset(&DefaultSigSet, SIGINT); + (void)posix_spawnattr_setsigdefault(&SpawnAttributes, &DefaultSigSet); + // Make sure the child process doesn't block SIGCHLD + (void)posix_spawnattr_setsigmask(&SpawnAttributes, &OldBlockedSignalsSet); + short SpawnFlags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; + (void)posix_spawnattr_setflags(&SpawnAttributes, SpawnFlags); + + pid_t Pid; + char **Environ = environ; // Read from global + const char *CommandCStr = Command.c_str(); + const char *Argv[] = {"sh", "-c", CommandCStr, NULL}; + int ErrorCode = 0, ProcessStatus = 0; + // FIXME: We probably shouldn't hardcode the shell path. + ErrorCode = posix_spawn(&Pid, "/bin/sh", NULL, &SpawnAttributes, + (char *const *)Argv, Environ); + (void)posix_spawnattr_destroy(&SpawnAttributes); + if (!ErrorCode) { + pid_t SavedPid = Pid; + do { + // Repeat until call completes uninterrupted. + Pid = waitpid(SavedPid, &ProcessStatus, /*options=*/0); + } while (Pid == -1 && errno == EINTR); + if (Pid == -1) { + // Fail for some other reason. + ProcessStatus = -1; + } + } else if (ErrorCode == ENOMEM || ErrorCode == EAGAIN) { + // Fork failure. + ProcessStatus = -1; + } else { + // Shell execution failure. + ProcessStatus = W_EXITCODE(127, 0); + } + + // Restore the signal handlers of the current process when the last thread + // using this function finishes. + { + std::lock_guard<std::mutex> Lock(SignalMutex); + --ActiveThreadCount; + if (ActiveThreadCount == 0) { + bool FailedRestore = false; + if (sigaction(SIGINT, &OldSigIntAction, NULL) == -1) { + Printf("Failed to restore SIGINT handling\n"); + FailedRestore = true; + } + if (sigaction(SIGQUIT, &OldSigQuitAction, NULL) == -1) { + Printf("Failed to restore SIGQUIT handling\n"); + FailedRestore = true; + } + if (sigprocmask(SIG_BLOCK, &OldBlockedSignalsSet, NULL) == -1) { + Printf("Failed to unblock SIGCHLD\n"); + FailedRestore = true; + } + if (FailedRestore) + ProcessStatus = -1; + } + } + return ProcessStatus; +} + +} // namespace fuzzer + +#endif // LIBFUZZER_APPLE diff --git a/test/fuzz_test/Fuzzer/FuzzerUtilLinux.cpp b/test/fuzz_test/Fuzzer/FuzzerUtilLinux.cpp new file mode 100644 index 00000000..dfe7e6f4 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerUtilLinux.cpp @@ -0,0 +1,24 @@ +//===- FuzzerUtilLinux.cpp - Misc utils for Linux. ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Misc utils for Linux. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_LINUX + +#include <stdlib.h> + +namespace fuzzer { + +int ExecuteCommand(const std::string &Command) { + return system(Command.c_str()); +} + +} // namespace fuzzer + +#endif // LIBFUZZER_LINUX diff --git a/test/fuzz_test/Fuzzer/FuzzerUtilPosix.cpp b/test/fuzz_test/Fuzzer/FuzzerUtilPosix.cpp new file mode 100644 index 00000000..8b484b8e --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerUtilPosix.cpp @@ -0,0 +1,117 @@ +//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Misc utils implementation using Posix API. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_POSIX +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include <cassert> +#include <chrono> +#include <cstring> +#include <errno.h> +#include <iomanip> +#include <signal.h> +#include <sstream> +#include <stdio.h> +#include <sys/resource.h> +#include <sys/syscall.h> +#include <sys/time.h> +#include <sys/types.h> +#include <thread> +#include <unistd.h> + +namespace fuzzer { + +static void AlarmHandler(int, siginfo_t *, void *) { + Fuzzer::StaticAlarmCallback(); +} + +static void CrashHandler(int, siginfo_t *, void *) { + Fuzzer::StaticCrashSignalCallback(); +} + +static void InterruptHandler(int, siginfo_t *, void *) { + Fuzzer::StaticInterruptCallback(); +} + +static void SetSigaction(int signum, + void (*callback)(int, siginfo_t *, void *)) { + struct sigaction sigact; + memset(&sigact, 0, sizeof(sigact)); + sigact.sa_sigaction = callback; + if (sigaction(signum, &sigact, 0)) { + Printf("libFuzzer: sigaction failed with %d\n", errno); + exit(1); + } +} + +void SetTimer(int Seconds) { + struct itimerval T { + {Seconds, 0}, { Seconds, 0 } + }; + if (setitimer(ITIMER_REAL, &T, nullptr)) { + Printf("libFuzzer: setitimer failed with %d\n", errno); + exit(1); + } + SetSigaction(SIGALRM, AlarmHandler); +} + +void SetSignalHandler(const FuzzingOptions& Options) { + if (Options.UnitTimeoutSec > 0) + SetTimer(Options.UnitTimeoutSec / 2 + 1); + if (Options.HandleInt) + SetSigaction(SIGINT, InterruptHandler); + if (Options.HandleTerm) + SetSigaction(SIGTERM, InterruptHandler); + if (Options.HandleSegv) + SetSigaction(SIGSEGV, CrashHandler); + if (Options.HandleBus) + SetSigaction(SIGBUS, CrashHandler); + if (Options.HandleAbrt) + SetSigaction(SIGABRT, CrashHandler); + if (Options.HandleIll) + SetSigaction(SIGILL, CrashHandler); + if (Options.HandleFpe) + SetSigaction(SIGFPE, CrashHandler); +} + +void SleepSeconds(int Seconds) { + sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. +} + +unsigned long GetPid() { return (unsigned long)getpid(); } + +size_t GetPeakRSSMb() { + struct rusage usage; + if (getrusage(RUSAGE_SELF, &usage)) + return 0; + if (LIBFUZZER_LINUX) { + // ru_maxrss is in KiB + return usage.ru_maxrss >> 10; + } else if (LIBFUZZER_APPLE) { + // ru_maxrss is in bytes + return usage.ru_maxrss >> 20; + } + assert(0 && "GetPeakRSSMb() is not implemented for your platform"); + return 0; +} + +FILE *OpenProcessPipe(const char *Command, const char *Mode) { + return popen(Command, Mode); +} + +const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, + size_t PattLen) { + return memmem(Data, DataLen, Patt, PattLen); +} + +} // namespace fuzzer + +#endif // LIBFUZZER_POSIX diff --git a/test/fuzz_test/Fuzzer/FuzzerUtilWindows.cpp b/test/fuzz_test/Fuzzer/FuzzerUtilWindows.cpp new file mode 100644 index 00000000..64adb7cd --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerUtilWindows.cpp @@ -0,0 +1,182 @@ +//===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Misc utils implementation for Windows. +//===----------------------------------------------------------------------===// +#include "FuzzerDefs.h" +#if LIBFUZZER_WINDOWS +#include "FuzzerIO.h" +#include "FuzzerInternal.h" +#include <cassert> +#include <chrono> +#include <cstring> +#include <errno.h> +#include <iomanip> +#include <signal.h> +#include <sstream> +#include <stdio.h> +#include <sys/types.h> +#include <windows.h> +#include <Psapi.h> + +namespace fuzzer { + +static const FuzzingOptions* HandlerOpt = nullptr; + +LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) { + switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { + case EXCEPTION_ACCESS_VIOLATION: + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + case EXCEPTION_STACK_OVERFLOW: + if (HandlerOpt->HandleSegv) + Fuzzer::StaticCrashSignalCallback(); + break; + case EXCEPTION_DATATYPE_MISALIGNMENT: + case EXCEPTION_IN_PAGE_ERROR: + if (HandlerOpt->HandleBus) + Fuzzer::StaticCrashSignalCallback(); + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + case EXCEPTION_PRIV_INSTRUCTION: + if (HandlerOpt->HandleIll) + Fuzzer::StaticCrashSignalCallback(); + break; + case EXCEPTION_FLT_DENORMAL_OPERAND: + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + case EXCEPTION_FLT_INEXACT_RESULT: + case EXCEPTION_FLT_INVALID_OPERATION: + case EXCEPTION_FLT_OVERFLOW: + case EXCEPTION_FLT_STACK_CHECK: + case EXCEPTION_FLT_UNDERFLOW: + case EXCEPTION_INT_DIVIDE_BY_ZERO: + case EXCEPTION_INT_OVERFLOW: + if (HandlerOpt->HandleFpe) + Fuzzer::StaticCrashSignalCallback(); + break; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +BOOL WINAPI CtrlHandler(DWORD dwCtrlType) { + switch (dwCtrlType) { + case CTRL_C_EVENT: + if (HandlerOpt->HandleInt) + Fuzzer::StaticInterruptCallback(); + return TRUE; + case CTRL_BREAK_EVENT: + if (HandlerOpt->HandleTerm) + Fuzzer::StaticInterruptCallback(); + return TRUE; + } + return FALSE; +} + +void CALLBACK AlarmHandler(PVOID, BOOLEAN) { + Fuzzer::StaticAlarmCallback(); +} + +class TimerQ { + HANDLE TimerQueue; + public: + TimerQ() : TimerQueue(NULL) {}; + ~TimerQ() { + if (TimerQueue) + DeleteTimerQueueEx(TimerQueue, NULL); + }; + void SetTimer(int Seconds) { + if (!TimerQueue) { + TimerQueue = CreateTimerQueue(); + if (!TimerQueue) { + Printf("libFuzzer: CreateTimerQueue failed.\n"); + exit(1); + } + } + HANDLE Timer; + if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL, + Seconds*1000, Seconds*1000, 0)) { + Printf("libFuzzer: CreateTimerQueueTimer failed.\n"); + exit(1); + } + }; +}; + +static TimerQ Timer; + +static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); } + +void SetSignalHandler(const FuzzingOptions& Options) { + HandlerOpt = &Options; + + if (Options.UnitTimeoutSec > 0) + Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1); + + if (Options.HandleInt || Options.HandleTerm) + if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) { + DWORD LastError = GetLastError(); + Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n", + LastError); + exit(1); + } + + if (Options.HandleSegv || Options.HandleBus || Options.HandleIll || + Options.HandleFpe) + if (!AddVectoredExceptionHandler(1, ExceptionHandler)) { + Printf("libFuzzer: AddVectoredExceptionHandler failed.\n"); + exit(1); + } + + if (Options.HandleAbrt) + if (SIG_ERR == signal(SIGABRT, CrashHandler)) { + Printf("libFuzzer: signal failed with %d\n", errno); + exit(1); + } +} + +void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); } + +unsigned long GetPid() { return GetCurrentProcessId(); } + +size_t GetPeakRSSMb() { + PROCESS_MEMORY_COUNTERS info; + if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info))) + return 0; + return info.PeakWorkingSetSize >> 20; +} + +FILE *OpenProcessPipe(const char *Command, const char *Mode) { + return _popen(Command, Mode); +} + +int ExecuteCommand(const std::string &Command) { + return system(Command.c_str()); +} + +const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, + size_t PattLen) { + // TODO: make this implementation more efficient. + const char *Cdata = (const char *)Data; + const char *Cpatt = (const char *)Patt; + + if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen) + return NULL; + + if (PattLen == 1) + return memchr(Data, *Cpatt, DataLen); + + const char *End = Cdata + DataLen - PattLen + 1; + + for (const char *It = Cdata; It < End; ++It) + if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0) + return It; + + return NULL; +} + +} // namespace fuzzer + +#endif // LIBFUZZER_WINDOWS diff --git a/test/fuzz_test/Fuzzer/FuzzerValueBitMap.h b/test/fuzz_test/Fuzzer/FuzzerValueBitMap.h new file mode 100644 index 00000000..0692acd1 --- /dev/null +++ b/test/fuzz_test/Fuzzer/FuzzerValueBitMap.h @@ -0,0 +1,87 @@ +//===- FuzzerValueBitMap.h - INTERNAL - Bit map -----------------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// ValueBitMap. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_VALUE_BIT_MAP_H +#define LLVM_FUZZER_VALUE_BIT_MAP_H + +#include "FuzzerDefs.h" + +namespace fuzzer { + +// A bit map containing kMapSizeInWords bits. +struct ValueBitMap { + static const size_t kMapSizeInBits = 65371; // Prime. + static const size_t kMapSizeInBitsAligned = 65536; // 2^16 + static const size_t kBitsInWord = (sizeof(uintptr_t) * 8); + static const size_t kMapSizeInWords = kMapSizeInBitsAligned / kBitsInWord; + public: + static const size_t kNumberOfItems = kMapSizeInBits; + // Clears all bits. + void Reset() { memset(Map, 0, sizeof(Map)); } + + // Computes a hash function of Value and sets the corresponding bit. + // Returns true if the bit was changed from 0 to 1. + inline bool AddValue(uintptr_t Value) { + uintptr_t Idx = Value < kMapSizeInBits ? Value : Value % kMapSizeInBits; + uintptr_t WordIdx = Idx / kBitsInWord; + uintptr_t BitIdx = Idx % kBitsInWord; + uintptr_t Old = Map[WordIdx]; + uintptr_t New = Old | (1UL << BitIdx); + Map[WordIdx] = New; + return New != Old; + } + + inline bool Get(uintptr_t Idx) { + assert(Idx < kMapSizeInBits); + uintptr_t WordIdx = Idx / kBitsInWord; + uintptr_t BitIdx = Idx % kBitsInWord; + return Map[WordIdx] & (1UL << BitIdx); + } + + size_t GetNumBitsSinceLastMerge() const { return NumBits; } + + // Merges 'Other' into 'this', clears 'Other', updates NumBits, + // returns true if new bits were added. + ATTRIBUTE_TARGET_POPCNT + bool MergeFrom(ValueBitMap &Other) { + uintptr_t Res = 0; + size_t OldNumBits = NumBits; + for (size_t i = 0; i < kMapSizeInWords; i++) { + auto O = Other.Map[i]; + auto M = Map[i]; + if (O) { + Map[i] = (M |= O); + Other.Map[i] = 0; + } + if (M) + Res += __builtin_popcountl(M); + } + NumBits = Res; + return OldNumBits < NumBits; + } + + template <class Callback> + void ForEach(Callback CB) { + for (size_t i = 0; i < kMapSizeInWords; i++) + if (uintptr_t M = Map[i]) + for (size_t j = 0; j < sizeof(M) * 8; j++) + if (M & ((uintptr_t)1 << j)) + CB(i * sizeof(M) * 8 + j); + } + + private: + size_t NumBits = 0; + uintptr_t Map[kMapSizeInWords] __attribute__((aligned(512))); +}; + +} // namespace fuzzer + +#endif // LLVM_FUZZER_VALUE_BIT_MAP_H diff --git a/test/fuzz_test/Fuzzer/README.txt b/test/fuzz_test/Fuzzer/README.txt new file mode 100644 index 00000000..79f49b55 --- /dev/null +++ b/test/fuzz_test/Fuzzer/README.txt @@ -0,0 +1,2 @@ +Move to http://llvm.org/docs/LibFuzzer.html + diff --git a/test/fuzz_test/Fuzzer/afl/afl_driver.cpp b/test/fuzz_test/Fuzzer/afl/afl_driver.cpp new file mode 100644 index 00000000..fc958955 --- /dev/null +++ b/test/fuzz_test/Fuzzer/afl/afl_driver.cpp @@ -0,0 +1,295 @@ +//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + +/* This file allows to fuzz libFuzzer-style target functions + (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode. + +Usage: +################################################################################ +cat << EOF > test_fuzzer.cc +#include <stdint.h> +#include <stddef.h> +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size > 0 && data[0] == 'H') + if (size > 1 && data[1] == 'I') + if (size > 2 && data[2] == '!') + __builtin_trap(); + return 0; +} +EOF +# Build your target with -fsanitize-coverage=trace-pc using fresh clang. +clang -g -fsanitize-coverage=trace-pc test_fuzzer.cc -c +# Build afl-llvm-rt.o.c from the AFL distribution. +clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c +# Build this file, link it with afl-llvm-rt.o.o and the target code. +clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o +# Run AFL: +rm -rf IN OUT; mkdir IN OUT; echo z > IN/z; +$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out +################################################################################ +Environment Variables: +There are a few environment variables that can be set to use features that +afl-fuzz doesn't have. + +AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file +specified. If the file does not exist, it is created. This is useful for getting +stack traces (when using ASAN for example) or original error messages on hard to +reproduce bugs. + +AFL_DRIVER_EXTRA_STATS_FILENAME: Setting this causes afl_driver to write extra +statistics to the file specified. Currently these are peak_rss_mb +(the peak amount of virtual memory used in MB) and slowest_unit_time_secs. If +the file does not exist it is created. If the file does exist then +afl_driver assumes it was restarted by afl-fuzz and will try to read old +statistics from the file. If that fails then the process will quit. + +*/ +#include <assert.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include <sys/resource.h> +#include <sys/time.h> +// Platform detection. Copied from FuzzerInternal.h +#ifdef __linux__ +#define LIBFUZZER_LINUX 1 +#define LIBFUZZER_APPLE 0 +#elif __APPLE__ +#define LIBFUZZER_LINUX 0 +#define LIBFUZZER_APPLE 1 +#else +#error "Support for your platform has not been implemented" +#endif + +// Used to avoid repeating error checking boilerplate. If cond is false, a +// fatal error has occured in the program. In this event print error_message +// to stderr and abort(). Otherwise do nothing. Note that setting +// AFL_DRIVER_STDERR_DUPLICATE_FILENAME may cause error_message to be appended +// to the file as well, if the error occurs after the duplication is performed. +#define CHECK_ERROR(cond, error_message) \ + if (!(cond)) { \ + fprintf(stderr, (error_message)); \ + abort(); \ + } + +// libFuzzer interface is thin, so we don't include any libFuzzer headers. +extern "C" { +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); +__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); +} + +// Notify AFL about persistent mode. +static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; +extern "C" int __afl_persistent_loop(unsigned int); +static volatile char suppress_warning2 = AFL_PERSISTENT[0]; + +// Notify AFL about deferred forkserver. +static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; +extern "C" void __afl_manual_init(); +static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0]; + +// Input buffer. +static const size_t kMaxAflInputSize = 1 << 20; +static uint8_t AflInputBuf[kMaxAflInputSize]; + +// Variables we need for writing to the extra stats file. +static FILE *extra_stats_file = NULL; +static uint32_t previous_peak_rss = 0; +static time_t slowest_unit_time_secs = 0; +static const int kNumExtraStats = 2; +static const char *kExtraStatsFormatString = "peak_rss_mb : %u\n" + "slowest_unit_time_sec : %u\n"; + +// Copied from FuzzerUtil.cpp. +size_t GetPeakRSSMb() { + struct rusage usage; + if (getrusage(RUSAGE_SELF, &usage)) + return 0; + if (LIBFUZZER_LINUX) { + // ru_maxrss is in KiB + return usage.ru_maxrss >> 10; + } else if (LIBFUZZER_APPLE) { + // ru_maxrss is in bytes + return usage.ru_maxrss >> 20; + } + assert(0 && "GetPeakRSSMb() is not implemented for your platform"); + return 0; +} + +// Based on SetSigaction in FuzzerUtil.cpp +static void SetSigaction(int signum, + void (*callback)(int, siginfo_t *, void *)) { + struct sigaction sigact; + memset(&sigact, 0, sizeof(sigact)); + sigact.sa_sigaction = callback; + if (sigaction(signum, &sigact, 0)) { + fprintf(stderr, "libFuzzer: sigaction failed with %d\n", errno); + exit(1); + } +} + +// Write extra stats to the file specified by the user. If none is specified +// this function will never be called. +static void write_extra_stats() { + uint32_t peak_rss = GetPeakRSSMb(); + + if (peak_rss < previous_peak_rss) + peak_rss = previous_peak_rss; + + int chars_printed = fprintf(extra_stats_file, kExtraStatsFormatString, + peak_rss, slowest_unit_time_secs); + + CHECK_ERROR(chars_printed != 0, "Failed to write extra_stats_file"); + + CHECK_ERROR(fclose(extra_stats_file) == 0, + "Failed to close extra_stats_file"); +} + +// Call write_extra_stats before we exit. +static void crash_handler(int, siginfo_t *, void *) { + // Make sure we don't try calling write_extra_stats again if we crashed while + // trying to call it. + static bool first_crash = true; + CHECK_ERROR(first_crash, + "Crashed in crash signal handler. This is a bug in the fuzzer."); + + first_crash = false; + write_extra_stats(); +} + +// If the user has specified an extra_stats_file through the environment +// variable AFL_DRIVER_EXTRA_STATS_FILENAME, then perform necessary set up +// to write stats to it on exit. If no file is specified, do nothing. Otherwise +// install signal and exit handlers to write to the file when the process exits. +// Then if the file doesn't exist create it and set extra stats to 0. But if it +// does exist then read the initial values of the extra stats from the file +// and check that the file is writable. +static void maybe_initialize_extra_stats() { + // If AFL_DRIVER_EXTRA_STATS_FILENAME isn't set then we have nothing to do. + char *extra_stats_filename = getenv("AFL_DRIVER_EXTRA_STATS_FILENAME"); + if (!extra_stats_filename) + return; + + // Open the file and find the previous peak_rss_mb value. + // This is necessary because the fuzzing process is restarted after N + // iterations are completed. So we may need to get this value from a previous + // process to be accurate. + extra_stats_file = fopen(extra_stats_filename, "r"); + + // If extra_stats_file already exists: read old stats from it. + if (extra_stats_file) { + int matches = fscanf(extra_stats_file, kExtraStatsFormatString, + &previous_peak_rss, &slowest_unit_time_secs); + + // Make sure we have read a real extra stats file and that we have used it + // to set slowest_unit_time_secs and previous_peak_rss. + CHECK_ERROR(matches == kNumExtraStats, "Extra stats file is corrupt"); + + CHECK_ERROR(fclose(extra_stats_file) == 0, "Failed to close file"); + + // Now open the file for writing. + extra_stats_file = fopen(extra_stats_filename, "w"); + CHECK_ERROR(extra_stats_file, + "Failed to open extra stats file for writing"); + } else { + // Looks like this is the first time in a fuzzing job this is being called. + extra_stats_file = fopen(extra_stats_filename, "w+"); + CHECK_ERROR(extra_stats_file, "failed to create extra stats file"); + } + + // Make sure that crash_handler gets called on any kind of fatal error. + int crash_signals[] = {SIGSEGV, SIGBUS, SIGABRT, SIGILL, SIGFPE, SIGINT, + SIGTERM}; + + const size_t num_signals = sizeof(crash_signals) / sizeof(crash_signals[0]); + + for (size_t idx = 0; idx < num_signals; idx++) + SetSigaction(crash_signals[idx], crash_handler); + + // Make sure it gets called on other kinds of exits. + atexit(write_extra_stats); +} + +// If the user asks us to duplicate stderr, then do it. +static void maybe_duplicate_stderr() { + char* stderr_duplicate_filename = + getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); + + if (!stderr_duplicate_filename) + return; + + FILE* stderr_duplicate_stream = + freopen(stderr_duplicate_filename, "a+", stderr); + + if (!stderr_duplicate_stream) { + fprintf( + stderr, + "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); + abort(); + } +} + +int main(int argc, char **argv) { + fprintf(stderr, "======================= INFO =========================\n" + "This binary is built for AFL-fuzz.\n" + "To run the target function on a single input execute this:\n" + " %s < INPUT_FILE\n" + "To run the fuzzing execute this:\n" + " afl-fuzz [afl-flags] %s [N] " + "-- run N fuzzing iterations before " + "re-spawning the process (default: 1000)\n" + "======================================================\n", + argv[0], argv[0]); + if (LLVMFuzzerInitialize) + LLVMFuzzerInitialize(&argc, &argv); + // Do any other expensive one-time initialization here. + + maybe_duplicate_stderr(); + maybe_initialize_extra_stats(); + + __afl_manual_init(); + + int N = 1000; + if (argc >= 2) + N = atoi(argv[1]); + assert(N > 0); + time_t unit_time_secs; + int num_runs = 0; + while (__afl_persistent_loop(N)) { + ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize); + if (n_read > 0) { + // Copy AflInputBuf into a separate buffer to let asan find buffer + // overflows. Don't use unique_ptr/etc to avoid extra dependencies. + uint8_t *copy = new uint8_t[n_read]; + memcpy(copy, AflInputBuf, n_read); + + struct timeval unit_start_time; + CHECK_ERROR(gettimeofday(&unit_start_time, NULL) == 0, + "Calling gettimeofday failed"); + + num_runs++; + LLVMFuzzerTestOneInput(copy, n_read); + + struct timeval unit_stop_time; + CHECK_ERROR(gettimeofday(&unit_stop_time, NULL) == 0, + "Calling gettimeofday failed"); + + // Update slowest_unit_time_secs if we see a new max. + unit_time_secs = unit_stop_time.tv_sec - unit_start_time.tv_sec; + if (slowest_unit_time_secs < unit_time_secs) + slowest_unit_time_secs = unit_time_secs; + + delete[] copy; + } + } + fprintf(stderr, "%s: successfully executed %d input(s)\n", argv[0], num_runs); +} diff --git a/test/fuzz_test/Fuzzer/build.sh b/test/fuzz_test/Fuzzer/build.sh new file mode 100755 index 00000000..27c148ad --- /dev/null +++ b/test/fuzz_test/Fuzzer/build.sh @@ -0,0 +1,10 @@ +#!/bin/bash +LIBFUZZER_SRC_DIR=$(dirname $0) +for f in $LIBFUZZER_SRC_DIR/*.cpp; do + clang -g -O2 -fno-omit-frame-pointer -std=c++11 $f -c & +done +wait +rm -f libFuzzer.a +ar ru libFuzzer.a Fuzzer*.o +rm -f Fuzzer*.o + diff --git a/test/fuzz_test/Fuzzer/cxx.dict b/test/fuzz_test/Fuzzer/cxx.dict new file mode 100644 index 00000000..41350f47 --- /dev/null +++ b/test/fuzz_test/Fuzzer/cxx.dict @@ -0,0 +1,122 @@ +"++" +"--" +"<<" +">>" +"+=" +"-=" +"*=" +"/=" +">>=" +"<<=" +"&=" +"|=" +"^=" +"%=" +"!=" +"&&" +"||" +"==" +">=" +"<=" +"->" +"alignas" +"alignof" +"and" +"and_eq" +"asm" +"auto" +"bitand" +"bitor" +"bool" +"break" +"case" +"catch" +"char" +"char16_t" +"char32_t" +"class" +"compl" +"concept" +"const" +"constexpr" +"const_cast" +"continue" +"decltype" +"default" +"delete" +"do" +"double" +"dynamic_cast" +"else" +"enum" +"explicit" +"export" +"extern" +"false" +"float" +"for" +"friend" +"goto" +"if" +"inline" +"int" +"long" +"mutable" +"namespace" +"new" +"noexcept" +"not" +"not_eq" +"nullptr" +"operator" +"or" +"or_eq" +"private" +"protected" +"public" +"register" +"reinterpret_cast" +"requires" +"return" +"short" +"signed" +"sizeof" +"static" +"static_assert" +"static_cast" +"struct" +"switch" +"template" +"this" +"thread_local" +"throw" +"true" +"try" +"typedef" +"typeid" +"typename" +"union" +"unsigned" +"using" +"virtual" +"void" +"volatile" +"wchar_t" +"while" +"xor" +"xor_eq" +"if" +"elif" +"else" +"endif" +"defined" +"ifdef" +"ifndef" +"define" +"undef" +"include" +"line" +"error" +"pragma" +"override" +"final" diff --git a/test/fuzz_test/Fuzzer/standalone/StandaloneFuzzTargetMain.c b/test/fuzz_test/Fuzzer/standalone/StandaloneFuzzTargetMain.c new file mode 100644 index 00000000..0d76ea49 --- /dev/null +++ b/test/fuzz_test/Fuzzer/standalone/StandaloneFuzzTargetMain.c @@ -0,0 +1,41 @@ +/*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This main() function can be linked to a fuzz target (i.e. a library +// that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize()) +// instead of libFuzzer. This main() function will not perform any fuzzing +// but will simply feed all input files one by one to the fuzz target. +// +// Use this file to provide reproducers for bugs when linking against libFuzzer +// or other fuzzing engine is undesirable. +//===----------------------------------------------------------------------===*/ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); +__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); +int main(int argc, char **argv) { + fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1); + if (LLVMFuzzerInitialize) + LLVMFuzzerInitialize(&argc, &argv); + for (int i = 1; i < argc; i++) { + fprintf(stderr, "Running: %s\n", argv[i]); + FILE *f = fopen(argv[i], "r"); + assert(f); + fseek(f, 0, SEEK_END); + size_t len = ftell(f); + fseek(f, 0, SEEK_SET); + unsigned char *buf = (unsigned char*)malloc(len); + size_t n_read = fread(buf, 1, len, f); + assert(n_read == len); + LLVMFuzzerTestOneInput(buf, len); + free(buf); + fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); + } +} diff --git a/test/fuzz_test/Fuzzer/test/AFLDriverTest.cpp b/test/fuzz_test/Fuzzer/test/AFLDriverTest.cpp new file mode 100644 index 00000000..3dd0b611 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/AFLDriverTest.cpp @@ -0,0 +1,22 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Contains dummy functions used to avoid dependency on AFL. +#include <stdint.h> +#include <stdlib.h> + +extern "C" void __afl_manual_init() {} + +extern "C" int __afl_persistent_loop(unsigned int) { + return 0; +} + +// This declaration exists to prevent the Darwin linker +// from complaining about this being a missing weak symbol. +extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/AbsNegAndConstant64Test.cpp b/test/fuzz_test/Fuzzer/test/AbsNegAndConstant64Test.cpp new file mode 100644 index 00000000..57748143 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/AbsNegAndConstant64Test.cpp @@ -0,0 +1,23 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// abs(x) < 0 and y == Const puzzle, 64-bit variant. +#include <cstring> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstdio> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 16) return 0; + int64_t x; + uint64_t y; + memcpy(&x, Data, sizeof(x)); + memcpy(&y, Data + sizeof(x), sizeof(y)); + if (labs(x) < 0 && y == 0xbaddcafedeadbeefUL) { + printf("BINGO; Found the target, exiting; x = 0x%lx y 0x%lx\n", x, y); + exit(1); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/AbsNegAndConstantTest.cpp b/test/fuzz_test/Fuzzer/test/AbsNegAndConstantTest.cpp new file mode 100644 index 00000000..69075a45 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/AbsNegAndConstantTest.cpp @@ -0,0 +1,23 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// abs(x) < 0 and y == Const puzzle. +#include <cstring> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstdio> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 8) return 0; + int x; + unsigned y; + memcpy(&x, Data, sizeof(x)); + memcpy(&y, Data + sizeof(x), sizeof(y)); + if (abs(x) < 0 && y == 0xbaddcafe) { + printf("BINGO; Found the target, exiting; x = 0x%x y 0x%x\n", x, y); + exit(1); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/AccumulateAllocationsTest.cpp b/test/fuzz_test/Fuzzer/test/AccumulateAllocationsTest.cpp new file mode 100644 index 00000000..604d8fa2 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/AccumulateAllocationsTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test with a more mallocs than frees, but no leak. +#include <cstdint> +#include <cstddef> + +const int kAllocatedPointersSize = 10000; +int NumAllocatedPointers = 0; +int *AllocatedPointers[kAllocatedPointersSize]; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (NumAllocatedPointers < kAllocatedPointersSize) + AllocatedPointers[NumAllocatedPointers++] = new int; + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/BufferOverflowOnInput.cpp b/test/fuzz_test/Fuzzer/test/BufferOverflowOnInput.cpp new file mode 100644 index 00000000..b9d14052 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/BufferOverflowOnInput.cpp @@ -0,0 +1,23 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <assert.h> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +static volatile bool SeedLargeBuffer; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size >= 4) + SeedLargeBuffer = true; + if (Size == 3 && SeedLargeBuffer && Data[3]) { + std::cout << "Woops, reading Data[3] w/o crashing\n"; + exit(1); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/CMakeLists.txt b/test/fuzz_test/Fuzzer/test/CMakeLists.txt new file mode 100644 index 00000000..c0457746 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/CMakeLists.txt @@ -0,0 +1,217 @@ +# Build all these tests with -O0, otherwise optimizations may merge some +# basic blocks and we'll fail to discover the targets. +# We change the flags for every build type because we might be doing +# a multi-configuration build (e.g. Xcode) where CMAKE_BUILD_TYPE doesn't +# mean anything. +set(variables_to_filter + CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_MINSIZEREL + LIBFUZZER_FLAGS_BASE + ) +foreach (VARNAME ${variables_to_filter}) + string(REPLACE " " ";" BUILD_FLAGS_AS_LIST "${${VARNAME}}") + set(new_flags "") + foreach (flag ${BUILD_FLAGS_AS_LIST}) + # NOTE: Use of XX here is to avoid a CMake warning due to CMP0054 + if (NOT ("XX${flag}" MATCHES "XX-O[0123s]")) + set(new_flags "${new_flags} ${flag}") + else() + set(new_flags "${new_flags} -O0") + endif() + endforeach() + set(${VARNAME} "${new_flags}") +endforeach() + +# Enable the coverage instrumentation (it is disabled for the Fuzzer lib). +set(CMAKE_CXX_FLAGS "${LIBFUZZER_FLAGS_BASE} -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp,trace-div,trace-gep -g") + +# add_libfuzzer_test(<name> +# SOURCES source0.cpp [source1.cpp ...] +# ) +# +# Declares a LibFuzzer test executable with target name LLVMFuzzer-<name>. +# +# One or more source files to be compiled into the binary must be declared +# after the SOURCES keyword. +function(add_libfuzzer_test name) + set(multi_arg_options "SOURCES") + cmake_parse_arguments( + "add_libfuzzer_test" "" "" "${multi_arg_options}" ${ARGN}) + if ("${add_libfuzzer_test_SOURCES}" STREQUAL "") + message(FATAL_ERROR "Source files must be specified") + endif() + add_executable(LLVMFuzzer-${name} + ${add_libfuzzer_test_SOURCES} + ) + target_link_libraries(LLVMFuzzer-${name} LLVMFuzzer) + # Place binary where llvm-lit expects to find it + set_target_properties(LLVMFuzzer-${name} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/lib/Fuzzer/test" + ) + set(TestBinaries ${TestBinaries} LLVMFuzzer-${name} PARENT_SCOPE) +endfunction() + +# Variable to keep track of all test targets +set(TestBinaries) + +############################################################################### +# Basic tests +############################################################################### + +set(Tests + AbsNegAndConstantTest + AbsNegAndConstant64Test + AccumulateAllocationsTest + BufferOverflowOnInput + CallerCalleeTest + CounterTest + CustomCrossOverTest + CustomMutatorTest + DivTest + EmptyTest + FourIndependentBranchesTest + FullCoverageSetTest + InitializeTest + MemcmpTest + LeakTest + LeakTimeoutTest + LoadTest + NullDerefTest + NullDerefOnEmptyTest + NthRunCrashTest + OneHugeAllocTest + OutOfMemoryTest + OutOfMemorySingleLargeMallocTest + RepeatedMemcmp + RepeatedBytesTest + SimpleCmpTest + SimpleDictionaryTest + SimpleHashTest + SimpleTest + SimpleThreadedTest + SingleMemcmpTest + SingleStrcmpTest + SingleStrncmpTest + SpamyTest + ShrinkControlFlowTest + ShrinkValueProfileTest + StrcmpTest + StrncmpOOBTest + StrncmpTest + StrstrTest + SwapCmpTest + SwitchTest + Switch2Test + ThreadedLeakTest + ThreadedTest + TimeoutTest + TimeoutEmptyTest + TraceMallocTest + ) + +if(APPLE) + # LeakSanitizer is not supported on OSX right now + set(HAS_LSAN 0) + message(WARNING "LeakSanitizer is not supported on Apple platforms." + " Building and running LibFuzzer LeakSanitizer tests is disabled." + ) +else() + set(HAS_LSAN 1) +endif() + +foreach(Test ${Tests}) + add_libfuzzer_test(${Test} SOURCES ${Test}.cpp) +endforeach() + + +############################################################################### +# Unit tests +############################################################################### + +add_executable(LLVMFuzzer-Unittest + FuzzerUnittest.cpp + ) + +add_executable(LLVMFuzzer-StandaloneInitializeTest + InitializeTest.cpp + ../standalone/StandaloneFuzzTargetMain.c + ) + +target_link_libraries(LLVMFuzzer-Unittest + gtest + gtest_main + LLVMFuzzerNoMain + ) + +target_include_directories(LLVMFuzzer-Unittest PRIVATE + "${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include" + ) + +set(TestBinaries ${TestBinaries} LLVMFuzzer-Unittest) +set_target_properties(LLVMFuzzer-Unittest + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}" +) + +set(TestBinaries ${TestBinaries} LLVMFuzzer-StandaloneInitializeTest) +set_target_properties(LLVMFuzzer-StandaloneInitializeTest + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}" +) + +############################################################################### +# Additional tests +############################################################################### + +include_directories(..) + +# add_subdirectory(uninstrumented) +add_subdirectory(no-coverage) +add_subdirectory(ubsan) + +add_library(LLVMFuzzer-DSO1 SHARED DSO1.cpp) +add_library(LLVMFuzzer-DSO2 SHARED DSO2.cpp) + +add_executable(LLVMFuzzer-DSOTest + DSOTestMain.cpp + DSOTestExtra.cpp) + +target_link_libraries(LLVMFuzzer-DSOTest + LLVMFuzzer-DSO1 + LLVMFuzzer-DSO2 + LLVMFuzzer + ) + +set_target_properties(LLVMFuzzer-DSOTest PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/lib/Fuzzer/test") +set_target_properties(LLVMFuzzer-DSO1 PROPERTIES LIBRARY_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/lib/Fuzzer/lib") +set_target_properties(LLVMFuzzer-DSO2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/lib/Fuzzer/lib") + +set(TestBinaries ${TestBinaries} LLVMFuzzer-DSOTest) + +############################################################################### +# Configure lit to run the tests +# +# Note this is done after declaring all tests so we can inform lit if any tests +# need to be disabled. +############################################################################### + +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg + ) + +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg + ) + +add_lit_testsuite(check-fuzzer "Running Fuzzer tests" + ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${TestBinaries} FileCheck not + ) diff --git a/test/fuzz_test/Fuzzer/test/CallerCalleeTest.cpp b/test/fuzz_test/Fuzzer/test/CallerCalleeTest.cpp new file mode 100644 index 00000000..3ec025d0 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/CallerCalleeTest.cpp @@ -0,0 +1,59 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. +// Try to find the target using the indirect caller-callee pairs. +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <iostream> + +typedef void (*F)(); +static F t[256]; + +void f34() { + std::cerr << "BINGO\n"; + exit(1); +} +void f23() { t[(unsigned)'d'] = f34;} +void f12() { t[(unsigned)'c'] = f23;} +void f01() { t[(unsigned)'b'] = f12;} +void f00() {} + +static F t0[256] = { + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, + f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 4) return 0; + // Spoof the counters. + for (int i = 0; i < 200; i++) { + f23(); + f12(); + f01(); + } + memcpy(t, t0, sizeof(t)); + t[(unsigned)'a'] = f01; + t[Data[0]](); + t[Data[1]](); + t[Data[2]](); + t[Data[3]](); + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/CounterTest.cpp b/test/fuzz_test/Fuzzer/test/CounterTest.cpp new file mode 100644 index 00000000..4917934c --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/CounterTest.cpp @@ -0,0 +1,18 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test for a fuzzer: must find the case where a particular basic block is +// executed many times. +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int Num = 0; + for (size_t i = 0; i < Size; i++) + if (Data[i] == 'A' + i) + Num++; + if (Num >= 4) { + std::cerr << "BINGO!\n"; + exit(1); + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/CustomCrossOverTest.cpp b/test/fuzz_test/Fuzzer/test/CustomCrossOverTest.cpp new file mode 100644 index 00000000..b624088b --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/CustomCrossOverTest.cpp @@ -0,0 +1,63 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a cutom mutator. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <iostream> +#include <random> +#include <string.h> + +#include "FuzzerInterface.h" + +static const char *Separator = "-_^_-"; +static const char *Target = "012-_^_-abc"; + +static volatile int sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + std::string Str(reinterpret_cast<const char *>(Data), Size); + + // Ensure that two different elements exist in the corpus. + if (Size && Data[0] == '0') sink++; + if (Size && Data[0] == 'a') sink--; + + if (Str.find(Target) != std::string::npos) { + std::cout << "BINGO; Found the target, exiting\n"; + exit(1); + } + return 0; +} + +extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1, + const uint8_t *Data2, size_t Size2, + uint8_t *Out, size_t MaxOutSize, + unsigned int Seed) { + static bool Printed; + static size_t SeparatorLen = strlen(Separator); + + if (!Printed) { + std::cerr << "In LLVMFuzzerCustomCrossover\n"; + Printed = true; + } + + std::mt19937 R(Seed); + + size_t Offset1 = 0; + size_t Len1 = R() % (Size1 - Offset1); + size_t Offset2 = 0; + size_t Len2 = R() % (Size2 - Offset2); + size_t Size = Len1 + Len2 + SeparatorLen; + + if (Size > MaxOutSize) + return 0; + + memcpy(Out, Data1 + Offset1, Len1); + memcpy(Out + Len1, Separator, SeparatorLen); + memcpy(Out + Len1 + SeparatorLen, Data2 + Offset2, Len2); + + return Len1 + Len2 + SeparatorLen; +} diff --git a/test/fuzz_test/Fuzzer/test/CustomMutatorTest.cpp b/test/fuzz_test/Fuzzer/test/CustomMutatorTest.cpp new file mode 100644 index 00000000..4f84519a --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/CustomMutatorTest.cpp @@ -0,0 +1,38 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a cutom mutator. +#include <assert.h> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +#include "FuzzerInterface.h" + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + std::cout << "BINGO; Found the target, exiting\n"; + exit(1); + } + } + } + return 0; +} + +extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, + size_t MaxSize, unsigned int Seed) { + static bool Printed; + if (!Printed) { + std::cerr << "In LLVMFuzzerCustomMutator\n"; + Printed = true; + } + return LLVMFuzzerMutate(Data, Size, MaxSize); +} diff --git a/test/fuzz_test/Fuzzer/test/DSO1.cpp b/test/fuzz_test/Fuzzer/test/DSO1.cpp new file mode 100644 index 00000000..4a293890 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/DSO1.cpp @@ -0,0 +1,12 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Source code for a simple DSO. + +int DSO1(int a) { + if (a < 123456) + return 0; + return 1; +} + +void Uncovered1() { } diff --git a/test/fuzz_test/Fuzzer/test/DSO2.cpp b/test/fuzz_test/Fuzzer/test/DSO2.cpp new file mode 100644 index 00000000..04b308d1 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/DSO2.cpp @@ -0,0 +1,12 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Source code for a simple DSO. + +int DSO2(int a) { + if (a < 3598235) + return 0; + return 1; +} + +void Uncovered2() {} diff --git a/test/fuzz_test/Fuzzer/test/DSOTestExtra.cpp b/test/fuzz_test/Fuzzer/test/DSOTestExtra.cpp new file mode 100644 index 00000000..a2274d07 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/DSOTestExtra.cpp @@ -0,0 +1,11 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Source code for a simple DSO. + +int DSOTestExtra(int a) { + if (a < 452345) + return 0; + return 1; +} + diff --git a/test/fuzz_test/Fuzzer/test/DSOTestMain.cpp b/test/fuzz_test/Fuzzer/test/DSOTestMain.cpp new file mode 100644 index 00000000..3e225d88 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/DSOTestMain.cpp @@ -0,0 +1,31 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Source code for a simple DSO. + +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <cstdio> +extern int DSO1(int a); +extern int DSO2(int a); +extern int DSOTestExtra(int a); + +static volatile int *nil = 0; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int x, y, z; + if (Size < sizeof(int) * 3) { + x = y = z = 0; + } else { + memcpy(&x, Data + 0 * sizeof(int), sizeof(int)); + memcpy(&y, Data + 1 * sizeof(int), sizeof(int)); + memcpy(&z, Data + 2 * sizeof(int), sizeof(int)); + } + int sum = DSO1(x) + DSO2(y) + (z ? DSOTestExtra(z) : 0); + if (sum == 3) { + fprintf(stderr, "BINGO %d %d %d\n", x, y, z); + *nil = 0; + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/DivTest.cpp b/test/fuzz_test/Fuzzer/test/DivTest.cpp new file mode 100644 index 00000000..63f6960f --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/DivTest.cpp @@ -0,0 +1,20 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer: find the interesting argument for div. +#include <assert.h> +#include <cstdint> +#include <cstring> +#include <cstddef> +#include <iostream> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 4) return 0; + int a; + memcpy(&a, Data, 4); + Sink = 12345678 / (987654 - a); + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/EmptyTest.cpp b/test/fuzz_test/Fuzzer/test/EmptyTest.cpp new file mode 100644 index 00000000..5e843308 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/EmptyTest.cpp @@ -0,0 +1,11 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// A fuzzer with empty target function. + +#include <cstdint> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/FourIndependentBranchesTest.cpp b/test/fuzz_test/Fuzzer/test/FourIndependentBranchesTest.cpp new file mode 100644 index 00000000..62b3be76 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/FourIndependentBranchesTest.cpp @@ -0,0 +1,22 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "FUZZ". +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int bits = 0; + if (Size > 0 && Data[0] == 'F') bits |= 1; + if (Size > 1 && Data[1] == 'U') bits |= 2; + if (Size > 2 && Data[2] == 'Z') bits |= 4; + if (Size > 3 && Data[3] == 'Z') bits |= 8; + if (bits == 15) { + std::cerr << "BINGO!\n"; + exit(1); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/FullCoverageSetTest.cpp b/test/fuzz_test/Fuzzer/test/FullCoverageSetTest.cpp new file mode 100644 index 00000000..415e0b47 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/FullCoverageSetTest.cpp @@ -0,0 +1,24 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "FUZZER". +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int bits = 0; + if (Size > 0 && Data[0] == 'F') bits |= 1; + if (Size > 1 && Data[1] == 'U') bits |= 2; + if (Size > 2 && Data[2] == 'Z') bits |= 4; + if (Size > 3 && Data[3] == 'Z') bits |= 8; + if (Size > 4 && Data[4] == 'E') bits |= 16; + if (Size > 5 && Data[5] == 'R') bits |= 32; + if (bits == 63) { + std::cerr << "BINGO!\n"; + exit(1); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/FuzzerUnittest.cpp b/test/fuzz_test/Fuzzer/test/FuzzerUnittest.cpp new file mode 100644 index 00000000..4992ef57 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/FuzzerUnittest.cpp @@ -0,0 +1,738 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Avoid ODR violations (LibFuzzer is built without ASan and this test is built +// with ASan) involving C++ standard library types when using libcxx. +#define _LIBCPP_HAS_NO_ASAN + +#include "FuzzerCorpus.h" +#include "FuzzerInternal.h" +#include "FuzzerDictionary.h" +#include "FuzzerMerge.h" +#include "FuzzerMutate.h" +#include "FuzzerRandom.h" +#include "gtest/gtest.h" +#include <memory> +#include <set> + +using namespace fuzzer; + +// For now, have LLVMFuzzerTestOneInput just to make it link. +// Later we may want to make unittests that actually call LLVMFuzzerTestOneInput. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + abort(); +} + +TEST(Fuzzer, CrossOver) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + Unit A({0, 1, 2}), B({5, 6, 7}); + Unit C; + Unit Expected[] = { + { 0 }, + { 0, 1 }, + { 0, 5 }, + { 0, 1, 2 }, + { 0, 1, 5 }, + { 0, 5, 1 }, + { 0, 5, 6 }, + { 0, 1, 2, 5 }, + { 0, 1, 5, 2 }, + { 0, 1, 5, 6 }, + { 0, 5, 1, 2 }, + { 0, 5, 1, 6 }, + { 0, 5, 6, 1 }, + { 0, 5, 6, 7 }, + { 0, 1, 2, 5, 6 }, + { 0, 1, 5, 2, 6 }, + { 0, 1, 5, 6, 2 }, + { 0, 1, 5, 6, 7 }, + { 0, 5, 1, 2, 6 }, + { 0, 5, 1, 6, 2 }, + { 0, 5, 1, 6, 7 }, + { 0, 5, 6, 1, 2 }, + { 0, 5, 6, 1, 7 }, + { 0, 5, 6, 7, 1 }, + { 0, 1, 2, 5, 6, 7 }, + { 0, 1, 5, 2, 6, 7 }, + { 0, 1, 5, 6, 2, 7 }, + { 0, 1, 5, 6, 7, 2 }, + { 0, 5, 1, 2, 6, 7 }, + { 0, 5, 1, 6, 2, 7 }, + { 0, 5, 1, 6, 7, 2 }, + { 0, 5, 6, 1, 2, 7 }, + { 0, 5, 6, 1, 7, 2 }, + { 0, 5, 6, 7, 1, 2 } + }; + for (size_t Len = 1; Len < 8; Len++) { + std::set<Unit> FoundUnits, ExpectedUnitsWitThisLength; + for (int Iter = 0; Iter < 3000; Iter++) { + C.resize(Len); + size_t NewSize = MD.CrossOver(A.data(), A.size(), B.data(), B.size(), + C.data(), C.size()); + C.resize(NewSize); + FoundUnits.insert(C); + } + for (const Unit &U : Expected) + if (U.size() <= Len) + ExpectedUnitsWitThisLength.insert(U); + EXPECT_EQ(ExpectedUnitsWitThisLength, FoundUnits); + } +} + +TEST(Fuzzer, Hash) { + uint8_t A[] = {'a', 'b', 'c'}; + fuzzer::Unit U(A, A + sizeof(A)); + EXPECT_EQ("a9993e364706816aba3e25717850c26c9cd0d89d", fuzzer::Hash(U)); + U.push_back('d'); + EXPECT_EQ("81fe8bfe87576c3ecb22426f8e57847382917acf", fuzzer::Hash(U)); +} + +typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size, + size_t MaxSize); + +void TestEraseBytes(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77}; + uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77}; + uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77}; + uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; + uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77}; + + uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44}; + uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77}; + + + Random Rand(0); + MutationDispatcher MD(Rand, {}); + int FoundMask = 0; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (MD.*M)(T, sizeof(T), sizeof(T)); + if (NewSize == 7 && !memcmp(REM0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(REM1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(REM2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(REM3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(REM4, T, 7)) FoundMask |= 1 << 4; + if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5; + if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6; + if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7; + + if (NewSize == 6 && !memcmp(REM8, T, 6)) FoundMask |= 1 << 8; + if (NewSize == 6 && !memcmp(REM9, T, 6)) FoundMask |= 1 << 9; + if (NewSize == 6 && !memcmp(REM10, T, 6)) FoundMask |= 1 << 10; + + if (NewSize == 5 && !memcmp(REM11, T, 5)) FoundMask |= 1 << 11; + if (NewSize == 5 && !memcmp(REM12, T, 5)) FoundMask |= 1 << 12; + if (NewSize == 5 && !memcmp(REM13, T, 5)) FoundMask |= 1 << 13; + } + EXPECT_EQ(FoundMask, (1 << 14) - 1); +} + +TEST(FuzzerMutate, EraseBytes1) { + TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200); +} +TEST(FuzzerMutate, EraseBytes2) { + TestEraseBytes(&MutationDispatcher::Mutate, 2000); +} + +void TestInsertByte(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + int FoundMask = 0; + uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66}; + uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66}; + uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66}; + uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66}; + uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + size_t NewSize = (MD.*M)(T, 7, 8); + if (NewSize == 8 && !memcmp(INS0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(INS1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(INS2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(INS3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(INS4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, InsertByte1) { + TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15); +} +TEST(FuzzerMutate, InsertByte2) { + TestInsertByte(&MutationDispatcher::Mutate, 1 << 17); +} + +void TestInsertRepeatedBytes(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + int FoundMask = 0; + uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'}; + uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33}; + uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33}; + uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33}; + uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33}; + + uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'}; + uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33}; + uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33}; + uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33}; + uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33}; + + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33}; + size_t NewSize = (MD.*M)(T, 4, 8); + if (NewSize == 7 && !memcmp(INS0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(INS1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(INS2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(INS3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(INS4, T, 7)) FoundMask |= 1 << 4; + + if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7; + if (NewSize == 8 && !memcmp(INS8, T, 8)) FoundMask |= 1 << 8; + if (NewSize == 8 && !memcmp(INS9, T, 8)) FoundMask |= 1 << 9; + + } + EXPECT_EQ(FoundMask, (1 << 10) - 1); +} + +TEST(FuzzerMutate, InsertRepeatedBytes1) { + TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000); +} +TEST(FuzzerMutate, InsertRepeatedBytes2) { + TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000); +} + +void TestChangeByte(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + int FoundMask = 0; + uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77}; + uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77}; + uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77}; + uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (MD.*M)(T, 8, 9); + if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, ChangeByte1) { + TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15); +} +TEST(FuzzerMutate, ChangeByte2) { + TestChangeByte(&MutationDispatcher::Mutate, 1 << 17); +} + +void TestChangeBit(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + int FoundMask = 0; + uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77}; + uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77}; + uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77}; + uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (MD.*M)(T, 8, 9); + if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; + if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, ChangeBit1) { + TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16); +} +TEST(FuzzerMutate, ChangeBit2) { + TestChangeBit(&MutationDispatcher::Mutate, 1 << 18); +} + +void TestShuffleBytes(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + int FoundMask = 0; + uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66}; + uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66}; + uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66}; + uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33}; + uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + size_t NewSize = (MD.*M)(T, 7, 7); + if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4; + } + EXPECT_EQ(FoundMask, 31); +} + +TEST(FuzzerMutate, ShuffleBytes1) { + TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 16); +} +TEST(FuzzerMutate, ShuffleBytes2) { + TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20); +} + +void TestCopyPart(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + int FoundMask = 0; + uint8_t CH0[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11}; + uint8_t CH1[7] = {0x55, 0x66, 0x22, 0x33, 0x44, 0x55, 0x66}; + uint8_t CH2[7] = {0x00, 0x55, 0x66, 0x33, 0x44, 0x55, 0x66}; + uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x66}; + uint8_t CH4[7] = {0x00, 0x11, 0x11, 0x22, 0x33, 0x55, 0x66}; + + for (int i = 0; i < NumIter; i++) { + uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + size_t NewSize = (MD.*M)(T, 7, 7); + if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4; + } + + uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22}; + uint8_t CH6[8] = {0x22, 0x33, 0x44, 0x00, 0x11, 0x22, 0x33, 0x44}; + uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x33, 0x44}; + uint8_t CH8[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x22, 0x33, 0x44}; + uint8_t CH9[8] = {0x00, 0x11, 0x22, 0x22, 0x33, 0x44, 0x33, 0x44}; + + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (MD.*M)(T, 5, 8); + if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + if (NewSize == 8 && !memcmp(CH8, T, 8)) FoundMask |= 1 << 8; + if (NewSize == 8 && !memcmp(CH9, T, 8)) FoundMask |= 1 << 9; + } + + EXPECT_EQ(FoundMask, 1023); +} + +TEST(FuzzerMutate, CopyPart1) { + TestCopyPart(&MutationDispatcher::Mutate_CopyPart, 1 << 10); +} +TEST(FuzzerMutate, CopyPart2) { + TestCopyPart(&MutationDispatcher::Mutate, 1 << 13); +} + +void TestAddWordFromDictionary(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD}; + uint8_t Word2[3] = {0xFF, 0xEE, 0xEF}; + MD.AddWordToManualDictionary(Word(Word1, sizeof(Word1))); + MD.AddWordToManualDictionary(Word(Word2, sizeof(Word2))); + int FoundMask = 0; + uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD}; + uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22}; + uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22}; + uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22}; + uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF}; + uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22}; + uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22}; + uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22}; + for (int i = 0; i < NumIter; i++) { + uint8_t T[7] = {0x00, 0x11, 0x22}; + size_t NewSize = (MD.*M)(T, 3, 7); + if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; + if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; + if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; + if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; + if (NewSize == 6 && !memcmp(CH4, T, 6)) FoundMask |= 1 << 4; + if (NewSize == 6 && !memcmp(CH5, T, 6)) FoundMask |= 1 << 5; + if (NewSize == 6 && !memcmp(CH6, T, 6)) FoundMask |= 1 << 6; + if (NewSize == 6 && !memcmp(CH7, T, 6)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, AddWordFromDictionary1) { + TestAddWordFromDictionary( + &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15); +} + +TEST(FuzzerMutate, AddWordFromDictionary2) { + TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15); +} + +void TestAddWordFromDictionaryWithHint(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + uint8_t W[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xFF, 0xEE, 0xEF}; + size_t PosHint = 7777; + MD.AddWordToAutoDictionary({Word(W, sizeof(W)), PosHint}); + int FoundMask = 0; + for (int i = 0; i < NumIter; i++) { + uint8_t T[10000]; + memset(T, 0, sizeof(T)); + size_t NewSize = (MD.*M)(T, 9000, 10000); + if (NewSize >= PosHint + sizeof(W) && + !memcmp(W, T + PosHint, sizeof(W))) + FoundMask = 1; + } + EXPECT_EQ(FoundMask, 1); +} + +TEST(FuzzerMutate, AddWordFromDictionaryWithHint1) { + TestAddWordFromDictionaryWithHint( + &MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary, 1 << 5); +} + +TEST(FuzzerMutate, AddWordFromDictionaryWithHint2) { + TestAddWordFromDictionaryWithHint(&MutationDispatcher::Mutate, 1 << 10); +} + +void TestChangeASCIIInteger(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + + uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'}; + uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'}; + uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'}; + uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'}; + int FoundMask = 0; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'}; + size_t NewSize = (MD.*M)(T, 8, 8); + /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + else if (NewSize == 8) FoundMask |= 1 << 4; + } + EXPECT_EQ(FoundMask, 31); +} + +TEST(FuzzerMutate, ChangeASCIIInteger1) { + TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger, + 1 << 15); +} + +TEST(FuzzerMutate, ChangeASCIIInteger2) { + TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15); +} + +void TestChangeBinaryInteger(Mutator M, int NumIter) { + std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); + fuzzer::EF = t.get(); + Random Rand(0); + MutationDispatcher MD(Rand, {}); + + uint8_t CH0[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x79}; + uint8_t CH1[8] = {0x00, 0x11, 0x22, 0x31, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH2[8] = {0xff, 0x10, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH3[8] = {0x00, 0x11, 0x2a, 0x33, 0x44, 0x55, 0x66, 0x77}; + uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x4f, 0x66, 0x77}; + uint8_t CH5[8] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88}; + uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x08, 0x77}; // Size + uint8_t CH7[8] = {0x00, 0x08, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77}; // Sw(Size) + + int FoundMask = 0; + for (int i = 0; i < NumIter; i++) { + uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + size_t NewSize = (MD.*M)(T, 8, 8); + /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; + else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; + else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; + else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; + else if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; + else if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; + else if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; + else if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; + } + EXPECT_EQ(FoundMask, 255); +} + +TEST(FuzzerMutate, ChangeBinaryInteger1) { + TestChangeBinaryInteger(&MutationDispatcher::Mutate_ChangeBinaryInteger, + 1 << 12); +} + +TEST(FuzzerMutate, ChangeBinaryInteger2) { + TestChangeBinaryInteger(&MutationDispatcher::Mutate, 1 << 15); +} + + +TEST(FuzzerDictionary, ParseOneDictionaryEntry) { + Unit U; + EXPECT_FALSE(ParseOneDictionaryEntry("", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry("\t ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" \" ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" zz\" ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" \"zz ", &U)); + EXPECT_FALSE(ParseOneDictionaryEntry(" \"\" ", &U)); + EXPECT_TRUE(ParseOneDictionaryEntry("\"a\"", &U)); + EXPECT_EQ(U, Unit({'a'})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"abc\"", &U)); + EXPECT_EQ(U, Unit({'a', 'b', 'c'})); + EXPECT_TRUE(ParseOneDictionaryEntry("abc=\"abc\"", &U)); + EXPECT_EQ(U, Unit({'a', 'b', 'c'})); + EXPECT_FALSE(ParseOneDictionaryEntry("\"\\\"", &U)); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\\\"", &U)); + EXPECT_EQ(U, Unit({'\\'})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xAB\"", &U)); + EXPECT_EQ(U, Unit({0xAB})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xABz\\xDE\"", &U)); + EXPECT_EQ(U, Unit({0xAB, 'z', 0xDE})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"#\"", &U)); + EXPECT_EQ(U, Unit({'#'})); + EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\"\"", &U)); + EXPECT_EQ(U, Unit({'"'})); +} + +TEST(FuzzerDictionary, ParseDictionaryFile) { + std::vector<Unit> Units; + EXPECT_FALSE(ParseDictionaryFile("zzz\n", &Units)); + EXPECT_FALSE(ParseDictionaryFile("", &Units)); + EXPECT_TRUE(ParseDictionaryFile("\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile("#zzzz a b c d\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units)); + EXPECT_EQ(Units.size(), 0U); + EXPECT_TRUE(ParseDictionaryFile(" #zzzz\naaa=\"aa\"", &Units)); + EXPECT_EQ(Units, std::vector<Unit>({Unit({'a', 'a'})})); + EXPECT_TRUE( + ParseDictionaryFile(" #zzzz\naaa=\"aa\"\n\nabc=\"abc\"", &Units)); + EXPECT_EQ(Units, + std::vector<Unit>({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})})); +} + +TEST(FuzzerUtil, Base64) { + EXPECT_EQ("", Base64({})); + EXPECT_EQ("YQ==", Base64({'a'})); + EXPECT_EQ("eA==", Base64({'x'})); + EXPECT_EQ("YWI=", Base64({'a', 'b'})); + EXPECT_EQ("eHk=", Base64({'x', 'y'})); + EXPECT_EQ("YWJj", Base64({'a', 'b', 'c'})); + EXPECT_EQ("eHl6", Base64({'x', 'y', 'z'})); + EXPECT_EQ("YWJjeA==", Base64({'a', 'b', 'c', 'x'})); + EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'})); + EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'})); +} + +TEST(Corpus, Distribution) { + Random Rand(0); + InputCorpus C(""); + size_t N = 10; + size_t TriesPerUnit = 1<<16; + for (size_t i = 0; i < N; i++) + C.AddToCorpus(Unit{ static_cast<uint8_t>(i) }, 0); + + std::vector<size_t> Hist(N); + for (size_t i = 0; i < N * TriesPerUnit; i++) { + Hist[C.ChooseUnitIdxToMutate(Rand)]++; + } + for (size_t i = 0; i < N; i++) { + // A weak sanity check that every unit gets invoked. + EXPECT_GT(Hist[i], TriesPerUnit / N / 3); + } +} + +TEST(Merge, Bad) { + const char *kInvalidInputs[] = { + "", + "x", + "3\nx", + "2\n3", + "2\n2", + "2\n2\nA\n", + "2\n2\nA\nB\nC\n", + "0\n0\n", + "1\n1\nA\nDONE 0", + "1\n1\nA\nSTARTED 1", + }; + Merger M; + for (auto S : kInvalidInputs) { + // fprintf(stderr, "TESTING:\n%s\n", S); + EXPECT_FALSE(M.Parse(S, false)); + } +} + +void EQ(const std::vector<uint32_t> &A, const std::vector<uint32_t> &B) { + EXPECT_EQ(A, B); +} + +void EQ(const std::vector<std::string> &A, const std::vector<std::string> &B) { + std::set<std::string> a(A.begin(), A.end()); + std::set<std::string> b(B.begin(), B.end()); + EXPECT_EQ(a, b); +} + +static void Merge(const std::string &Input, + const std::vector<std::string> Result, + size_t NumNewFeatures) { + Merger M; + std::vector<std::string> NewFiles; + EXPECT_TRUE(M.Parse(Input, true)); + EXPECT_EQ(NumNewFeatures, M.Merge(&NewFiles)); + EQ(NewFiles, Result); +} + +TEST(Merge, Good) { + Merger M; + + EXPECT_TRUE(M.Parse("1\n0\nAA\n", false)); + EXPECT_EQ(M.Files.size(), 1U); + EXPECT_EQ(M.NumFilesInFirstCorpus, 0U); + EXPECT_EQ(M.Files[0].Name, "AA"); + EXPECT_TRUE(M.LastFailure.empty()); + EXPECT_EQ(M.FirstNotProcessedFile, 0U); + + EXPECT_TRUE(M.Parse("2\n1\nAA\nBB\nSTARTED 0 42\n", false)); + EXPECT_EQ(M.Files.size(), 2U); + EXPECT_EQ(M.NumFilesInFirstCorpus, 1U); + EXPECT_EQ(M.Files[0].Name, "AA"); + EXPECT_EQ(M.Files[1].Name, "BB"); + EXPECT_EQ(M.LastFailure, "AA"); + EXPECT_EQ(M.FirstNotProcessedFile, 1U); + + EXPECT_TRUE(M.Parse("3\n1\nAA\nBB\nC\n" + "STARTED 0 1000\n" + "DONE 0 1 2 3\n" + "STARTED 1 1001\n" + "DONE 1 4 5 6 \n" + "STARTED 2 1002\n" + "", true)); + EXPECT_EQ(M.Files.size(), 3U); + EXPECT_EQ(M.NumFilesInFirstCorpus, 1U); + EXPECT_EQ(M.Files[0].Name, "AA"); + EXPECT_EQ(M.Files[0].Size, 1000U); + EXPECT_EQ(M.Files[1].Name, "BB"); + EXPECT_EQ(M.Files[1].Size, 1001U); + EXPECT_EQ(M.Files[2].Name, "C"); + EXPECT_EQ(M.Files[2].Size, 1002U); + EXPECT_EQ(M.LastFailure, "C"); + EXPECT_EQ(M.FirstNotProcessedFile, 3U); + EQ(M.Files[0].Features, {1, 2, 3}); + EQ(M.Files[1].Features, {4, 5, 6}); + + + std::vector<std::string> NewFiles; + + EXPECT_TRUE(M.Parse("3\n2\nAA\nBB\nC\n" + "STARTED 0 1000\nDONE 0 1 2 3\n" + "STARTED 1 1001\nDONE 1 4 5 6 \n" + "STARTED 2 1002\nDONE 2 6 1 3 \n" + "", true)); + EXPECT_EQ(M.Files.size(), 3U); + EXPECT_EQ(M.NumFilesInFirstCorpus, 2U); + EXPECT_TRUE(M.LastFailure.empty()); + EXPECT_EQ(M.FirstNotProcessedFile, 3U); + EQ(M.Files[0].Features, {1, 2, 3}); + EQ(M.Files[1].Features, {4, 5, 6}); + EQ(M.Files[2].Features, {1, 3, 6}); + EXPECT_EQ(0U, M.Merge(&NewFiles)); + EQ(NewFiles, {}); + + EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n" + "STARTED 0 1000\nDONE 0 1 2 3\n" + "STARTED 1 1001\nDONE 1 4 5 6 \n" + "STARTED 2 1002\nDONE 2 6 1 3\n" + "", true)); + EQ(M.Files[0].Features, {1, 2, 3}); + EQ(M.Files[1].Features, {4, 5, 6}); + EQ(M.Files[2].Features, {1, 3, 6}); + EXPECT_EQ(3U, M.Merge(&NewFiles)); + EQ(NewFiles, {"B"}); +} + +TEST(Merge, Merge) { + + Merge("3\n1\nA\nB\nC\n" + "STARTED 0 1000\nDONE 0 1 2 3\n" + "STARTED 1 1001\nDONE 1 4 5 6 \n" + "STARTED 2 1002\nDONE 2 6 1 3 \n", + {"B"}, 3); + + Merge("3\n0\nA\nB\nC\n" + "STARTED 0 2000\nDONE 0 1 2 3\n" + "STARTED 1 1001\nDONE 1 4 5 6 \n" + "STARTED 2 1002\nDONE 2 6 1 3 \n", + {"A", "B", "C"}, 6); + + Merge("4\n0\nA\nB\nC\nD\n" + "STARTED 0 2000\nDONE 0 1 2 3\n" + "STARTED 1 1101\nDONE 1 4 5 6 \n" + "STARTED 2 1102\nDONE 2 6 1 3 100 \n" + "STARTED 3 1000\nDONE 3 1 \n", + {"A", "B", "C", "D"}, 7); + + Merge("4\n1\nA\nB\nC\nD\n" + "STARTED 0 2000\nDONE 0 4 5 6 7 8\n" + "STARTED 1 1100\nDONE 1 1 2 3 \n" + "STARTED 2 1100\nDONE 2 2 3 \n" + "STARTED 3 1000\nDONE 3 1 \n", + {"B", "D"}, 3); +} diff --git a/test/fuzz_test/Fuzzer/test/InitializeTest.cpp b/test/fuzz_test/Fuzzer/test/InitializeTest.cpp new file mode 100644 index 00000000..0d6a0fda --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/InitializeTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Make sure LLVMFuzzerInitialize is called. +#include <assert.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static char *argv0; + +extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { + assert(*argc > 0); + argv0 = **argv; + fprintf(stderr, "LLVMFuzzerInitialize: %s\n", argv0); + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size == strlen(argv0) && + !strncmp(reinterpret_cast<const char *>(Data), argv0, Size)) { + fprintf(stderr, "BINGO %s\n", argv0); + exit(1); + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/LeakTest.cpp b/test/fuzz_test/Fuzzer/test/LeakTest.cpp new file mode 100644 index 00000000..22e51640 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/LeakTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test with a leak. +#include <cstdint> +#include <cstddef> + +static volatile void *Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && *Data == 'H') { + Sink = new int; + Sink = nullptr; + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/LeakTimeoutTest.cpp b/test/fuzz_test/Fuzzer/test/LeakTimeoutTest.cpp new file mode 100644 index 00000000..4f31b3e5 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/LeakTimeoutTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test with a leak. +#include <cstdint> +#include <cstddef> + +static volatile int *Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (!Size) return 0; + Sink = new int; + Sink = new int; + while (Sink) *Sink = 0; // Infinite loop. + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/LoadTest.cpp b/test/fuzz_test/Fuzzer/test/LoadTest.cpp new file mode 100644 index 00000000..c1780d5c --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/LoadTest.cpp @@ -0,0 +1,22 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer: find interesting value of array index. +#include <assert.h> +#include <cstdint> +#include <cstring> +#include <cstddef> +#include <iostream> + +static volatile int Sink; +const int kArraySize = 1234567; +int array[kArraySize]; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 8) return 0; + size_t a = 0; + memcpy(&a, Data, 8); + Sink = array[a % (kArraySize + 1)]; + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/MemcmpTest.cpp b/test/fuzz_test/Fuzzer/test/MemcmpTest.cpp new file mode 100644 index 00000000..fdbf9468 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/MemcmpTest.cpp @@ -0,0 +1,31 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + // TODO: check other sizes. + if (Size >= 8 && memcmp(Data, "01234567", 8) == 0) { + if (Size >= 12 && memcmp(Data + 8, "ABCD", 4) == 0) { + if (Size >= 14 && memcmp(Data + 12, "XY", 2) == 0) { + if (Size >= 17 && memcmp(Data + 14, "KLM", 3) == 0) { + if (Size >= 27 && memcmp(Data + 17, "ABCDE-GHIJ", 10) == 0){ + fprintf(stderr, "BINGO %zd\n", Size); + for (size_t i = 0; i < Size; i++) { + uint8_t C = Data[i]; + if (C >= 32 && C < 127) + fprintf(stderr, "%c", C); + } + fprintf(stderr, "\n"); + exit(1); + } + } + } + } + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/NthRunCrashTest.cpp b/test/fuzz_test/Fuzzer/test/NthRunCrashTest.cpp new file mode 100644 index 00000000..b43e69e5 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/NthRunCrashTest.cpp @@ -0,0 +1,18 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Crash on the N-th execution. +#include <cstdint> +#include <cstddef> +#include <iostream> + +static int Counter; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Counter++ == 1000) { + std::cout << "BINGO; Found the target, exiting\n"; + exit(1); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/NullDerefOnEmptyTest.cpp b/test/fuzz_test/Fuzzer/test/NullDerefOnEmptyTest.cpp new file mode 100644 index 00000000..15371092 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/NullDerefOnEmptyTest.cpp @@ -0,0 +1,19 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the empty string. +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +static volatile int *Null = 0; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size == 0) { + std::cout << "Found the target, dereferencing NULL\n"; + *Null = 1; + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/NullDerefTest.cpp b/test/fuzz_test/Fuzzer/test/NullDerefTest.cpp new file mode 100644 index 00000000..3f03d249 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/NullDerefTest.cpp @@ -0,0 +1,26 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +static volatile int Sink; +static volatile int *Null = 0; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + std::cout << "Found the target, dereferencing NULL\n"; + *Null = 1; + } + } + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/OneHugeAllocTest.cpp b/test/fuzz_test/Fuzzer/test/OneHugeAllocTest.cpp new file mode 100644 index 00000000..8d3d1d6d --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/OneHugeAllocTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Tests OOM handling when there is a single large allocation. +#include <assert.h> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <iostream> + +static volatile char *SinkPtr; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + if (Size > 1 && Data[1] == 'i') { + if (Size > 2 && Data[2] == '!') { + size_t kSize = (size_t)1 << 31; + char *p = new char[kSize]; + memset(p, 0, kSize); + SinkPtr = p; + delete [] p; + } + } + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp b/test/fuzz_test/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp new file mode 100644 index 00000000..ea23a601 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp @@ -0,0 +1,27 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Tests OOM handling. +#include <assert.h> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <iostream> + +static volatile char *SinkPtr; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + if (Size > 1 && Data[1] == 'i') { + if (Size > 2 && Data[2] == '!') { + size_t kSize = 0xff000000U; + char *p = new char[kSize]; + SinkPtr = p; + delete [] p; + } + } + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/OutOfMemoryTest.cpp b/test/fuzz_test/Fuzzer/test/OutOfMemoryTest.cpp new file mode 100644 index 00000000..078a39ee --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/OutOfMemoryTest.cpp @@ -0,0 +1,31 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Tests OOM handling. +#include <assert.h> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <iostream> +#include <thread> + +static volatile char *SinkPtr; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + if (Size > 1 && Data[1] == 'i') { + if (Size > 2 && Data[2] == '!') { + while (true) { + size_t kSize = 1 << 28; + char *p = new char[kSize]; + memset(p, 0, kSize); + SinkPtr = p; + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + } + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/RepeatedBytesTest.cpp b/test/fuzz_test/Fuzzer/test/RepeatedBytesTest.cpp new file mode 100644 index 00000000..2fa6c78c --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/RepeatedBytesTest.cpp @@ -0,0 +1,29 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find repeated bytes. +#include <assert.h> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + // Looking for AAAAAAAAAAAAAAAAAAAAAA or some such. + size_t CurA = 0, MaxA = 0; + for (size_t i = 0; i < Size; i++) { + // Make sure there are no conditionals in the loop so that + // coverage can't help the fuzzer. + int EQ = Data[i] == 'A'; + CurA = EQ * (CurA + 1); + int GT = CurA > MaxA; + MaxA = GT * CurA + (!GT) * MaxA; + } + if (MaxA >= 20) { + std::cout << "BINGO; Found the target (Max: " << MaxA << "), exiting\n"; + exit(0); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/RepeatedMemcmp.cpp b/test/fuzz_test/Fuzzer/test/RepeatedMemcmp.cpp new file mode 100644 index 00000000..a327bbee --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/RepeatedMemcmp.cpp @@ -0,0 +1,22 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + + +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int Matches = 0; + for (size_t i = 0; i + 2 < Size; i += 3) { + const char *Pat = i % 2 ? "foo" : "bar"; + if (!memcmp(Data + i, Pat, 3)) + Matches++; + } + if (Matches > 20) { + fprintf(stderr, "BINGO!\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/ShrinkControlFlowTest.cpp b/test/fuzz_test/Fuzzer/test/ShrinkControlFlowTest.cpp new file mode 100644 index 00000000..0fd7c5e9 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/ShrinkControlFlowTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test that we can find the minimal item in the corpus (3 bytes: "FUZ"). +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <cstdio> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + int8_t Ids[256]; + memset(Ids, -1, sizeof(Ids)); + for (size_t i = 0; i < Size; i++) + if (Ids[Data[i]] == -1) + Ids[Data[i]] = i; + int F = Ids[(unsigned char)'F']; + int U = Ids[(unsigned char)'U']; + int Z = Ids[(unsigned char)'Z']; + if (F >= 0 && U > F && Z > U) { + Sink++; + //fprintf(stderr, "IDS: %d %d %d\n", F, U, Z); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/ShrinkValueProfileTest.cpp b/test/fuzz_test/Fuzzer/test/ShrinkValueProfileTest.cpp new file mode 100644 index 00000000..026b8ce2 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/ShrinkValueProfileTest.cpp @@ -0,0 +1,22 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test that we can find the minimal item in the corpus (3 bytes: "FUZ"). +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <cstdio> + +static volatile uint32_t Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < sizeof(uint32_t)) return 0; + uint32_t X, Y; + size_t Offset = Size < 8 ? 0 : Size / 2; + memcpy(&X, Data + Offset, sizeof(uint32_t)); + memcpy(&Y, "FUZZ", sizeof(uint32_t)); + Sink = X == Y; + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/SignedIntOverflowTest.cpp b/test/fuzz_test/Fuzzer/test/SignedIntOverflowTest.cpp new file mode 100644 index 00000000..7df32ad5 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SignedIntOverflowTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test for signed-integer-overflow. +#include <assert.h> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> +#include <climits> + +static volatile int Sink; +static int Large = INT_MAX; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + Large++; // int overflow. + } + } + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/SimpleCmpTest.cpp b/test/fuzz_test/Fuzzer/test/SimpleCmpTest.cpp new file mode 100644 index 00000000..0220c30f --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SimpleCmpTest.cpp @@ -0,0 +1,46 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find several narrow ranges. +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <cstdio> + +extern int AllLines[]; + +bool PrintOnce(int Line) { + if (!AllLines[Line]) + fprintf(stderr, "Seen line %d\n", Line); + AllLines[Line] = 1; + return true; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size != 22) return 0; + uint64_t x = 0; + int64_t y = 0; + int32_t z = 0; + uint16_t a = 0; + memcpy(&x, Data, 8); // 8 + memcpy(&y, Data + 8, 8); // 16 + memcpy(&z, Data + 16, sizeof(z)); // 20 + memcpy(&a, Data + 20, sizeof(a)); // 22 + + if (x > 1234567890 && PrintOnce(__LINE__) && + x < 1234567895 && PrintOnce(__LINE__) && + a == 0x4242 && PrintOnce(__LINE__) && + y >= 987654321 && PrintOnce(__LINE__) && + y <= 987654325 && PrintOnce(__LINE__) && + z < -10000 && PrintOnce(__LINE__) && + z >= -10005 && PrintOnce(__LINE__) && + z != -10003 && PrintOnce(__LINE__) && + true) { + fprintf(stderr, "BINGO; Found the target: size %zd (%zd, %zd, %d, %d), exiting.\n", + Size, x, y, z, a); + exit(1); + } + return 0; +} + +int AllLines[__LINE__ + 1]; // Must be the last line. diff --git a/test/fuzz_test/Fuzzer/test/SimpleDictionaryTest.cpp b/test/fuzz_test/Fuzzer/test/SimpleDictionaryTest.cpp new file mode 100644 index 00000000..cd7292bd --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SimpleDictionaryTest.cpp @@ -0,0 +1,29 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. +// The fuzzer must find a string based on dictionary words: +// "Elvis" +// "Presley" +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <cstring> +#include <iostream> + +static volatile int Zero = 0; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + const char *Expected = "ElvisPresley"; + if (Size < strlen(Expected)) return 0; + size_t Match = 0; + for (size_t i = 0; Expected[i]; i++) + if (Expected[i] + Zero == Data[i]) + Match++; + if (Match == strlen(Expected)) { + std::cout << "BINGO; Found the target, exiting\n"; + exit(1); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/SimpleHashTest.cpp b/test/fuzz_test/Fuzzer/test/SimpleHashTest.cpp new file mode 100644 index 00000000..00599de7 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SimpleHashTest.cpp @@ -0,0 +1,40 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// This test computes a checksum of the data (all but the last 4 bytes), +// and then compares the last 4 bytes with the computed value. +// A fuzzer with cmp traces is expected to defeat this check. +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <cstdio> + +// A modified jenkins_one_at_a_time_hash initialized by non-zero, +// so that simple_hash(0) != 0. See also +// https://en.wikipedia.org/wiki/Jenkins_hash_function +static uint32_t simple_hash(const uint8_t *Data, size_t Size) { + uint32_t Hash = 0x12039854; + for (uint32_t i = 0; i < Size; i++) { + Hash += Data[i]; + Hash += (Hash << 10); + Hash ^= (Hash >> 6); + } + Hash += (Hash << 3); + Hash ^= (Hash >> 11); + Hash += (Hash << 15); + return Hash; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 14) + return 0; + + uint32_t Hash = simple_hash(&Data[0], Size - 4); + uint32_t Want = reinterpret_cast<const uint32_t *>(&Data[Size - 4])[0]; + if (Hash != Want) + return 0; + fprintf(stderr, "BINGO; simple_hash defeated: %x == %x\n", (unsigned int)Hash, + (unsigned int)Want); + exit(1); + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/SimpleTest.cpp b/test/fuzz_test/Fuzzer/test/SimpleTest.cpp new file mode 100644 index 00000000..e53ea160 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SimpleTest.cpp @@ -0,0 +1,27 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <assert.h> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + std::cout << "BINGO; Found the target, exiting\n"; + exit(0); + } + } + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/SimpleThreadedTest.cpp b/test/fuzz_test/Fuzzer/test/SimpleThreadedTest.cpp new file mode 100644 index 00000000..5f02d3f8 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SimpleThreadedTest.cpp @@ -0,0 +1,25 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Threaded test for a fuzzer. The fuzzer should find "H" +#include <assert.h> +#include <cstdint> +#include <cstddef> +#include <cstring> +#include <iostream> +#include <thread> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + auto C = [&] { + if (Size >= 2 && Data[0] == 'H') { + std::cout << "BINGO; Found the target, exiting\n"; + abort(); + } + }; + std::thread T[] = {std::thread(C), std::thread(C), std::thread(C), + std::thread(C), std::thread(C), std::thread(C)}; + for (auto &X : T) + X.join(); + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/SingleMemcmpTest.cpp b/test/fuzz_test/Fuzzer/test/SingleMemcmpTest.cpp new file mode 100644 index 00000000..c73f68a7 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SingleMemcmpTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + char *S = (char*)Data; + if (Size >= 6 && !memcmp(S, "qwerty", 6)) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/SingleStrcmpTest.cpp b/test/fuzz_test/Fuzzer/test/SingleStrcmpTest.cpp new file mode 100644 index 00000000..73470b52 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SingleStrcmpTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + char *S = (char*)Data; + if (Size >= 7 && !strcmp(S, "qwerty")) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/SingleStrncmpTest.cpp b/test/fuzz_test/Fuzzer/test/SingleStrncmpTest.cpp new file mode 100644 index 00000000..dbcc464b --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SingleStrncmpTest.cpp @@ -0,0 +1,17 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + char *S = (char*)Data; + if (Size >= 6 && !strncmp(S, "qwerty", 6)) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/SpamyTest.cpp b/test/fuzz_test/Fuzzer/test/SpamyTest.cpp new file mode 100644 index 00000000..d294d4dc --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SpamyTest.cpp @@ -0,0 +1,21 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// The test spams to stderr and stdout. +#include <assert.h> +#include <cstdint> +#include <cstdio> +#include <cstddef> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + printf("PRINTF_STDOUT\n"); + fflush(stdout); + fprintf(stderr, "PRINTF_STDERR\n"); + std::cout << "STREAM_COUT\n"; + std::cout.flush(); + std::cerr << "STREAM_CERR\n"; + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/StrcmpTest.cpp b/test/fuzz_test/Fuzzer/test/StrcmpTest.cpp new file mode 100644 index 00000000..cd91dda7 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/StrcmpTest.cpp @@ -0,0 +1,32 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Break through a series of strcmp. +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cassert> + +bool Eq(const uint8_t *Data, size_t Size, const char *Str) { + char Buff[1024]; + size_t Len = strlen(Str); + if (Size < Len) return false; + if (Len >= sizeof(Buff)) return false; + memcpy(Buff, (char*)Data, Len); + Buff[Len] = 0; + int res = strcmp(Buff, Str); + return res == 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Eq(Data, Size, "ABC") && + Size >= 3 && Eq(Data + 3, Size - 3, "QWER") && + Size >= 7 && Eq(Data + 7, Size - 7, "ZXCVN") && + Size >= 14 && Data[13] == 42 + ) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/StrncmpOOBTest.cpp b/test/fuzz_test/Fuzzer/test/StrncmpOOBTest.cpp new file mode 100644 index 00000000..f70b003a --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/StrncmpOOBTest.cpp @@ -0,0 +1,21 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test that libFuzzer itself does not read out of bounds. +#include <assert.h> +#include <cstdint> +#include <cstring> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 5) return 0; + const char *Ch = reinterpret_cast<const char *>(Data); + if (Ch[Size - 3] == 'a') + Sink = strncmp(Ch + Size - 3, "abcdefg", 6); + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/StrncmpTest.cpp b/test/fuzz_test/Fuzzer/test/StrncmpTest.cpp new file mode 100644 index 00000000..5ffd011d --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/StrncmpTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find a particular string. +#include <cstring> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +static volatile int sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + // TODO: check other sizes. + char *S = (char*)Data; + if (Size >= 8 && strncmp(S, "123", 8)) + sink = 1; + if (Size >= 8 && strncmp(S, "01234567", 8) == 0) { + if (Size >= 12 && strncmp(S + 8, "ABCD", 4) == 0) { + if (Size >= 14 && strncmp(S + 12, "XY", 2) == 0) { + if (Size >= 17 && strncmp(S + 14, "KLM", 3) == 0) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + } + } + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/StrstrTest.cpp b/test/fuzz_test/Fuzzer/test/StrstrTest.cpp new file mode 100644 index 00000000..f021e75e --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/StrstrTest.cpp @@ -0,0 +1,28 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Test strstr and strcasestr hooks. +#include <string> +#include <string.h> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +// Windows does not have strcasestr and memmem, so we are not testing them. +#ifdef _WIN32 +#define strcasestr strstr +#define memmem(a, b, c, d) true +#endif + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 4) return 0; + std::string s(reinterpret_cast<const char*>(Data), Size); + if (strstr(s.c_str(), "FUZZ") && + strcasestr(s.c_str(), "aBcD") && + memmem(s.data(), s.size(), "kuku", 4) + ) { + fprintf(stderr, "BINGO\n"); + exit(1); + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/SwapCmpTest.cpp b/test/fuzz_test/Fuzzer/test/SwapCmpTest.cpp new file mode 100644 index 00000000..f79db4cc --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SwapCmpTest.cpp @@ -0,0 +1,34 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// The fuzzer must find several constants with swapped bytes. +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <cstdio> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 14) return 0; + uint64_t x = 0; + uint32_t y = 0; + uint16_t z = 0; + memcpy(&x, Data, sizeof(x)); + memcpy(&y, Data + Size / 2, sizeof(y)); + memcpy(&z, Data + Size - sizeof(z), sizeof(z)); + + x = __builtin_bswap64(x); + y = __builtin_bswap32(y); + z = __builtin_bswap16(z); + + if (x == 0x46555A5A5A5A5546ULL && + z == 0x4F4B && + y == 0x66757A7A && + true + ) { + if (Data[Size - 3] == 'z') { + fprintf(stderr, "BINGO; Found the target\n"); + exit(1); + } + } + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/Switch2Test.cpp b/test/fuzz_test/Fuzzer/test/Switch2Test.cpp new file mode 100644 index 00000000..3c6a3004 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/Switch2Test.cpp @@ -0,0 +1,35 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the interesting switch value. +#include <cstdint> +#include <cstdlib> +#include <cstdio> +#include <cstring> +#include <cstddef> + +int Switch(int a) { + switch(a) { + case 100001: return 1; + case 100002: return 2; + case 100003: return 4; + } + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + const int N = 3; + if (Size < N * sizeof(int)) return 0; + int Res = 0; + for (int i = 0; i < N; i++) { + int X; + memcpy(&X, Data + i * sizeof(int), sizeof(int)); + Res += Switch(X); + } + if (Res == 5 || Res == 3 || Res == 6 || Res == 7) { + fprintf(stderr, "BINGO; Found the target, exiting; Res=%d\n", Res); + exit(1); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/SwitchTest.cpp b/test/fuzz_test/Fuzzer/test/SwitchTest.cpp new file mode 100644 index 00000000..74e86c06 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/SwitchTest.cpp @@ -0,0 +1,58 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the interesting switch value. +#include <cstdint> +#include <cstdlib> +#include <cstdio> +#include <cstring> +#include <cstddef> + +static volatile int Sink; + +template<class T> +bool Switch(const uint8_t *Data, size_t Size) { + T X; + if (Size < sizeof(X)) return false; + memcpy(&X, Data, sizeof(X)); + switch (X) { + case 1: Sink = __LINE__; break; + case 101: Sink = __LINE__; break; + case 1001: Sink = __LINE__; break; + case 10001: Sink = __LINE__; break; +// case 100001: Sink = __LINE__; break; +// case 1000001: Sink = __LINE__; break; + case 10000001: Sink = __LINE__; break; + case 100000001: return true; + } + return false; +} + +bool ShortSwitch(const uint8_t *Data, size_t Size) { + short X; + if (Size < sizeof(short)) return false; + memcpy(&X, Data, sizeof(short)); + switch(X) { + case 42: Sink = __LINE__; break; + case 402: Sink = __LINE__; break; + case 4002: Sink = __LINE__; break; + case 5002: Sink = __LINE__; break; + case 7002: Sink = __LINE__; break; + case 9002: Sink = __LINE__; break; + case 14002: Sink = __LINE__; break; + case 21402: return true; + } + return false; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size >= 4 && Switch<int>(Data, Size) && + Size >= 12 && Switch<uint64_t>(Data + 4, Size - 4) && + Size >= 14 && ShortSwitch(Data + 12, 2) + ) { + fprintf(stderr, "BINGO; Found the target, exiting\n"); + exit(1); + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/ThreadedLeakTest.cpp b/test/fuzz_test/Fuzzer/test/ThreadedLeakTest.cpp new file mode 100644 index 00000000..75110711 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/ThreadedLeakTest.cpp @@ -0,0 +1,18 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// The fuzzer should find a leak in a non-main thread. +#include <cstdint> +#include <cstddef> +#include <thread> + +static volatile int *Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size == 0) return 0; + if (Data[0] != 'F') return 0; + std::thread T([&] { Sink = new int; }); + T.join(); + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/ThreadedTest.cpp b/test/fuzz_test/Fuzzer/test/ThreadedTest.cpp new file mode 100644 index 00000000..09137a9a --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/ThreadedTest.cpp @@ -0,0 +1,26 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Threaded test for a fuzzer. The fuzzer should not crash. +#include <assert.h> +#include <cstdint> +#include <cstddef> +#include <cstring> +#include <thread> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 8) return 0; + assert(Data); + auto C = [&] { + size_t Res = 0; + for (size_t i = 0; i < Size / 2; i++) + Res += memcmp(Data, Data + Size / 2, 4); + return Res; + }; + std::thread T[] = {std::thread(C), std::thread(C), std::thread(C), + std::thread(C), std::thread(C), std::thread(C)}; + for (auto &X : T) + X.join(); + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/TimeoutEmptyTest.cpp b/test/fuzz_test/Fuzzer/test/TimeoutEmptyTest.cpp new file mode 100644 index 00000000..8066f480 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/TimeoutEmptyTest.cpp @@ -0,0 +1,14 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the empty string. +#include <cstdint> +#include <cstddef> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static volatile int Zero = 0; + if (!Size) + while(!Zero) + ; + return 0; +} diff --git a/test/fuzz_test/Fuzzer/test/TimeoutTest.cpp b/test/fuzz_test/Fuzzer/test/TimeoutTest.cpp new file mode 100644 index 00000000..f8107012 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/TimeoutTest.cpp @@ -0,0 +1,26 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + Sink = 2; + while (Sink) + ; + } + } + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/TraceMallocTest.cpp b/test/fuzz_test/Fuzzer/test/TraceMallocTest.cpp new file mode 100644 index 00000000..43e6950e --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/TraceMallocTest.cpp @@ -0,0 +1,27 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Tests -trace_malloc +#include <assert.h> +#include <cstdint> +#include <cstdlib> +#include <cstddef> +#include <iostream> + +int *Ptr; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (!Size) return 0; + if (*Data == 1) { + delete Ptr; + Ptr = nullptr; + } else if (*Data == 2) { + delete Ptr; + Ptr = new int; + } else if (*Data == 3) { + if (!Ptr) + Ptr = new int; + } + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/UninstrumentedTest.cpp b/test/fuzz_test/Fuzzer/test/UninstrumentedTest.cpp new file mode 100644 index 00000000..ffe952c7 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/UninstrumentedTest.cpp @@ -0,0 +1,11 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// This test should not be instrumented. +#include <cstdint> +#include <cstddef> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return 0; +} + diff --git a/test/fuzz_test/Fuzzer/test/afl-driver-extra-stats.test b/test/fuzz_test/Fuzzer/test/afl-driver-extra-stats.test new file mode 100644 index 00000000..81e384e7 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/afl-driver-extra-stats.test @@ -0,0 +1,28 @@ +; Test that not specifying an extra stats file isn't broken. +RUN: unset AFL_DRIVER_EXTRA_STATS_FILENAME +RUN: AFLDriverTest + +; Test that specifying an invalid extra stats file causes a crash. +RUN: ASAN_OPTIONS= AFL_DRIVER_EXTRA_STATS_FILENAME=%T not --crash AFLDriverTest + +; Test that specifying a corrupted stats file causes a crash. +echo "peak_rss_mb :0" > %t +ASAN_OPTIONS= AFL_DRIVER_EXTRA_STATS_FILENAME=%t not --crash AFLDriverTest + +; Test that specifying a valid nonexistent stats file works. +RUN: rm -f %t +RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t AFLDriverTest +RUN: [[ $(grep "peak_rss_mb\|slowest_unit_time_sec" %t | wc -l) -eq 2 ]] + +; Test that specifying a valid preexisting stats file works. +RUN: printf "peak_rss_mb : 0\nslowest_unit_time_sec: 0\n" > %t +RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t AFLDriverTest +; Check that both lines were printed. +RUN: [[ $(grep "peak_rss_mb\|slowest_unit_time_sec" %t | wc -l) -eq 2 ]] + +; Test that peak_rss_mb and slowest_unit_time_in_secs are only updated when necessary. +; Check that both lines have 9999 since there's no way we have exceeded that +; amount of time or virtual memory. +RUN: printf "peak_rss_mb : 9999\nslowest_unit_time_sec: 9999\n" > %t +RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t AFLDriverTest +RUN: [[ $(grep "9999" %t | wc -l) -eq 2 ]] diff --git a/test/fuzz_test/Fuzzer/test/afl-driver-stderr.test b/test/fuzz_test/Fuzzer/test/afl-driver-stderr.test new file mode 100644 index 00000000..c0f9c839 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/afl-driver-stderr.test @@ -0,0 +1,10 @@ +; Test that not specifying a stderr file isn't broken. +RUN: unset AFL_DRIVER_STDERR_DUPLICATE_FILENAME +RUN: AFLDriverTest + +; Test that specifying an invalid file causes a crash. +RUN: ASAN_OPTIONS= AFL_DRIVER_STDERR_DUPLICATE_FILENAME="%T" not --crash AFLDriverTest + +; Test that a file is created when specified as the duplicate stderr. +RUN: AFL_DRIVER_STDERR_DUPLICATE_FILENAME=%t AFLDriverTest +RUN: stat %t diff --git a/test/fuzz_test/Fuzzer/test/caller-callee.test b/test/fuzz_test/Fuzzer/test/caller-callee.test new file mode 100644 index 00000000..76a951c5 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/caller-callee.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-CallerCalleeTest -use_value_profile=1 -cross_over=0 -max_len=6 -seed=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/coverage.test b/test/fuzz_test/Fuzzer/test/coverage.test new file mode 100644 index 00000000..fa11be50 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/coverage.test @@ -0,0 +1,19 @@ +CHECK: COVERAGE: +CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:13 +CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:14 +CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:16 +CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:19 +CHECK: COVERED_DIRS: {{.*}}lib/Fuzzer/test +RUN: not LLVMFuzzer-NullDerefTest -print_coverage=1 2>&1 | FileCheck %s + +RUN: LLVMFuzzer-DSOTest -print_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO +DSO: COVERAGE: +DSO-DAG: COVERED:{{.*}}DSO1{{.*}}DSO1.cpp +DSO-DAG: COVERED:{{.*}}DSO2{{.*}}DSO2.cpp +DSO-DAG: COVERED:{{.*}}LLVMFuzzerTestOneInput{{.*}}DSOTestMain +DSO-DAG: UNCOVERED_LINE:{{.*}}DSO1{{.*}}DSO1.cpp +DSO-DAG: UNCOVERED_LINE:{{.*}}DSO2{{.*}}DSO2.cpp +DSO-DAG: UNCOVERED_FUNC: in Uncovered1 +DSO-DAG: UNCOVERED_FUNC: in Uncovered2 +DSO-DAG: UNCOVERED_LINE: in LLVMFuzzerTestOneInput +DSO-DAG: UNCOVERED_FILE:{{.*}}DSOTestExtra.cpp diff --git a/test/fuzz_test/Fuzzer/test/dict1.txt b/test/fuzz_test/Fuzzer/test/dict1.txt new file mode 100644 index 00000000..520d0cc7 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/dict1.txt @@ -0,0 +1,4 @@ +# Dictionary for SimpleDictionaryTest + +a="Elvis" +b="Presley" diff --git a/test/fuzz_test/Fuzzer/test/dump_coverage.test b/test/fuzz_test/Fuzzer/test/dump_coverage.test new file mode 100644 index 00000000..9bd98daa --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/dump_coverage.test @@ -0,0 +1,16 @@ +RUN: DIR=%t_workdir +RUN: BUILD_DIR=$(pwd) +RUN: rm -rf $DIR && mkdir -p $DIR && cd $DIR +RUN: not $BUILD_DIR/LLVMFuzzer-NullDerefTest -dump_coverage=1 2>&1 | FileCheck %s +RUN: $BUILD_DIR/LLVMFuzzer-DSOTest -dump_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO +RUN: not $BUILD_DIR/LLVMFuzzer-NullDerefTest -dump_coverage=0 2>&1 | FileCheck %s --check-prefix=NOCOV +RUN: rm -rf $DIR + + +CHECK: SanitizerCoverage: ./LLVMFuzzer-NullDerefTest.{{.*}}.sancov {{.*}} PCs written + +DSO: SanitizerCoverage: ./LLVMFuzzer-DSOTest.{{.*}}.sancov {{.*}} PCs written +DSO-DAG: SanitizerCoverage: ./libLLVMFuzzer-DSO1.{{.*}}.sancov {{.*}} PCs written +DSO-DAG: SanitizerCoverage: ./libLLVMFuzzer-DSO2.{{.*}}.sancov {{.*}} PCs written + +NOCOV-NOT: SanitizerCoverage: {{.*}} PCs written diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-customcrossover.test b/test/fuzz_test/Fuzzer/test/fuzzer-customcrossover.test new file mode 100644 index 00000000..28d39ce3 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-customcrossover.test @@ -0,0 +1,10 @@ +RUN: rm -rf %t/CustomCrossover +RUN: mkdir -p %t/CustomCrossover +RUN: echo "0123456789" > %t/CustomCrossover/digits +RUN: echo "abcdefghij" > %t/CustomCrossover/chars +RUN: not LLVMFuzzer-CustomCrossOverTest -seed=1 -use_memcmp=0 -runs=100000 %t/CustomCrossover 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomCrossover +RUN: rm -rf %t/CustomCrossover + +LLVMFuzzerCustomCrossover: In LLVMFuzzerCustomCrossover +LLVMFuzzerCustomCrossover: BINGO + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-custommutator.test b/test/fuzz_test/Fuzzer/test/fuzzer-custommutator.test new file mode 100644 index 00000000..fcd740bf --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-custommutator.test @@ -0,0 +1,4 @@ +RUN: not LLVMFuzzer-CustomMutatorTest 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutator +LLVMFuzzerCustomMutator: In LLVMFuzzerCustomMutator +LLVMFuzzerCustomMutator: BINGO + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-dict.test b/test/fuzz_test/Fuzzer/test/fuzzer-dict.test new file mode 100644 index 00000000..dec002f6 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-dict.test @@ -0,0 +1,6 @@ +CHECK: BINGO +Done1000000: Done 1000000 runs in + +RUN: not LLVMFuzzer-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000003 2>&1 | FileCheck %s +RUN: LLVMFuzzer-SimpleDictionaryTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-dirs.test b/test/fuzz_test/Fuzzer/test/fuzzer-dirs.test new file mode 100644 index 00000000..63afe8df --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-dirs.test @@ -0,0 +1,15 @@ +RUN: rm -rf %t/SUB1 +RUN: mkdir -p %t/SUB1/SUB2/SUB3 +RUN: echo a > %t/SUB1/a +RUN: echo b > %t/SUB1/SUB2/b +RUN: echo c > %t/SUB1/SUB2/SUB3/c +RUN: LLVMFuzzer-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=SUBDIRS +SUBDIRS: READ units: 3 +RUN: echo zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz > %t/SUB1/long +RUN: LLVMFuzzer-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=LONG +LONG: INFO: -max_len is not provided, using 94 +RUN: rm -rf %t/SUB1 + +RUN: not LLVMFuzzer-SimpleTest NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR +NONEXISTENT_DIR: No such directory: NONEXISTENT_DIR; exiting + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-fdmask.test b/test/fuzz_test/Fuzzer/test/fuzzer-fdmask.test new file mode 100644 index 00000000..abbc4bd6 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-fdmask.test @@ -0,0 +1,30 @@ +RUN: LLVMFuzzer-SpamyTest -runs=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_0 +RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=0 2>&1 | FileCheck %s --check-prefix=FD_MASK_0 +RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_1 +RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=2 2>&1 | FileCheck %s --check-prefix=FD_MASK_2 +RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=FD_MASK_3 + +FD_MASK_0: PRINTF_STDOUT +FD_MASK_0: PRINTF_STDERR +FD_MASK_0: STREAM_COUT +FD_MASK_0: STREAM_CERR +FD_MASK_0: INITED + +FD_MASK_1-NOT: PRINTF_STDOUT +FD_MASK_1: PRINTF_STDERR +FD_MASK_1-NOT: STREAM_COUT +FD_MASK_1: STREAM_CERR +FD_MASK_1: INITED + +FD_MASK_2: PRINTF_STDOUT +FD_MASK_2-NOT: PRINTF_STDERR +FD_MASK_2: STREAM_COUT +FD_MASK_2-NOTE: STREAM_CERR +FD_MASK_2: INITED + +FD_MASK_3-NOT: PRINTF_STDOUT +FD_MASK_3-NOT: PRINTF_STDERR +FD_MASK_3-NOT: STREAM_COUT +FD_MASK_3-NOT: STREAM_CERR +FD_MASK_3: INITED + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-finalstats.test b/test/fuzz_test/Fuzzer/test/fuzzer-finalstats.test new file mode 100644 index 00000000..1cbcd10f --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-finalstats.test @@ -0,0 +1,11 @@ +RUN: LLVMFuzzer-SimpleTest -seed=1 -runs=77 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS +FINAL_STATS: stat::number_of_executed_units: 77 +FINAL_STATS: stat::average_exec_per_sec: 0 +FINAL_STATS: stat::new_units_added: +FINAL_STATS: stat::slowest_unit_time_sec: 0 +FINAL_STATS: stat::peak_rss_mb: + +RUN: LLVMFuzzer-SimpleTest %S/dict1.txt -runs=33 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS1 +FINAL_STATS1: stat::number_of_executed_units: 33 +FINAL_STATS1: stat::peak_rss_mb: + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-flags.test b/test/fuzz_test/Fuzzer/test/fuzzer-flags.test new file mode 100644 index 00000000..76ea2770 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-flags.test @@ -0,0 +1,10 @@ +RUN: LLVMFuzzer-SimpleTest -foo_bar=1 2>&1 | FileCheck %s --check-prefix=FOO_BAR +FOO_BAR: WARNING: unrecognized flag '-foo_bar=1'; use -help=1 to list all flags +FOO_BAR: BINGO + +RUN: LLVMFuzzer-SimpleTest -runs=10 --max_len=100 2>&1 | FileCheck %s --check-prefix=DASH_DASH +DASH_DASH: WARNING: did you mean '-max_len=100' (single dash)? +DASH_DASH: INFO: A corpus is not provided, starting from an empty corpus + +RUN: LLVMFuzzer-SimpleTest -help=1 2>&1 | FileCheck %s --check-prefix=NO_INTERNAL +NO_INTERNAL-NOT: internal flag diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-jobs.test b/test/fuzz_test/Fuzzer/test/fuzzer-jobs.test new file mode 100644 index 00000000..5bf8cfad --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-jobs.test @@ -0,0 +1,29 @@ +RUN: rm -rf %tmp +RUN: mkdir %tmp && cd %tmp +# Create a shared corpus directory +RUN: rm -rf FuzzerJobsTestCORPUS +RUN: mkdir FuzzerJobsTestCORPUS +RUN: rm -f fuzz-{0,1}.log +# Start fuzzer and in parallel check that the output files +# that should be created exist. +RUN: LLVMFuzzer-EmptyTest -max_total_time=4 -jobs=2 -workers=2 FuzzerJobsTestCORPUS > %t-fuzzer-jobs-test.log 2>&1 & export FUZZER_PID=$! +# Wait a short while to give time for the child processes +# to start fuzzing +RUN: sleep 2 +# If the instances are running in parallel they should have created their log +# files by now. +RUN: ls fuzz-0.log +RUN: ls fuzz-1.log +# Wait for libfuzzer to finish. +# This probably isn't portable but we need a way to block until +# the fuzzer is done otherwise we might remove the files while +# they are being used. +RUN: while kill -0 ${FUZZER_PID}; do : ; done +RUN: rm -f fuzz-{0,1}.log +RUN: rm -rf FuzzerJobsTestCORPUS +RUN: FileCheck -input-file=%t-fuzzer-jobs-test.log %s +RUN: rm %t-fuzzer-jobs-test.log +RUN: cd ../ + +CHECK-DAG: Job 0 exited with exit code 0 +CHECK-DAG: Job 1 exited with exit code 0 diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-leak.test b/test/fuzz_test/Fuzzer/test/fuzzer-leak.test new file mode 100644 index 00000000..9cf5c743 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-leak.test @@ -0,0 +1,35 @@ +REQUIRES: lsan +RUN: not LLVMFuzzer-LeakTest -runs=100000 -detect_leaks=1 2>&1 | FileCheck %s --check-prefix=LEAK_DURING +LEAK_DURING: ERROR: LeakSanitizer: detected memory leaks +LEAK_DURING: Direct leak of 4 byte(s) in 1 object(s) allocated from: +LEAK_DURING: INFO: to ignore leaks on libFuzzer side use -detect_leaks=0 +LEAK_DURING: Test unit written to ./leak- +LEAK_DURING-NOT: DONE +LEAK_DURING-NOT: Done + +RUN: not LLVMFuzzer-LeakTest -runs=0 -detect_leaks=1 %S 2>&1 | FileCheck %s --check-prefix=LEAK_IN_CORPUS +LEAK_IN_CORPUS: ERROR: LeakSanitizer: detected memory leaks +LEAK_IN_CORPUS: INFO: a leak has been found in the initial corpus. + +RUN: not LLVMFuzzer-LeakTest -runs=100000000 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=MULTI_RUN_LEAK +MULTI_RUN_LEAK-NOT: pulse +MULTI_RUN_LEAK: LeakSanitizer: detected memory leaks + +RUN: not LLVMFuzzer-LeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER +RUN: not LLVMFuzzer-LeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING +RUN: not LLVMFuzzer-ThreadedLeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER +RUN: not LLVMFuzzer-ThreadedLeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING +LEAK_AFTER: Done 100000 runs in +LEAK_AFTER: ERROR: LeakSanitizer: detected memory leaks + +RUN: not LLVMFuzzer-LeakTest -runs=100000 -max_len=1 2>&1 | FileCheck %s --check-prefix=MAX_LEN_1 +MAX_LEN_1: Test unit written to ./leak-7cf184f4c67ad58283ecb19349720b0cae756829 + +RUN: not LLVMFuzzer-LeakTimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=LEAK_TIMEOUT +LEAK_TIMEOUT: ERROR: libFuzzer: timeout after +LEAK_TIMEOUT-NOT: LeakSanitizer + +RUN: LLVMFuzzer-AccumulateAllocationsTest -detect_leaks=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=ACCUMULATE_ALLOCS +ACCUMULATE_ALLOCS: INFO: libFuzzer disabled leak detection after every mutation + +RUN: LLVMFuzzer-LeakTest -error_exitcode=0 diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-oom-with-profile.test b/test/fuzz_test/Fuzzer/test/fuzzer-oom-with-profile.test new file mode 100644 index 00000000..2b2b0b9d --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-oom-with-profile.test @@ -0,0 +1,6 @@ +REQUIRES: linux +RUN: not LLVMFuzzer-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s +CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 300Mb) +CHECK: Live Heap Allocations +CHECK: Test unit written to ./oom- +SUMMARY: libFuzzer: out-of-memory diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-oom.test b/test/fuzz_test/Fuzzer/test/fuzzer-oom.test new file mode 100644 index 00000000..8caf649e --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-oom.test @@ -0,0 +1,11 @@ +RUN: not LLVMFuzzer-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s +CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 300Mb) +CHECK: Test unit written to ./oom- +SUMMARY: libFuzzer: out-of-memory + +RUN: not LLVMFuzzer-OutOfMemorySingleLargeMallocTest 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC +SINGLE_LARGE_MALLOC: libFuzzer: out-of-memory (malloc(42{{.*}})) +SINGLE_LARGE_MALLOC: in LLVMFuzzerTestOneInput + +# Check that -rss_limit_mb=0 means no limit. +RUN: LLVMFuzzer-AccumulateAllocationsTest -runs=1000 -rss_limit_mb=0 diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-printcovpcs.test b/test/fuzz_test/Fuzzer/test/fuzzer-printcovpcs.test new file mode 100644 index 00000000..e4c6f0ed --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-printcovpcs.test @@ -0,0 +1,8 @@ +RUN: LLVMFuzzer-SimpleTest -print_pcs=1 -seed=1 2>&1 | FileCheck %s --check-prefix=PCS +PCS-NOT: NEW_PC +PCS:INITED +PCS:NEW_PC: {{0x[a-f0-9]+}} +PCS:NEW_PC: {{0x[a-f0-9]+}} +PCS:NEW +PCS:BINGO + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-runs.test b/test/fuzz_test/Fuzzer/test/fuzzer-runs.test new file mode 100644 index 00000000..056c4478 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-runs.test @@ -0,0 +1,8 @@ +RUN: mkdir -p %t +RUN: echo abcd > %t/NthRunCrashTest.in +RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in +RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in -runs=10 +RUN: not LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in -runs=10000 2>&1 | FileCheck %s +RUN: rm %t/NthRunCrashTest.in +CHECK: BINGO + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-seed.test b/test/fuzz_test/Fuzzer/test/fuzzer-seed.test new file mode 100644 index 00000000..f1bdf9e4 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-seed.test @@ -0,0 +1,3 @@ +RUN: LLVMFuzzer-SimpleCmpTest -seed=-1 -runs=0 2>&1 | FileCheck %s --check-prefix=CHECK_SEED_MINUS_ONE +CHECK_SEED_MINUS_ONE: Seed: 4294967295 + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-segv.test b/test/fuzz_test/Fuzzer/test/fuzzer-segv.test new file mode 100644 index 00000000..330f03bc --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-segv.test @@ -0,0 +1,5 @@ +RUN: ASAN_OPTIONS=handle_segv=0 not LLVMFuzzer-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER +LIBFUZZER_OWN_SEGV_HANDLER: == ERROR: libFuzzer: deadly signal +LIBFUZZER_OWN_SEGV_HANDLER: SUMMARY: libFuzzer: deadly signal +LIBFUZZER_OWN_SEGV_HANDLER: Test unit written to ./crash- + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-singleinputs.test b/test/fuzz_test/Fuzzer/test/fuzzer-singleinputs.test new file mode 100644 index 00000000..ca8403bf --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-singleinputs.test @@ -0,0 +1,16 @@ +RUN: not LLVMFuzzer-NullDerefTest %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInput +SingleInput-NOT: Test unit written to ./crash- + +RUN: rm -rf %tmp/SINGLE_INPUTS +RUN: mkdir -p %tmp/SINGLE_INPUTS +RUN: echo aaa > %tmp/SINGLE_INPUTS/aaa +RUN: echo bbb > %tmp/SINGLE_INPUTS/bbb +RUN: LLVMFuzzer-SimpleTest %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS +RUN: LLVMFuzzer-SimpleTest -max_len=2 %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS +RUN: rm -rf %tmp/SINGLE_INPUTS +SINGLE_INPUTS: LLVMFuzzer-SimpleTest: Running 2 inputs 1 time(s) each. +SINGLE_INPUTS: aaa in +SINGLE_INPUTS: bbb in +SINGLE_INPUTS: NOTE: fuzzing was not performed, you have only +SINGLE_INPUTS: executed the target code on a fixed set of inputs. + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-threaded.test b/test/fuzz_test/Fuzzer/test/fuzzer-threaded.test new file mode 100644 index 00000000..c58a3345 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-threaded.test @@ -0,0 +1,7 @@ +CHECK: Done 1000 runs in + +RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-timeout.test b/test/fuzz_test/Fuzzer/test/fuzzer-timeout.test new file mode 100644 index 00000000..beb08671 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-timeout.test @@ -0,0 +1,19 @@ +RUN: not LLVMFuzzer-TimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutTest +TimeoutTest: ALARM: working on the last Unit for +TimeoutTest: Test unit written to ./timeout- +TimeoutTest: == ERROR: libFuzzer: timeout after +TimeoutTest: #0 +TimeoutTest: #1 +TimeoutTest: #2 +TimeoutTest: SUMMARY: libFuzzer: timeout + +RUN: not LLVMFuzzer-TimeoutTest -timeout=1 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInputTimeoutTest +SingleInputTimeoutTest: ALARM: working on the last Unit for {{[1-3]}} seconds +SingleInputTimeoutTest-NOT: Test unit written to ./timeout- + +RUN: LLVMFuzzer-TimeoutTest -timeout=1 -timeout_exitcode=0 + +RUN: not LLVMFuzzer-TimeoutEmptyTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutEmptyTest +TimeoutEmptyTest: ALARM: working on the last Unit for +TimeoutEmptyTest: == ERROR: libFuzzer: timeout after +TimeoutEmptyTest: SUMMARY: libFuzzer: timeout diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-traces-hooks.test b/test/fuzz_test/Fuzzer/test/fuzzer-traces-hooks.test new file mode 100644 index 00000000..71fe6f2d --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-traces-hooks.test @@ -0,0 +1,25 @@ +// FIXME: Support sanitizer hooks for memcmp and strcmp need +// to be implemented in the sanitizer runtime for platforms other +// than linux +REQUIRES: linux +CHECK: BINGO +Done1000000: Done 1000000 runs in + +RUN: not LLVMFuzzer-MemcmpTest -seed=4294967295 -runs=100000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-MemcmpTest -use_memcmp=0 -seed=4294967295 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + +RUN: not LLVMFuzzer-StrncmpTest -seed=2 -runs=100000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-StrncmpTest -use_memcmp=0 -seed=3 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + +RUN: not LLVMFuzzer-StrcmpTest -seed=4 -runs=200000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-StrcmpTest -use_memcmp=0 -seed=5 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + +RUN: not LLVMFuzzer-StrstrTest -seed=6 -runs=200000 2>&1 | FileCheck %s +RUN: LLVMFuzzer-StrstrTest -use_memmem=0 -seed=7 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 + +RUN: LLVMFuzzer-RepeatedMemcmp -seed=10 -runs=100000 2>&1 | FileCheck %s --check-prefix=RECOMMENDED_DICT +RECOMMENDED_DICT:###### Recommended dictionary. ###### +RECOMMENDED_DICT-DAG: "foo" +RECOMMENDED_DICT-DAG: "bar" +RECOMMENDED_DICT:###### End of recommended dictionary. ###### + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-ubsan.test b/test/fuzz_test/Fuzzer/test/fuzzer-ubsan.test new file mode 100644 index 00000000..0e8ad6c9 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer-ubsan.test @@ -0,0 +1,4 @@ +RUN: not LLVMFuzzer-SignedIntOverflowTest-Ubsan 2>&1 | FileCheck %s +CHECK: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' +CHECK: Test unit written to ./crash- + diff --git a/test/fuzz_test/Fuzzer/test/fuzzer.test b/test/fuzz_test/Fuzzer/test/fuzzer.test new file mode 100644 index 00000000..2f91c219 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/fuzzer.test @@ -0,0 +1,57 @@ +CHECK: BINGO +Done1000000: Done 1000000 runs in + +RUN: LLVMFuzzer-SimpleTest 2>&1 | FileCheck %s + +# only_ascii mode. Will perform some minimal self-validation. +RUN: LLVMFuzzer-SimpleTest -only_ascii=1 2>&1 + +RUN: LLVMFuzzer-SimpleCmpTest -max_total_time=1 -use_cmp=0 2>&1 | FileCheck %s --check-prefix=MaxTotalTime +MaxTotalTime: Done {{.*}} runs in {{.}} second(s) + +RUN: not LLVMFuzzer-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest +RUN: not LLVMFuzzer-NullDerefTest -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=NullDerefTest +NullDerefTest: ERROR: AddressSanitizer: SEGV on unknown address +NullDerefTest: Test unit written to ./crash- +RUN: not LLVMFuzzer-NullDerefTest -artifact_prefix=ZZZ 2>&1 | FileCheck %s --check-prefix=NullDerefTestPrefix +NullDerefTestPrefix: Test unit written to ZZZcrash- +RUN: not LLVMFuzzer-NullDerefTest -artifact_prefix=ZZZ -exact_artifact_path=FOOBAR 2>&1 | FileCheck %s --check-prefix=NullDerefTestExactPath +NullDerefTestExactPath: Test unit written to FOOBAR + +RUN: not LLVMFuzzer-NullDerefOnEmptyTest -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=NULL_DEREF_ON_EMPTY +NULL_DEREF_ON_EMPTY: stat::number_of_executed_units: + +#not LLVMFuzzer-FullCoverageSetTest -timeout=15 -seed=1 -mutate_depth=2 -use_full_coverage_set=1 2>&1 | FileCheck %s + +RUN: not LLVMFuzzer-CounterTest -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s --check-prefix=COUNTERS + +COUNTERS: INITED {{.*}} {{bits:|ft:}} +COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}} +COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}} +COUNTERS: BINGO + +# Don't run UninstrumentedTest for now since we build libFuzzer itself with asan. +DISABLED: not LLVMFuzzer-UninstrumentedTest-Uninstrumented 2>&1 | FileCheck %s --check-prefix=UNINSTRUMENTED +UNINSTRUMENTED: ERROR: __sanitizer_set_death_callback is not defined. Exiting. + +RUN: not LLVMFuzzer-UninstrumentedTest-NoCoverage 2>&1 | FileCheck %s --check-prefix=NO_COVERAGE +NO_COVERAGE: ERROR: no interesting inputs were found. Is the code instrumented for coverage? Exiting + +RUN: not LLVMFuzzer-BufferOverflowOnInput 2>&1 | FileCheck %s --check-prefix=OOB +OOB: AddressSanitizer: heap-buffer-overflow +OOB: is located 0 bytes to the right of 3-byte region + +RUN: not LLVMFuzzer-InitializeTest -use_value_profile=1 2>&1 | FileCheck %s + +RUN: not LLVMFuzzer-DSOTest 2>&1 | FileCheck %s --check-prefix=DSO +DSO: INFO: Loaded 3 modules +DSO: BINGO + +RUN: LLVMFuzzer-SimpleTest -exit_on_src_pos=SimpleTest.cpp:17 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS +RUN: LLVMFuzzer-ShrinkControlFlowTest -exit_on_src_pos=ShrinkControlFlowTest.cpp:23 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS +EXIT_ON_SRC_POS: INFO: found line matching '{{.*}}', exiting. + +RUN: ASAN_OPTIONS=strict_string_checks=1 not LLVMFuzzer-StrncmpOOBTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=STRNCMP +STRNCMP: AddressSanitizer: heap-buffer-overflow +STRNCMP-NOT: __sanitizer_weak_hook_strncmp +STRNCMP: in LLVMFuzzerTestOneInput diff --git a/test/fuzz_test/Fuzzer/test/hi.txt b/test/fuzz_test/Fuzzer/test/hi.txt new file mode 100644 index 00000000..2f9031f0 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/hi.txt @@ -0,0 +1 @@ +Hi! \ No newline at end of file diff --git a/test/fuzz_test/Fuzzer/test/lit.cfg b/test/fuzz_test/Fuzzer/test/lit.cfg new file mode 100644 index 00000000..745af0c3 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/lit.cfg @@ -0,0 +1,29 @@ +import lit.formats +import sys + +config.name = "LLVMFuzzer" +config.test_format = lit.formats.ShTest(True) +config.suffixes = ['.test'] +config.test_source_root = os.path.dirname(__file__) + +# Tweak PATH to include llvm tools dir and current exec dir. +llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) +if (not llvm_tools_dir) or (not os.path.exists(llvm_tools_dir)): + lit_config.fatal("Invalid llvm_tools_dir config attribute: %r" % llvm_tools_dir) +path = os.path.pathsep.join((llvm_tools_dir, config.test_exec_root, + config.environment['PATH'])) +config.environment['PATH'] = path + +if config.has_lsan: + lit_config.note('lsan feature available') + config.available_features.add('lsan') +else: + lit_config.note('lsan feature unavailable') + +if sys.platform.startswith('linux'): + # Note the value of ``sys.platform`` is not consistent + # between python 2 and 3, hence the use of ``.startswith()``. + lit_config.note('linux feature available') + config.available_features.add('linux') +else: + lit_config.note('linux feature unavailable') diff --git a/test/fuzz_test/Fuzzer/test/lit.site.cfg.in b/test/fuzz_test/Fuzzer/test/lit.site.cfg.in new file mode 100644 index 00000000..03e86c48 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/lit.site.cfg.in @@ -0,0 +1,4 @@ +config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" +config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" +config.has_lsan = True if @HAS_LSAN@ == 1 else False +lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") diff --git a/test/fuzz_test/Fuzzer/test/merge.test b/test/fuzz_test/Fuzzer/test/merge.test new file mode 100644 index 00000000..1f1810eb --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/merge.test @@ -0,0 +1,46 @@ +CHECK: BINGO + +RUN: rm -rf %tmp/T1 %tmp/T2 +RUN: mkdir -p %tmp/T1 %tmp/T2 +RUN: echo F..... > %tmp/T1/1 +RUN: echo .U.... > %tmp/T1/2 +RUN: echo ..Z... > %tmp/T1/3 + +# T1 has 3 elements, T2 is empty. +RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK1 +CHECK1: MERGE-OUTER: 3 files, 3 in the initial corpus +CHECK1: MERGE-OUTER: 0 new files with 0 new features added + +RUN: echo ...Z.. > %tmp/T2/1 +RUN: echo ....E. > %tmp/T2/2 +RUN: echo .....R > %tmp/T2/3 +RUN: echo F..... > %tmp/T2/a +RUN: echo .U.... > %tmp/T2/b +RUN: echo ..Z... > %tmp/T2/c + +# T1 has 3 elements, T2 has 6 elements, only 3 are new. +RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK2 +CHECK2: MERGE-OUTER: 9 files, 3 in the initial corpus +CHECK2: MERGE-OUTER: 3 new files with 3 new features added + +# Now, T1 has 6 units and T2 has no new interesting units. +RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK3 +CHECK3: MERGE-OUTER: 12 files, 6 in the initial corpus +CHECK3: MERGE-OUTER: 0 new files with 0 new features added + +# Check that we respect max_len during the merge and don't crash. +RUN: rm %tmp/T1/??* +RUN: echo looooooooong > %tmp/T2/looooooooong +RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 -max_len=6 2>&1 | FileCheck %s --check-prefix=MAX_LEN +MAX_LEN: MERGE-OUTER: 3 new files + +# Check that merge tolerates failures. +RUN: rm %tmp/T1/??* +RUN: echo 'FUZZER' > %tmp/T2/FUZZER +RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=MERGE_WITH_CRASH +MERGE_WITH_CRASH: MERGE-OUTER: succesfull in 2 attempt(s) +MERGE_WITH_CRASH: MERGE-OUTER: 3 new files + +# Check that we actually limit the size with max_len +RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 -max_len=5 2>&1 | FileCheck %s --check-prefix=MERGE_LEN5 +MERGE_LEN5: MERGE-OUTER: succesfull in 1 attempt(s) diff --git a/test/fuzz_test/Fuzzer/test/minimize_crash.test b/test/fuzz_test/Fuzzer/test/minimize_crash.test new file mode 100644 index 00000000..7e540659 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/minimize_crash.test @@ -0,0 +1,6 @@ +RUN: echo 'Hi!rv349f34t3gg' > not_minimal_crash +RUN: LLVMFuzzer-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 2>&1 | FileCheck %s +CHECK: CRASH_MIN: failed to minimize beyond minimized-from-{{.*}} (3 bytes), exiting +RUN: LLVMFuzzer-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 -exact_artifact_path=exact_minimized_path 2>&1 | FileCheck %s --check-prefix=CHECK_EXACT +CHECK_EXACT: CRASH_MIN: failed to minimize beyond exact_minimized_path (3 bytes), exiting +RUN: rm not_minimal_crash minimized-from-* exact_minimized_path diff --git a/test/fuzz_test/Fuzzer/test/no-coverage/CMakeLists.txt b/test/fuzz_test/Fuzzer/test/no-coverage/CMakeLists.txt new file mode 100644 index 00000000..d2f6f438 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/no-coverage/CMakeLists.txt @@ -0,0 +1,29 @@ +# These tests are not instrumented with coverage, +# but have coverage rt in the binary. + +set(CMAKE_CXX_FLAGS + "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard") + +set(NoCoverageTests + UninstrumentedTest + ) + +foreach(Test ${NoCoverageTests}) + add_libfuzzer_test(${Test}-NoCoverage SOURCES ../${Test}.cpp) +endforeach() + + +############################################################################### +# AFL Driver test +############################################################################### + +add_executable(AFLDriverTest + ../AFLDriverTest.cpp ../../afl/afl_driver.cpp) + +set_target_properties(AFLDriverTest + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/lib/Fuzzer/test" + ) + +# Propagate value into parent directory +set(TestBinaries ${TestBinaries} AFLDriverTest PARENT_SCOPE) diff --git a/test/fuzz_test/Fuzzer/test/repeated-bytes.test b/test/fuzz_test/Fuzzer/test/repeated-bytes.test new file mode 100644 index 00000000..71394087 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/repeated-bytes.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: LLVMFuzzer-RepeatedBytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/shrink.test b/test/fuzz_test/Fuzzer/test/shrink.test new file mode 100644 index 00000000..edb86cb1 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/shrink.test @@ -0,0 +1,7 @@ +RUN: LLVMFuzzer-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=1 2>&1 | FileCheck %s --check-prefix=SHRINK1 +RUN: LLVMFuzzer-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=0 2>&1 | FileCheck %s --check-prefix=SHRINK0 +RUN: LLVMFuzzer-ShrinkValueProfileTest -seed=1 -exit_on_item=aea2e3923af219a8956f626558ef32f30a914ebc -runs=100000 -shrink=1 -use_value_profile=1 2>&1 | FileCheck %s --check-prefix=SHRINK1_VP + +SHRINK0: Done 1000000 runs in +SHRINK1: INFO: found item with checksum '0eb8e4ed029b774d80f2b66408203801cb982a60', exiting. +SHRINK1_VP: INFO: found item with checksum 'aea2e3923af219a8956f626558ef32f30a914ebc', exiting diff --git a/test/fuzz_test/Fuzzer/test/simple-cmp.test b/test/fuzz_test/Fuzzer/test/simple-cmp.test new file mode 100644 index 00000000..145a0366 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/simple-cmp.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-SimpleCmpTest -seed=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/standalone.test b/test/fuzz_test/Fuzzer/test/standalone.test new file mode 100644 index 00000000..3097b3ff --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/standalone.test @@ -0,0 +1,4 @@ +RUN: LLVMFuzzer-StandaloneInitializeTest %S/hi.txt %S/dict1.txt 2>&1 | FileCheck %s +CHECK: StandaloneFuzzTargetMain: running 2 inputs +CHECK: Done: {{.*}}hi.txt: (3 bytes) +CHECK: Done: {{.*}}dict1.txt: (61 bytes) diff --git a/test/fuzz_test/Fuzzer/test/swap-cmp.test b/test/fuzz_test/Fuzzer/test/swap-cmp.test new file mode 100644 index 00000000..908b7986 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/swap-cmp.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-SwapCmpTest -seed=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/trace-malloc.test b/test/fuzz_test/Fuzzer/test/trace-malloc.test new file mode 100644 index 00000000..c9514790 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/trace-malloc.test @@ -0,0 +1,10 @@ +RUN: LLVMFuzzer-TraceMallocTest -seed=1 -trace_malloc=1 -runs=10000 2>&1 | FileCheck %s +CHECK-DAG: MallocFreeTracer: STOP 0 0 (same) +CHECK-DAG: MallocFreeTracer: STOP 0 1 (DIFFERENT) +CHECK-DAG: MallocFreeTracer: STOP 1 0 (DIFFERENT) +CHECK-DAG: MallocFreeTracer: STOP 1 1 (same) + +RUN: LLVMFuzzer-TraceMallocTest -seed=1 -trace_malloc=2 -runs=1000 2>&1 | FileCheck %s --check-prefix=TRACE2 +TRACE2-DAG: FREE[0] +TRACE2-DAG: MALLOC[0] +TRACE2-DAG: in LLVMFuzzerTestOneInput diff --git a/test/fuzz_test/Fuzzer/test/ubsan/CMakeLists.txt b/test/fuzz_test/Fuzzer/test/ubsan/CMakeLists.txt new file mode 100644 index 00000000..7a9eacdb --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/ubsan/CMakeLists.txt @@ -0,0 +1,15 @@ +# These tests are instrumented with ubsan in non-recovery mode. + +set(CMAKE_CXX_FLAGS + "${LIBFUZZER_FLAGS_BASE} -fsanitize=undefined -fno-sanitize-recover=all") + +set(UbsanTests + SignedIntOverflowTest + ) + +foreach(Test ${UbsanTests}) + add_libfuzzer_test(${Test}-Ubsan SOURCES ../${Test}.cpp) +endforeach() + +# Propagate value into parent directory +set(TestBinaries ${TestBinaries} PARENT_SCOPE) diff --git a/test/fuzz_test/Fuzzer/test/ulimit.test b/test/fuzz_test/Fuzzer/test/ulimit.test new file mode 100644 index 00000000..a60636c3 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/ulimit.test @@ -0,0 +1,2 @@ +RUN: ulimit -s 1000 +RUN: LLVMFuzzer-SimpleTest diff --git a/test/fuzz_test/Fuzzer/test/uninstrumented/CMakeLists.txt b/test/fuzz_test/Fuzzer/test/uninstrumented/CMakeLists.txt new file mode 100644 index 00000000..29b66e6e --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/uninstrumented/CMakeLists.txt @@ -0,0 +1,16 @@ +# These tests are not instrumented with coverage and don't +# have coverage rt in the binary. + +set(CMAKE_CXX_FLAGS + "${LIBFUZZER_FLAGS_BASE} -fno-sanitize=all -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard") + +set(UninstrumentedTests + UninstrumentedTest + ) + +foreach(Test ${UninstrumentedTests}) + add_libfuzzer_test(${Test}-Uninstrumented SOURCES ../${Test}.cpp) +endforeach() + +# Propagate value into parent directory +set(TestBinaries ${TestBinaries} PARENT_SCOPE) diff --git a/test/fuzz_test/Fuzzer/test/unit/lit.cfg b/test/fuzz_test/Fuzzer/test/unit/lit.cfg new file mode 100644 index 00000000..0cc31939 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/unit/lit.cfg @@ -0,0 +1,7 @@ +import lit.formats + +config.name = "LLVMFuzzer-Unittest" +print config.test_exec_root +config.test_format = lit.formats.GoogleTest(".", "Unittest") +config.suffixes = [] +config.test_source_root = config.test_exec_root diff --git a/test/fuzz_test/Fuzzer/test/unit/lit.site.cfg.in b/test/fuzz_test/Fuzzer/test/unit/lit.site.cfg.in new file mode 100644 index 00000000..114daf47 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/unit/lit.site.cfg.in @@ -0,0 +1,2 @@ +config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" +lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/unit/lit.cfg") diff --git a/test/fuzz_test/Fuzzer/test/value-profile-cmp.test b/test/fuzz_test/Fuzzer/test/value-profile-cmp.test new file mode 100644 index 00000000..48edba4f --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-cmp.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-SimpleCmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/value-profile-cmp2.test b/test/fuzz_test/Fuzzer/test/value-profile-cmp2.test new file mode 100644 index 00000000..43d62400 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-cmp2.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-SimpleHashTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/value-profile-cmp3.test b/test/fuzz_test/Fuzzer/test/value-profile-cmp3.test new file mode 100644 index 00000000..8a962763 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-cmp3.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-AbsNegAndConstantTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/value-profile-cmp4.test b/test/fuzz_test/Fuzzer/test/value-profile-cmp4.test new file mode 100644 index 00000000..1e7131e5 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-cmp4.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-AbsNegAndConstant64Test -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/value-profile-div.test b/test/fuzz_test/Fuzzer/test/value-profile-div.test new file mode 100644 index 00000000..ba45e412 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-div.test @@ -0,0 +1,3 @@ +CHECK: AddressSanitizer: FPE +RUN: not LLVMFuzzer-DivTest -seed=1 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s + diff --git a/test/fuzz_test/Fuzzer/test/value-profile-load.test b/test/fuzz_test/Fuzzer/test/value-profile-load.test new file mode 100644 index 00000000..14d3109a --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-load.test @@ -0,0 +1,3 @@ +CHECK: AddressSanitizer: global-buffer-overflow +RUN: not LLVMFuzzer-LoadTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s + diff --git a/test/fuzz_test/Fuzzer/test/value-profile-mem.test b/test/fuzz_test/Fuzzer/test/value-profile-mem.test new file mode 100644 index 00000000..09d737db --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-mem.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-SingleMemcmpTest -seed=1 -use_cmp=0 -use_memcmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/value-profile-set.test b/test/fuzz_test/Fuzzer/test/value-profile-set.test new file mode 100644 index 00000000..9d06c365 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-set.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-FourIndependentBranchesTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s + diff --git a/test/fuzz_test/Fuzzer/test/value-profile-strcmp.test b/test/fuzz_test/Fuzzer/test/value-profile-strcmp.test new file mode 100644 index 00000000..1e7ef9b4 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-strcmp.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-SingleStrcmpTest -seed=1 -use_cmp=0 -use_memcmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/value-profile-strncmp.test b/test/fuzz_test/Fuzzer/test/value-profile-strncmp.test new file mode 100644 index 00000000..65097318 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-strncmp.test @@ -0,0 +1,2 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-SingleStrncmpTest -seed=1 -use_cmp=0 -use_memcmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzz_test/Fuzzer/test/value-profile-switch.test b/test/fuzz_test/Fuzzer/test/value-profile-switch.test new file mode 100644 index 00000000..1947f568 --- /dev/null +++ b/test/fuzz_test/Fuzzer/test/value-profile-switch.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: not LLVMFuzzer-SwitchTest -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s +RUN: not LLVMFuzzer-Switch2Test -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s From 6e8791912ff4b3480acaa350c628404f04aefa47 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 22 Dec 2016 09:09:40 +0100 Subject: [PATCH 33/71] :construction: added fuzzer from OSS-Fuzz --- test/fuzz_test/parse_fuzzer.cc | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 test/fuzz_test/parse_fuzzer.cc diff --git a/test/fuzz_test/parse_fuzzer.cc b/test/fuzz_test/parse_fuzzer.cc new file mode 100644 index 00000000..bb8b3d37 --- /dev/null +++ b/test/fuzz_test/parse_fuzzer.cc @@ -0,0 +1,36 @@ +// Copyright 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <iostream> +#include <sstream> +#include <json.hpp> + +using json = nlohmann::json; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + try { + std::stringstream s; + s << json::parse(data, data + size); + try { + auto j = json::parse(s.str()); + std::stringstream s2; + s2 << j; + assert(s.str() == s2.str()); + assert(j == json::parse(s.str())); + } catch (const std::invalid_argument&) { + assert(0); + } + } catch (const std::invalid_argument&) { } + return 0; +} From ad241a2260ed33fa0b0aa40ec65e5a68650eb5f7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 22 Dec 2016 09:35:53 +0100 Subject: [PATCH 34/71] :hammer: moved third-party code into separate folder --- .gitignore | 2 +- test/CMakeLists.txt | 4 +-- test/Makefile | 8 ++--- .../fuzzer-parse_json.cpp} | 34 +++++++++++-------- .../Fuzzer/CMakeLists.txt | 0 .../Fuzzer/FuzzerCorpus.h | 0 .../Fuzzer/FuzzerCrossOver.cpp | 0 .../Fuzzer/FuzzerDefs.h | 0 .../Fuzzer/FuzzerDictionary.h | 0 .../Fuzzer/FuzzerDriver.cpp | 0 .../Fuzzer/FuzzerExtFunctions.def | 0 .../Fuzzer/FuzzerExtFunctions.h | 0 .../Fuzzer/FuzzerExtFunctionsDlsym.cpp | 0 .../Fuzzer/FuzzerExtFunctionsWeak.cpp | 0 .../Fuzzer/FuzzerExtFunctionsWeakAlias.cpp | 0 .../Fuzzer/FuzzerFlags.def | 0 .../Fuzzer/FuzzerIO.cpp | 0 .../Fuzzer/FuzzerIO.h | 0 .../Fuzzer/FuzzerIOPosix.cpp | 0 .../Fuzzer/FuzzerIOWindows.cpp | 0 .../Fuzzer/FuzzerInterface.h | 0 .../Fuzzer/FuzzerInternal.h | 0 .../Fuzzer/FuzzerLoop.cpp | 0 .../Fuzzer/FuzzerMain.cpp | 0 .../Fuzzer/FuzzerMerge.cpp | 0 .../Fuzzer/FuzzerMerge.h | 0 .../Fuzzer/FuzzerMutate.cpp | 0 .../Fuzzer/FuzzerMutate.h | 0 .../Fuzzer/FuzzerOptions.h | 0 .../Fuzzer/FuzzerRandom.h | 0 .../Fuzzer/FuzzerSHA1.cpp | 0 .../Fuzzer/FuzzerSHA1.h | 0 .../Fuzzer/FuzzerTracePC.cpp | 0 .../Fuzzer/FuzzerTracePC.h | 0 .../Fuzzer/FuzzerTraceState.cpp | 0 .../Fuzzer/FuzzerUtil.cpp | 0 .../Fuzzer/FuzzerUtil.h | 0 .../Fuzzer/FuzzerUtilDarwin.cpp | 0 .../Fuzzer/FuzzerUtilLinux.cpp | 0 .../Fuzzer/FuzzerUtilPosix.cpp | 0 .../Fuzzer/FuzzerUtilWindows.cpp | 0 .../Fuzzer/FuzzerValueBitMap.h | 0 .../Fuzzer/README.txt | 0 .../Fuzzer/afl/afl_driver.cpp | 0 .../{fuzz_test => thirdparty}/Fuzzer/build.sh | 0 .../{fuzz_test => thirdparty}/Fuzzer/cxx.dict | 0 .../standalone/StandaloneFuzzTargetMain.c | 0 .../Fuzzer/test/AFLDriverTest.cpp | 0 .../Fuzzer/test/AbsNegAndConstant64Test.cpp | 0 .../Fuzzer/test/AbsNegAndConstantTest.cpp | 0 .../Fuzzer/test/AccumulateAllocationsTest.cpp | 0 .../Fuzzer/test/BufferOverflowOnInput.cpp | 0 .../Fuzzer/test/CMakeLists.txt | 0 .../Fuzzer/test/CallerCalleeTest.cpp | 0 .../Fuzzer/test/CounterTest.cpp | 0 .../Fuzzer/test/CustomCrossOverTest.cpp | 0 .../Fuzzer/test/CustomMutatorTest.cpp | 0 .../Fuzzer/test/DSO1.cpp | 0 .../Fuzzer/test/DSO2.cpp | 0 .../Fuzzer/test/DSOTestExtra.cpp | 0 .../Fuzzer/test/DSOTestMain.cpp | 0 .../Fuzzer/test/DivTest.cpp | 0 .../Fuzzer/test/EmptyTest.cpp | 0 .../test/FourIndependentBranchesTest.cpp | 0 .../Fuzzer/test/FullCoverageSetTest.cpp | 0 .../Fuzzer/test/FuzzerUnittest.cpp | 0 .../Fuzzer/test/InitializeTest.cpp | 0 .../Fuzzer/test/LeakTest.cpp | 0 .../Fuzzer/test/LeakTimeoutTest.cpp | 0 .../Fuzzer/test/LoadTest.cpp | 0 .../Fuzzer/test/MemcmpTest.cpp | 0 .../Fuzzer/test/NthRunCrashTest.cpp | 0 .../Fuzzer/test/NullDerefOnEmptyTest.cpp | 0 .../Fuzzer/test/NullDerefTest.cpp | 0 .../Fuzzer/test/OneHugeAllocTest.cpp | 0 .../test/OutOfMemorySingleLargeMallocTest.cpp | 0 .../Fuzzer/test/OutOfMemoryTest.cpp | 0 .../Fuzzer/test/RepeatedBytesTest.cpp | 0 .../Fuzzer/test/RepeatedMemcmp.cpp | 0 .../Fuzzer/test/ShrinkControlFlowTest.cpp | 0 .../Fuzzer/test/ShrinkValueProfileTest.cpp | 0 .../Fuzzer/test/SignedIntOverflowTest.cpp | 0 .../Fuzzer/test/SimpleCmpTest.cpp | 0 .../Fuzzer/test/SimpleDictionaryTest.cpp | 0 .../Fuzzer/test/SimpleHashTest.cpp | 0 .../Fuzzer/test/SimpleTest.cpp | 0 .../Fuzzer/test/SimpleThreadedTest.cpp | 0 .../Fuzzer/test/SingleMemcmpTest.cpp | 0 .../Fuzzer/test/SingleStrcmpTest.cpp | 0 .../Fuzzer/test/SingleStrncmpTest.cpp | 0 .../Fuzzer/test/SpamyTest.cpp | 0 .../Fuzzer/test/StrcmpTest.cpp | 0 .../Fuzzer/test/StrncmpOOBTest.cpp | 0 .../Fuzzer/test/StrncmpTest.cpp | 0 .../Fuzzer/test/StrstrTest.cpp | 0 .../Fuzzer/test/SwapCmpTest.cpp | 0 .../Fuzzer/test/Switch2Test.cpp | 0 .../Fuzzer/test/SwitchTest.cpp | 0 .../Fuzzer/test/ThreadedLeakTest.cpp | 0 .../Fuzzer/test/ThreadedTest.cpp | 0 .../Fuzzer/test/TimeoutEmptyTest.cpp | 0 .../Fuzzer/test/TimeoutTest.cpp | 0 .../Fuzzer/test/TraceMallocTest.cpp | 0 .../Fuzzer/test/UninstrumentedTest.cpp | 0 .../Fuzzer/test/afl-driver-extra-stats.test | 0 .../Fuzzer/test/afl-driver-stderr.test | 0 .../Fuzzer/test/caller-callee.test | 0 .../Fuzzer/test/coverage.test | 0 .../Fuzzer/test/dict1.txt | 0 .../Fuzzer/test/dump_coverage.test | 0 .../Fuzzer/test/fuzzer-customcrossover.test | 0 .../Fuzzer/test/fuzzer-custommutator.test | 0 .../Fuzzer/test/fuzzer-dict.test | 0 .../Fuzzer/test/fuzzer-dirs.test | 0 .../Fuzzer/test/fuzzer-fdmask.test | 0 .../Fuzzer/test/fuzzer-finalstats.test | 0 .../Fuzzer/test/fuzzer-flags.test | 0 .../Fuzzer/test/fuzzer-jobs.test | 0 .../Fuzzer/test/fuzzer-leak.test | 0 .../Fuzzer/test/fuzzer-oom-with-profile.test | 0 .../Fuzzer/test/fuzzer-oom.test | 0 .../Fuzzer/test/fuzzer-printcovpcs.test | 0 .../Fuzzer/test/fuzzer-runs.test | 0 .../Fuzzer/test/fuzzer-seed.test | 0 .../Fuzzer/test/fuzzer-segv.test | 0 .../Fuzzer/test/fuzzer-singleinputs.test | 0 .../Fuzzer/test/fuzzer-threaded.test | 0 .../Fuzzer/test/fuzzer-timeout.test | 0 .../Fuzzer/test/fuzzer-traces-hooks.test | 0 .../Fuzzer/test/fuzzer-ubsan.test | 0 .../Fuzzer/test/fuzzer.test | 0 .../Fuzzer/test/hi.txt | 0 .../Fuzzer/test/lit.cfg | 0 .../Fuzzer/test/lit.site.cfg.in | 0 .../Fuzzer/test/merge.test | 0 .../Fuzzer/test/minimize_crash.test | 0 .../Fuzzer/test/no-coverage/CMakeLists.txt | 0 .../Fuzzer/test/repeated-bytes.test | 0 .../Fuzzer/test/shrink.test | 0 .../Fuzzer/test/simple-cmp.test | 0 .../Fuzzer/test/standalone.test | 0 .../Fuzzer/test/swap-cmp.test | 0 .../Fuzzer/test/trace-malloc.test | 0 .../Fuzzer/test/ubsan/CMakeLists.txt | 0 .../Fuzzer/test/ulimit.test | 0 .../Fuzzer/test/uninstrumented/CMakeLists.txt | 0 .../Fuzzer/test/unit/lit.cfg | 0 .../Fuzzer/test/unit/lit.site.cfg.in | 0 .../Fuzzer/test/value-profile-cmp.test | 0 .../Fuzzer/test/value-profile-cmp2.test | 0 .../Fuzzer/test/value-profile-cmp3.test | 0 .../Fuzzer/test/value-profile-cmp4.test | 0 .../Fuzzer/test/value-profile-div.test | 0 .../Fuzzer/test/value-profile-load.test | 0 .../Fuzzer/test/value-profile-mem.test | 0 .../Fuzzer/test/value-profile-set.test | 0 .../Fuzzer/test/value-profile-strcmp.test | 0 .../Fuzzer/test/value-profile-strncmp.test | 0 .../Fuzzer/test/value-profile-switch.test | 0 test/{src => thirdparty/catch}/catch.hpp | 0 160 files changed, 27 insertions(+), 21 deletions(-) rename test/{fuzz_test/parse_fuzzer.cc => src/fuzzer-parse_json.cpp} (61%) rename test/{fuzz_test => thirdparty}/Fuzzer/CMakeLists.txt (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerCorpus.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerCrossOver.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerDefs.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerDictionary.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerDriver.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerExtFunctions.def (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerExtFunctions.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerExtFunctionsDlsym.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerExtFunctionsWeak.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerFlags.def (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerIO.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerIO.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerIOPosix.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerIOWindows.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerInterface.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerInternal.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerLoop.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerMain.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerMerge.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerMerge.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerMutate.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerMutate.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerOptions.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerRandom.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerSHA1.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerSHA1.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerTracePC.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerTracePC.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerTraceState.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerUtil.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerUtil.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerUtilDarwin.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerUtilLinux.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerUtilPosix.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerUtilWindows.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/FuzzerValueBitMap.h (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/README.txt (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/afl/afl_driver.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/build.sh (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/cxx.dict (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/standalone/StandaloneFuzzTargetMain.c (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/AFLDriverTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/AbsNegAndConstant64Test.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/AbsNegAndConstantTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/AccumulateAllocationsTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/BufferOverflowOnInput.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/CMakeLists.txt (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/CallerCalleeTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/CounterTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/CustomCrossOverTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/CustomMutatorTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/DSO1.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/DSO2.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/DSOTestExtra.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/DSOTestMain.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/DivTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/EmptyTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/FourIndependentBranchesTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/FullCoverageSetTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/FuzzerUnittest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/InitializeTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/LeakTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/LeakTimeoutTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/LoadTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/MemcmpTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/NthRunCrashTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/NullDerefOnEmptyTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/NullDerefTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/OneHugeAllocTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/OutOfMemoryTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/RepeatedBytesTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/RepeatedMemcmp.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/ShrinkControlFlowTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/ShrinkValueProfileTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SignedIntOverflowTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SimpleCmpTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SimpleDictionaryTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SimpleHashTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SimpleTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SimpleThreadedTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SingleMemcmpTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SingleStrcmpTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SingleStrncmpTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SpamyTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/StrcmpTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/StrncmpOOBTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/StrncmpTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/StrstrTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SwapCmpTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/Switch2Test.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/SwitchTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/ThreadedLeakTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/ThreadedTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/TimeoutEmptyTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/TimeoutTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/TraceMallocTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/UninstrumentedTest.cpp (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/afl-driver-extra-stats.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/afl-driver-stderr.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/caller-callee.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/coverage.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/dict1.txt (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/dump_coverage.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-customcrossover.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-custommutator.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-dict.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-dirs.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-fdmask.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-finalstats.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-flags.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-jobs.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-leak.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-oom-with-profile.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-oom.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-printcovpcs.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-runs.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-seed.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-segv.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-singleinputs.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-threaded.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-timeout.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-traces-hooks.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer-ubsan.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/fuzzer.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/hi.txt (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/lit.cfg (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/lit.site.cfg.in (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/merge.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/minimize_crash.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/no-coverage/CMakeLists.txt (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/repeated-bytes.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/shrink.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/simple-cmp.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/standalone.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/swap-cmp.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/trace-malloc.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/ubsan/CMakeLists.txt (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/ulimit.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/uninstrumented/CMakeLists.txt (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/unit/lit.cfg (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/unit/lit.site.cfg.in (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-cmp.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-cmp2.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-cmp3.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-cmp4.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-div.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-load.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-mem.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-set.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-strcmp.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-strncmp.test (100%) rename test/{fuzz_test => thirdparty}/Fuzzer/test/value-profile-switch.test (100%) rename test/{src => thirdparty/catch}/catch.hpp (100%) diff --git a/.gitignore b/.gitignore index 099cad5c..104befbe 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,4 @@ cmake-build-debug test/test-* -test/fuzz_test/Fuzzer/.svn +.svn diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f57ddf71..47785aee 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,7 @@ # The unit test executable. set(JSON_UNITTEST_TARGET_NAME "json_unit") add_executable(${JSON_UNITTEST_TARGET_NAME} - "src/catch.hpp" + "thirdparty/catch/catch.hpp" "src/unit.cpp" "src/unit-algorithms.cpp" "src/unit-allocator.cpp" @@ -44,7 +44,7 @@ set_target_properties(${JSON_UNITTEST_TARGET_NAME} PROPERTIES COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>" ) -target_include_directories(${JSON_UNITTEST_TARGET_NAME} PRIVATE "src") +target_include_directories(${JSON_UNITTEST_TARGET_NAME} PRIVATE "src" "thirdparty/catch") target_link_libraries(${JSON_UNITTEST_TARGET_NAME} ${JSON_TARGET_NAME}) add_test(NAME "${JSON_UNITTEST_TARGET_NAME}_default" diff --git a/test/Makefile b/test/Makefile index 488cec89..c1fb33f4 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,7 +4,7 @@ # additional flags CXXFLAGS += -std=c++11 -Wall -Wextra -pedantic -Weffc++ -Wcast-align -Wcast-qual -Wno-ctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch -Wundef -Wno-unused -Wnon-virtual-dtor -Wreorder -Wdeprecated -Wno-float-equal -CPPFLAGS += -I ../src -I . +CPPFLAGS += -I ../src -I . -I thirdparty/catch SOURCES = src/unit.cpp \ src/unit-algorithms.cpp \ @@ -57,11 +57,11 @@ clean: # single test file ############################################################################## -json_unit: $(OBJECTS) ../src/json.hpp src/catch.hpp +json_unit: $(OBJECTS) ../src/json.hpp thirdparty/catch/catch.hpp @echo "[CXXLD] $@" @$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJECTS) -o $@ -%.o: %.cpp ../src/json.hpp src/catch.hpp +%.o: %.cpp ../src/json.hpp thirdparty/catch/catch.hpp @echo "[CXX] $@" @$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@ @@ -70,7 +70,7 @@ json_unit: $(OBJECTS) ../src/json.hpp src/catch.hpp # individual test cases ############################################################################## -test-%: src/unit-%.cpp ../src/json.hpp src/catch.hpp +test-%: src/unit-%.cpp ../src/json.hpp thirdparty/catch/catch.hpp @echo "[CXXLD] $@" @$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -DCATCH_CONFIG_MAIN $< -o $@ diff --git a/test/fuzz_test/parse_fuzzer.cc b/test/src/fuzzer-parse_json.cpp similarity index 61% rename from test/fuzz_test/parse_fuzzer.cc rename to test/src/fuzzer-parse_json.cpp index bb8b3d37..20a824db 100644 --- a/test/fuzz_test/parse_fuzzer.cc +++ b/test/src/fuzzer-parse_json.cpp @@ -18,19 +18,25 @@ using json = nlohmann::json; -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - try { - std::stringstream s; - s << json::parse(data, data + size); - try { - auto j = json::parse(s.str()); - std::stringstream s2; - s2 << j; - assert(s.str() == s2.str()); - assert(j == json::parse(s.str())); - } catch (const std::invalid_argument&) { - assert(0); +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + try + { + std::stringstream s; + s << json::parse(data, data + size); + try + { + auto j = json::parse(s.str()); + std::stringstream s2; + s2 << j; + assert(s.str() == s2.str()); + assert(j == json::parse(s.str())); + } + catch (const std::invalid_argument&) + { + assert(0); + } } - } catch (const std::invalid_argument&) { } - return 0; + catch (const std::invalid_argument&) { } + return 0; } diff --git a/test/fuzz_test/Fuzzer/CMakeLists.txt b/test/thirdparty/Fuzzer/CMakeLists.txt similarity index 100% rename from test/fuzz_test/Fuzzer/CMakeLists.txt rename to test/thirdparty/Fuzzer/CMakeLists.txt diff --git a/test/fuzz_test/Fuzzer/FuzzerCorpus.h b/test/thirdparty/Fuzzer/FuzzerCorpus.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerCorpus.h rename to test/thirdparty/Fuzzer/FuzzerCorpus.h diff --git a/test/fuzz_test/Fuzzer/FuzzerCrossOver.cpp b/test/thirdparty/Fuzzer/FuzzerCrossOver.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerCrossOver.cpp rename to test/thirdparty/Fuzzer/FuzzerCrossOver.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerDefs.h b/test/thirdparty/Fuzzer/FuzzerDefs.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerDefs.h rename to test/thirdparty/Fuzzer/FuzzerDefs.h diff --git a/test/fuzz_test/Fuzzer/FuzzerDictionary.h b/test/thirdparty/Fuzzer/FuzzerDictionary.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerDictionary.h rename to test/thirdparty/Fuzzer/FuzzerDictionary.h diff --git a/test/fuzz_test/Fuzzer/FuzzerDriver.cpp b/test/thirdparty/Fuzzer/FuzzerDriver.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerDriver.cpp rename to test/thirdparty/Fuzzer/FuzzerDriver.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerExtFunctions.def b/test/thirdparty/Fuzzer/FuzzerExtFunctions.def similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerExtFunctions.def rename to test/thirdparty/Fuzzer/FuzzerExtFunctions.def diff --git a/test/fuzz_test/Fuzzer/FuzzerExtFunctions.h b/test/thirdparty/Fuzzer/FuzzerExtFunctions.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerExtFunctions.h rename to test/thirdparty/Fuzzer/FuzzerExtFunctions.h diff --git a/test/fuzz_test/Fuzzer/FuzzerExtFunctionsDlsym.cpp b/test/thirdparty/Fuzzer/FuzzerExtFunctionsDlsym.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerExtFunctionsDlsym.cpp rename to test/thirdparty/Fuzzer/FuzzerExtFunctionsDlsym.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeak.cpp b/test/thirdparty/Fuzzer/FuzzerExtFunctionsWeak.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeak.cpp rename to test/thirdparty/Fuzzer/FuzzerExtFunctionsWeak.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp b/test/thirdparty/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp rename to test/thirdparty/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerFlags.def b/test/thirdparty/Fuzzer/FuzzerFlags.def similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerFlags.def rename to test/thirdparty/Fuzzer/FuzzerFlags.def diff --git a/test/fuzz_test/Fuzzer/FuzzerIO.cpp b/test/thirdparty/Fuzzer/FuzzerIO.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerIO.cpp rename to test/thirdparty/Fuzzer/FuzzerIO.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerIO.h b/test/thirdparty/Fuzzer/FuzzerIO.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerIO.h rename to test/thirdparty/Fuzzer/FuzzerIO.h diff --git a/test/fuzz_test/Fuzzer/FuzzerIOPosix.cpp b/test/thirdparty/Fuzzer/FuzzerIOPosix.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerIOPosix.cpp rename to test/thirdparty/Fuzzer/FuzzerIOPosix.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerIOWindows.cpp b/test/thirdparty/Fuzzer/FuzzerIOWindows.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerIOWindows.cpp rename to test/thirdparty/Fuzzer/FuzzerIOWindows.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerInterface.h b/test/thirdparty/Fuzzer/FuzzerInterface.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerInterface.h rename to test/thirdparty/Fuzzer/FuzzerInterface.h diff --git a/test/fuzz_test/Fuzzer/FuzzerInternal.h b/test/thirdparty/Fuzzer/FuzzerInternal.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerInternal.h rename to test/thirdparty/Fuzzer/FuzzerInternal.h diff --git a/test/fuzz_test/Fuzzer/FuzzerLoop.cpp b/test/thirdparty/Fuzzer/FuzzerLoop.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerLoop.cpp rename to test/thirdparty/Fuzzer/FuzzerLoop.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerMain.cpp b/test/thirdparty/Fuzzer/FuzzerMain.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerMain.cpp rename to test/thirdparty/Fuzzer/FuzzerMain.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerMerge.cpp b/test/thirdparty/Fuzzer/FuzzerMerge.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerMerge.cpp rename to test/thirdparty/Fuzzer/FuzzerMerge.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerMerge.h b/test/thirdparty/Fuzzer/FuzzerMerge.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerMerge.h rename to test/thirdparty/Fuzzer/FuzzerMerge.h diff --git a/test/fuzz_test/Fuzzer/FuzzerMutate.cpp b/test/thirdparty/Fuzzer/FuzzerMutate.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerMutate.cpp rename to test/thirdparty/Fuzzer/FuzzerMutate.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerMutate.h b/test/thirdparty/Fuzzer/FuzzerMutate.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerMutate.h rename to test/thirdparty/Fuzzer/FuzzerMutate.h diff --git a/test/fuzz_test/Fuzzer/FuzzerOptions.h b/test/thirdparty/Fuzzer/FuzzerOptions.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerOptions.h rename to test/thirdparty/Fuzzer/FuzzerOptions.h diff --git a/test/fuzz_test/Fuzzer/FuzzerRandom.h b/test/thirdparty/Fuzzer/FuzzerRandom.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerRandom.h rename to test/thirdparty/Fuzzer/FuzzerRandom.h diff --git a/test/fuzz_test/Fuzzer/FuzzerSHA1.cpp b/test/thirdparty/Fuzzer/FuzzerSHA1.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerSHA1.cpp rename to test/thirdparty/Fuzzer/FuzzerSHA1.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerSHA1.h b/test/thirdparty/Fuzzer/FuzzerSHA1.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerSHA1.h rename to test/thirdparty/Fuzzer/FuzzerSHA1.h diff --git a/test/fuzz_test/Fuzzer/FuzzerTracePC.cpp b/test/thirdparty/Fuzzer/FuzzerTracePC.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerTracePC.cpp rename to test/thirdparty/Fuzzer/FuzzerTracePC.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerTracePC.h b/test/thirdparty/Fuzzer/FuzzerTracePC.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerTracePC.h rename to test/thirdparty/Fuzzer/FuzzerTracePC.h diff --git a/test/fuzz_test/Fuzzer/FuzzerTraceState.cpp b/test/thirdparty/Fuzzer/FuzzerTraceState.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerTraceState.cpp rename to test/thirdparty/Fuzzer/FuzzerTraceState.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerUtil.cpp b/test/thirdparty/Fuzzer/FuzzerUtil.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerUtil.cpp rename to test/thirdparty/Fuzzer/FuzzerUtil.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerUtil.h b/test/thirdparty/Fuzzer/FuzzerUtil.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerUtil.h rename to test/thirdparty/Fuzzer/FuzzerUtil.h diff --git a/test/fuzz_test/Fuzzer/FuzzerUtilDarwin.cpp b/test/thirdparty/Fuzzer/FuzzerUtilDarwin.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerUtilDarwin.cpp rename to test/thirdparty/Fuzzer/FuzzerUtilDarwin.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerUtilLinux.cpp b/test/thirdparty/Fuzzer/FuzzerUtilLinux.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerUtilLinux.cpp rename to test/thirdparty/Fuzzer/FuzzerUtilLinux.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerUtilPosix.cpp b/test/thirdparty/Fuzzer/FuzzerUtilPosix.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerUtilPosix.cpp rename to test/thirdparty/Fuzzer/FuzzerUtilPosix.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerUtilWindows.cpp b/test/thirdparty/Fuzzer/FuzzerUtilWindows.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerUtilWindows.cpp rename to test/thirdparty/Fuzzer/FuzzerUtilWindows.cpp diff --git a/test/fuzz_test/Fuzzer/FuzzerValueBitMap.h b/test/thirdparty/Fuzzer/FuzzerValueBitMap.h similarity index 100% rename from test/fuzz_test/Fuzzer/FuzzerValueBitMap.h rename to test/thirdparty/Fuzzer/FuzzerValueBitMap.h diff --git a/test/fuzz_test/Fuzzer/README.txt b/test/thirdparty/Fuzzer/README.txt similarity index 100% rename from test/fuzz_test/Fuzzer/README.txt rename to test/thirdparty/Fuzzer/README.txt diff --git a/test/fuzz_test/Fuzzer/afl/afl_driver.cpp b/test/thirdparty/Fuzzer/afl/afl_driver.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/afl/afl_driver.cpp rename to test/thirdparty/Fuzzer/afl/afl_driver.cpp diff --git a/test/fuzz_test/Fuzzer/build.sh b/test/thirdparty/Fuzzer/build.sh similarity index 100% rename from test/fuzz_test/Fuzzer/build.sh rename to test/thirdparty/Fuzzer/build.sh diff --git a/test/fuzz_test/Fuzzer/cxx.dict b/test/thirdparty/Fuzzer/cxx.dict similarity index 100% rename from test/fuzz_test/Fuzzer/cxx.dict rename to test/thirdparty/Fuzzer/cxx.dict diff --git a/test/fuzz_test/Fuzzer/standalone/StandaloneFuzzTargetMain.c b/test/thirdparty/Fuzzer/standalone/StandaloneFuzzTargetMain.c similarity index 100% rename from test/fuzz_test/Fuzzer/standalone/StandaloneFuzzTargetMain.c rename to test/thirdparty/Fuzzer/standalone/StandaloneFuzzTargetMain.c diff --git a/test/fuzz_test/Fuzzer/test/AFLDriverTest.cpp b/test/thirdparty/Fuzzer/test/AFLDriverTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/AFLDriverTest.cpp rename to test/thirdparty/Fuzzer/test/AFLDriverTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/AbsNegAndConstant64Test.cpp b/test/thirdparty/Fuzzer/test/AbsNegAndConstant64Test.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/AbsNegAndConstant64Test.cpp rename to test/thirdparty/Fuzzer/test/AbsNegAndConstant64Test.cpp diff --git a/test/fuzz_test/Fuzzer/test/AbsNegAndConstantTest.cpp b/test/thirdparty/Fuzzer/test/AbsNegAndConstantTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/AbsNegAndConstantTest.cpp rename to test/thirdparty/Fuzzer/test/AbsNegAndConstantTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/AccumulateAllocationsTest.cpp b/test/thirdparty/Fuzzer/test/AccumulateAllocationsTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/AccumulateAllocationsTest.cpp rename to test/thirdparty/Fuzzer/test/AccumulateAllocationsTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/BufferOverflowOnInput.cpp b/test/thirdparty/Fuzzer/test/BufferOverflowOnInput.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/BufferOverflowOnInput.cpp rename to test/thirdparty/Fuzzer/test/BufferOverflowOnInput.cpp diff --git a/test/fuzz_test/Fuzzer/test/CMakeLists.txt b/test/thirdparty/Fuzzer/test/CMakeLists.txt similarity index 100% rename from test/fuzz_test/Fuzzer/test/CMakeLists.txt rename to test/thirdparty/Fuzzer/test/CMakeLists.txt diff --git a/test/fuzz_test/Fuzzer/test/CallerCalleeTest.cpp b/test/thirdparty/Fuzzer/test/CallerCalleeTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/CallerCalleeTest.cpp rename to test/thirdparty/Fuzzer/test/CallerCalleeTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/CounterTest.cpp b/test/thirdparty/Fuzzer/test/CounterTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/CounterTest.cpp rename to test/thirdparty/Fuzzer/test/CounterTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/CustomCrossOverTest.cpp b/test/thirdparty/Fuzzer/test/CustomCrossOverTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/CustomCrossOverTest.cpp rename to test/thirdparty/Fuzzer/test/CustomCrossOverTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/CustomMutatorTest.cpp b/test/thirdparty/Fuzzer/test/CustomMutatorTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/CustomMutatorTest.cpp rename to test/thirdparty/Fuzzer/test/CustomMutatorTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/DSO1.cpp b/test/thirdparty/Fuzzer/test/DSO1.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/DSO1.cpp rename to test/thirdparty/Fuzzer/test/DSO1.cpp diff --git a/test/fuzz_test/Fuzzer/test/DSO2.cpp b/test/thirdparty/Fuzzer/test/DSO2.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/DSO2.cpp rename to test/thirdparty/Fuzzer/test/DSO2.cpp diff --git a/test/fuzz_test/Fuzzer/test/DSOTestExtra.cpp b/test/thirdparty/Fuzzer/test/DSOTestExtra.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/DSOTestExtra.cpp rename to test/thirdparty/Fuzzer/test/DSOTestExtra.cpp diff --git a/test/fuzz_test/Fuzzer/test/DSOTestMain.cpp b/test/thirdparty/Fuzzer/test/DSOTestMain.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/DSOTestMain.cpp rename to test/thirdparty/Fuzzer/test/DSOTestMain.cpp diff --git a/test/fuzz_test/Fuzzer/test/DivTest.cpp b/test/thirdparty/Fuzzer/test/DivTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/DivTest.cpp rename to test/thirdparty/Fuzzer/test/DivTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/EmptyTest.cpp b/test/thirdparty/Fuzzer/test/EmptyTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/EmptyTest.cpp rename to test/thirdparty/Fuzzer/test/EmptyTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/FourIndependentBranchesTest.cpp b/test/thirdparty/Fuzzer/test/FourIndependentBranchesTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/FourIndependentBranchesTest.cpp rename to test/thirdparty/Fuzzer/test/FourIndependentBranchesTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/FullCoverageSetTest.cpp b/test/thirdparty/Fuzzer/test/FullCoverageSetTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/FullCoverageSetTest.cpp rename to test/thirdparty/Fuzzer/test/FullCoverageSetTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/FuzzerUnittest.cpp b/test/thirdparty/Fuzzer/test/FuzzerUnittest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/FuzzerUnittest.cpp rename to test/thirdparty/Fuzzer/test/FuzzerUnittest.cpp diff --git a/test/fuzz_test/Fuzzer/test/InitializeTest.cpp b/test/thirdparty/Fuzzer/test/InitializeTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/InitializeTest.cpp rename to test/thirdparty/Fuzzer/test/InitializeTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/LeakTest.cpp b/test/thirdparty/Fuzzer/test/LeakTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/LeakTest.cpp rename to test/thirdparty/Fuzzer/test/LeakTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/LeakTimeoutTest.cpp b/test/thirdparty/Fuzzer/test/LeakTimeoutTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/LeakTimeoutTest.cpp rename to test/thirdparty/Fuzzer/test/LeakTimeoutTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/LoadTest.cpp b/test/thirdparty/Fuzzer/test/LoadTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/LoadTest.cpp rename to test/thirdparty/Fuzzer/test/LoadTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/MemcmpTest.cpp b/test/thirdparty/Fuzzer/test/MemcmpTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/MemcmpTest.cpp rename to test/thirdparty/Fuzzer/test/MemcmpTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/NthRunCrashTest.cpp b/test/thirdparty/Fuzzer/test/NthRunCrashTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/NthRunCrashTest.cpp rename to test/thirdparty/Fuzzer/test/NthRunCrashTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/NullDerefOnEmptyTest.cpp b/test/thirdparty/Fuzzer/test/NullDerefOnEmptyTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/NullDerefOnEmptyTest.cpp rename to test/thirdparty/Fuzzer/test/NullDerefOnEmptyTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/NullDerefTest.cpp b/test/thirdparty/Fuzzer/test/NullDerefTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/NullDerefTest.cpp rename to test/thirdparty/Fuzzer/test/NullDerefTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/OneHugeAllocTest.cpp b/test/thirdparty/Fuzzer/test/OneHugeAllocTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/OneHugeAllocTest.cpp rename to test/thirdparty/Fuzzer/test/OneHugeAllocTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp b/test/thirdparty/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp rename to test/thirdparty/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/OutOfMemoryTest.cpp b/test/thirdparty/Fuzzer/test/OutOfMemoryTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/OutOfMemoryTest.cpp rename to test/thirdparty/Fuzzer/test/OutOfMemoryTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/RepeatedBytesTest.cpp b/test/thirdparty/Fuzzer/test/RepeatedBytesTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/RepeatedBytesTest.cpp rename to test/thirdparty/Fuzzer/test/RepeatedBytesTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/RepeatedMemcmp.cpp b/test/thirdparty/Fuzzer/test/RepeatedMemcmp.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/RepeatedMemcmp.cpp rename to test/thirdparty/Fuzzer/test/RepeatedMemcmp.cpp diff --git a/test/fuzz_test/Fuzzer/test/ShrinkControlFlowTest.cpp b/test/thirdparty/Fuzzer/test/ShrinkControlFlowTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/ShrinkControlFlowTest.cpp rename to test/thirdparty/Fuzzer/test/ShrinkControlFlowTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/ShrinkValueProfileTest.cpp b/test/thirdparty/Fuzzer/test/ShrinkValueProfileTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/ShrinkValueProfileTest.cpp rename to test/thirdparty/Fuzzer/test/ShrinkValueProfileTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SignedIntOverflowTest.cpp b/test/thirdparty/Fuzzer/test/SignedIntOverflowTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SignedIntOverflowTest.cpp rename to test/thirdparty/Fuzzer/test/SignedIntOverflowTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SimpleCmpTest.cpp b/test/thirdparty/Fuzzer/test/SimpleCmpTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SimpleCmpTest.cpp rename to test/thirdparty/Fuzzer/test/SimpleCmpTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SimpleDictionaryTest.cpp b/test/thirdparty/Fuzzer/test/SimpleDictionaryTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SimpleDictionaryTest.cpp rename to test/thirdparty/Fuzzer/test/SimpleDictionaryTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SimpleHashTest.cpp b/test/thirdparty/Fuzzer/test/SimpleHashTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SimpleHashTest.cpp rename to test/thirdparty/Fuzzer/test/SimpleHashTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SimpleTest.cpp b/test/thirdparty/Fuzzer/test/SimpleTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SimpleTest.cpp rename to test/thirdparty/Fuzzer/test/SimpleTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SimpleThreadedTest.cpp b/test/thirdparty/Fuzzer/test/SimpleThreadedTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SimpleThreadedTest.cpp rename to test/thirdparty/Fuzzer/test/SimpleThreadedTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SingleMemcmpTest.cpp b/test/thirdparty/Fuzzer/test/SingleMemcmpTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SingleMemcmpTest.cpp rename to test/thirdparty/Fuzzer/test/SingleMemcmpTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SingleStrcmpTest.cpp b/test/thirdparty/Fuzzer/test/SingleStrcmpTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SingleStrcmpTest.cpp rename to test/thirdparty/Fuzzer/test/SingleStrcmpTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SingleStrncmpTest.cpp b/test/thirdparty/Fuzzer/test/SingleStrncmpTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SingleStrncmpTest.cpp rename to test/thirdparty/Fuzzer/test/SingleStrncmpTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SpamyTest.cpp b/test/thirdparty/Fuzzer/test/SpamyTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SpamyTest.cpp rename to test/thirdparty/Fuzzer/test/SpamyTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/StrcmpTest.cpp b/test/thirdparty/Fuzzer/test/StrcmpTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/StrcmpTest.cpp rename to test/thirdparty/Fuzzer/test/StrcmpTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/StrncmpOOBTest.cpp b/test/thirdparty/Fuzzer/test/StrncmpOOBTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/StrncmpOOBTest.cpp rename to test/thirdparty/Fuzzer/test/StrncmpOOBTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/StrncmpTest.cpp b/test/thirdparty/Fuzzer/test/StrncmpTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/StrncmpTest.cpp rename to test/thirdparty/Fuzzer/test/StrncmpTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/StrstrTest.cpp b/test/thirdparty/Fuzzer/test/StrstrTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/StrstrTest.cpp rename to test/thirdparty/Fuzzer/test/StrstrTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/SwapCmpTest.cpp b/test/thirdparty/Fuzzer/test/SwapCmpTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SwapCmpTest.cpp rename to test/thirdparty/Fuzzer/test/SwapCmpTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/Switch2Test.cpp b/test/thirdparty/Fuzzer/test/Switch2Test.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/Switch2Test.cpp rename to test/thirdparty/Fuzzer/test/Switch2Test.cpp diff --git a/test/fuzz_test/Fuzzer/test/SwitchTest.cpp b/test/thirdparty/Fuzzer/test/SwitchTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/SwitchTest.cpp rename to test/thirdparty/Fuzzer/test/SwitchTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/ThreadedLeakTest.cpp b/test/thirdparty/Fuzzer/test/ThreadedLeakTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/ThreadedLeakTest.cpp rename to test/thirdparty/Fuzzer/test/ThreadedLeakTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/ThreadedTest.cpp b/test/thirdparty/Fuzzer/test/ThreadedTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/ThreadedTest.cpp rename to test/thirdparty/Fuzzer/test/ThreadedTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/TimeoutEmptyTest.cpp b/test/thirdparty/Fuzzer/test/TimeoutEmptyTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/TimeoutEmptyTest.cpp rename to test/thirdparty/Fuzzer/test/TimeoutEmptyTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/TimeoutTest.cpp b/test/thirdparty/Fuzzer/test/TimeoutTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/TimeoutTest.cpp rename to test/thirdparty/Fuzzer/test/TimeoutTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/TraceMallocTest.cpp b/test/thirdparty/Fuzzer/test/TraceMallocTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/TraceMallocTest.cpp rename to test/thirdparty/Fuzzer/test/TraceMallocTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/UninstrumentedTest.cpp b/test/thirdparty/Fuzzer/test/UninstrumentedTest.cpp similarity index 100% rename from test/fuzz_test/Fuzzer/test/UninstrumentedTest.cpp rename to test/thirdparty/Fuzzer/test/UninstrumentedTest.cpp diff --git a/test/fuzz_test/Fuzzer/test/afl-driver-extra-stats.test b/test/thirdparty/Fuzzer/test/afl-driver-extra-stats.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/afl-driver-extra-stats.test rename to test/thirdparty/Fuzzer/test/afl-driver-extra-stats.test diff --git a/test/fuzz_test/Fuzzer/test/afl-driver-stderr.test b/test/thirdparty/Fuzzer/test/afl-driver-stderr.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/afl-driver-stderr.test rename to test/thirdparty/Fuzzer/test/afl-driver-stderr.test diff --git a/test/fuzz_test/Fuzzer/test/caller-callee.test b/test/thirdparty/Fuzzer/test/caller-callee.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/caller-callee.test rename to test/thirdparty/Fuzzer/test/caller-callee.test diff --git a/test/fuzz_test/Fuzzer/test/coverage.test b/test/thirdparty/Fuzzer/test/coverage.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/coverage.test rename to test/thirdparty/Fuzzer/test/coverage.test diff --git a/test/fuzz_test/Fuzzer/test/dict1.txt b/test/thirdparty/Fuzzer/test/dict1.txt similarity index 100% rename from test/fuzz_test/Fuzzer/test/dict1.txt rename to test/thirdparty/Fuzzer/test/dict1.txt diff --git a/test/fuzz_test/Fuzzer/test/dump_coverage.test b/test/thirdparty/Fuzzer/test/dump_coverage.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/dump_coverage.test rename to test/thirdparty/Fuzzer/test/dump_coverage.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-customcrossover.test b/test/thirdparty/Fuzzer/test/fuzzer-customcrossover.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-customcrossover.test rename to test/thirdparty/Fuzzer/test/fuzzer-customcrossover.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-custommutator.test b/test/thirdparty/Fuzzer/test/fuzzer-custommutator.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-custommutator.test rename to test/thirdparty/Fuzzer/test/fuzzer-custommutator.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-dict.test b/test/thirdparty/Fuzzer/test/fuzzer-dict.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-dict.test rename to test/thirdparty/Fuzzer/test/fuzzer-dict.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-dirs.test b/test/thirdparty/Fuzzer/test/fuzzer-dirs.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-dirs.test rename to test/thirdparty/Fuzzer/test/fuzzer-dirs.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-fdmask.test b/test/thirdparty/Fuzzer/test/fuzzer-fdmask.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-fdmask.test rename to test/thirdparty/Fuzzer/test/fuzzer-fdmask.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-finalstats.test b/test/thirdparty/Fuzzer/test/fuzzer-finalstats.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-finalstats.test rename to test/thirdparty/Fuzzer/test/fuzzer-finalstats.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-flags.test b/test/thirdparty/Fuzzer/test/fuzzer-flags.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-flags.test rename to test/thirdparty/Fuzzer/test/fuzzer-flags.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-jobs.test b/test/thirdparty/Fuzzer/test/fuzzer-jobs.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-jobs.test rename to test/thirdparty/Fuzzer/test/fuzzer-jobs.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-leak.test b/test/thirdparty/Fuzzer/test/fuzzer-leak.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-leak.test rename to test/thirdparty/Fuzzer/test/fuzzer-leak.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-oom-with-profile.test b/test/thirdparty/Fuzzer/test/fuzzer-oom-with-profile.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-oom-with-profile.test rename to test/thirdparty/Fuzzer/test/fuzzer-oom-with-profile.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-oom.test b/test/thirdparty/Fuzzer/test/fuzzer-oom.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-oom.test rename to test/thirdparty/Fuzzer/test/fuzzer-oom.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-printcovpcs.test b/test/thirdparty/Fuzzer/test/fuzzer-printcovpcs.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-printcovpcs.test rename to test/thirdparty/Fuzzer/test/fuzzer-printcovpcs.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-runs.test b/test/thirdparty/Fuzzer/test/fuzzer-runs.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-runs.test rename to test/thirdparty/Fuzzer/test/fuzzer-runs.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-seed.test b/test/thirdparty/Fuzzer/test/fuzzer-seed.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-seed.test rename to test/thirdparty/Fuzzer/test/fuzzer-seed.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-segv.test b/test/thirdparty/Fuzzer/test/fuzzer-segv.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-segv.test rename to test/thirdparty/Fuzzer/test/fuzzer-segv.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-singleinputs.test b/test/thirdparty/Fuzzer/test/fuzzer-singleinputs.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-singleinputs.test rename to test/thirdparty/Fuzzer/test/fuzzer-singleinputs.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-threaded.test b/test/thirdparty/Fuzzer/test/fuzzer-threaded.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-threaded.test rename to test/thirdparty/Fuzzer/test/fuzzer-threaded.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-timeout.test b/test/thirdparty/Fuzzer/test/fuzzer-timeout.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-timeout.test rename to test/thirdparty/Fuzzer/test/fuzzer-timeout.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-traces-hooks.test b/test/thirdparty/Fuzzer/test/fuzzer-traces-hooks.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-traces-hooks.test rename to test/thirdparty/Fuzzer/test/fuzzer-traces-hooks.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer-ubsan.test b/test/thirdparty/Fuzzer/test/fuzzer-ubsan.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer-ubsan.test rename to test/thirdparty/Fuzzer/test/fuzzer-ubsan.test diff --git a/test/fuzz_test/Fuzzer/test/fuzzer.test b/test/thirdparty/Fuzzer/test/fuzzer.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/fuzzer.test rename to test/thirdparty/Fuzzer/test/fuzzer.test diff --git a/test/fuzz_test/Fuzzer/test/hi.txt b/test/thirdparty/Fuzzer/test/hi.txt similarity index 100% rename from test/fuzz_test/Fuzzer/test/hi.txt rename to test/thirdparty/Fuzzer/test/hi.txt diff --git a/test/fuzz_test/Fuzzer/test/lit.cfg b/test/thirdparty/Fuzzer/test/lit.cfg similarity index 100% rename from test/fuzz_test/Fuzzer/test/lit.cfg rename to test/thirdparty/Fuzzer/test/lit.cfg diff --git a/test/fuzz_test/Fuzzer/test/lit.site.cfg.in b/test/thirdparty/Fuzzer/test/lit.site.cfg.in similarity index 100% rename from test/fuzz_test/Fuzzer/test/lit.site.cfg.in rename to test/thirdparty/Fuzzer/test/lit.site.cfg.in diff --git a/test/fuzz_test/Fuzzer/test/merge.test b/test/thirdparty/Fuzzer/test/merge.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/merge.test rename to test/thirdparty/Fuzzer/test/merge.test diff --git a/test/fuzz_test/Fuzzer/test/minimize_crash.test b/test/thirdparty/Fuzzer/test/minimize_crash.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/minimize_crash.test rename to test/thirdparty/Fuzzer/test/minimize_crash.test diff --git a/test/fuzz_test/Fuzzer/test/no-coverage/CMakeLists.txt b/test/thirdparty/Fuzzer/test/no-coverage/CMakeLists.txt similarity index 100% rename from test/fuzz_test/Fuzzer/test/no-coverage/CMakeLists.txt rename to test/thirdparty/Fuzzer/test/no-coverage/CMakeLists.txt diff --git a/test/fuzz_test/Fuzzer/test/repeated-bytes.test b/test/thirdparty/Fuzzer/test/repeated-bytes.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/repeated-bytes.test rename to test/thirdparty/Fuzzer/test/repeated-bytes.test diff --git a/test/fuzz_test/Fuzzer/test/shrink.test b/test/thirdparty/Fuzzer/test/shrink.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/shrink.test rename to test/thirdparty/Fuzzer/test/shrink.test diff --git a/test/fuzz_test/Fuzzer/test/simple-cmp.test b/test/thirdparty/Fuzzer/test/simple-cmp.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/simple-cmp.test rename to test/thirdparty/Fuzzer/test/simple-cmp.test diff --git a/test/fuzz_test/Fuzzer/test/standalone.test b/test/thirdparty/Fuzzer/test/standalone.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/standalone.test rename to test/thirdparty/Fuzzer/test/standalone.test diff --git a/test/fuzz_test/Fuzzer/test/swap-cmp.test b/test/thirdparty/Fuzzer/test/swap-cmp.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/swap-cmp.test rename to test/thirdparty/Fuzzer/test/swap-cmp.test diff --git a/test/fuzz_test/Fuzzer/test/trace-malloc.test b/test/thirdparty/Fuzzer/test/trace-malloc.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/trace-malloc.test rename to test/thirdparty/Fuzzer/test/trace-malloc.test diff --git a/test/fuzz_test/Fuzzer/test/ubsan/CMakeLists.txt b/test/thirdparty/Fuzzer/test/ubsan/CMakeLists.txt similarity index 100% rename from test/fuzz_test/Fuzzer/test/ubsan/CMakeLists.txt rename to test/thirdparty/Fuzzer/test/ubsan/CMakeLists.txt diff --git a/test/fuzz_test/Fuzzer/test/ulimit.test b/test/thirdparty/Fuzzer/test/ulimit.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/ulimit.test rename to test/thirdparty/Fuzzer/test/ulimit.test diff --git a/test/fuzz_test/Fuzzer/test/uninstrumented/CMakeLists.txt b/test/thirdparty/Fuzzer/test/uninstrumented/CMakeLists.txt similarity index 100% rename from test/fuzz_test/Fuzzer/test/uninstrumented/CMakeLists.txt rename to test/thirdparty/Fuzzer/test/uninstrumented/CMakeLists.txt diff --git a/test/fuzz_test/Fuzzer/test/unit/lit.cfg b/test/thirdparty/Fuzzer/test/unit/lit.cfg similarity index 100% rename from test/fuzz_test/Fuzzer/test/unit/lit.cfg rename to test/thirdparty/Fuzzer/test/unit/lit.cfg diff --git a/test/fuzz_test/Fuzzer/test/unit/lit.site.cfg.in b/test/thirdparty/Fuzzer/test/unit/lit.site.cfg.in similarity index 100% rename from test/fuzz_test/Fuzzer/test/unit/lit.site.cfg.in rename to test/thirdparty/Fuzzer/test/unit/lit.site.cfg.in diff --git a/test/fuzz_test/Fuzzer/test/value-profile-cmp.test b/test/thirdparty/Fuzzer/test/value-profile-cmp.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-cmp.test rename to test/thirdparty/Fuzzer/test/value-profile-cmp.test diff --git a/test/fuzz_test/Fuzzer/test/value-profile-cmp2.test b/test/thirdparty/Fuzzer/test/value-profile-cmp2.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-cmp2.test rename to test/thirdparty/Fuzzer/test/value-profile-cmp2.test diff --git a/test/fuzz_test/Fuzzer/test/value-profile-cmp3.test b/test/thirdparty/Fuzzer/test/value-profile-cmp3.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-cmp3.test rename to test/thirdparty/Fuzzer/test/value-profile-cmp3.test diff --git a/test/fuzz_test/Fuzzer/test/value-profile-cmp4.test b/test/thirdparty/Fuzzer/test/value-profile-cmp4.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-cmp4.test rename to test/thirdparty/Fuzzer/test/value-profile-cmp4.test diff --git a/test/fuzz_test/Fuzzer/test/value-profile-div.test b/test/thirdparty/Fuzzer/test/value-profile-div.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-div.test rename to test/thirdparty/Fuzzer/test/value-profile-div.test diff --git a/test/fuzz_test/Fuzzer/test/value-profile-load.test b/test/thirdparty/Fuzzer/test/value-profile-load.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-load.test rename to test/thirdparty/Fuzzer/test/value-profile-load.test diff --git a/test/fuzz_test/Fuzzer/test/value-profile-mem.test b/test/thirdparty/Fuzzer/test/value-profile-mem.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-mem.test rename to test/thirdparty/Fuzzer/test/value-profile-mem.test diff --git a/test/fuzz_test/Fuzzer/test/value-profile-set.test b/test/thirdparty/Fuzzer/test/value-profile-set.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-set.test rename to test/thirdparty/Fuzzer/test/value-profile-set.test diff --git a/test/fuzz_test/Fuzzer/test/value-profile-strcmp.test b/test/thirdparty/Fuzzer/test/value-profile-strcmp.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-strcmp.test rename to test/thirdparty/Fuzzer/test/value-profile-strcmp.test diff --git a/test/fuzz_test/Fuzzer/test/value-profile-strncmp.test b/test/thirdparty/Fuzzer/test/value-profile-strncmp.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-strncmp.test rename to test/thirdparty/Fuzzer/test/value-profile-strncmp.test diff --git a/test/fuzz_test/Fuzzer/test/value-profile-switch.test b/test/thirdparty/Fuzzer/test/value-profile-switch.test similarity index 100% rename from test/fuzz_test/Fuzzer/test/value-profile-switch.test rename to test/thirdparty/Fuzzer/test/value-profile-switch.test diff --git a/test/src/catch.hpp b/test/thirdparty/catch/catch.hpp similarity index 100% rename from test/src/catch.hpp rename to test/thirdparty/catch/catch.hpp From 22a6b956e89d3468b28a46b11ad242ebee0c4954 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 22 Dec 2016 09:36:34 +0100 Subject: [PATCH 35/71] :page_facing_up: added license for Catch --- test/thirdparty/catch/LICENSE_1_0.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100755 test/thirdparty/catch/LICENSE_1_0.txt diff --git a/test/thirdparty/catch/LICENSE_1_0.txt b/test/thirdparty/catch/LICENSE_1_0.txt new file mode 100755 index 00000000..36b7cd93 --- /dev/null +++ b/test/thirdparty/catch/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. From 048330b14b019d93e4f05437915fdd01d9861c81 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 22 Dec 2016 09:37:15 +0100 Subject: [PATCH 36/71] :arrow_up: Catch v1.5.9 --- test/thirdparty/catch/catch.hpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) mode change 100644 => 100755 test/thirdparty/catch/catch.hpp diff --git a/test/thirdparty/catch/catch.hpp b/test/thirdparty/catch/catch.hpp old mode 100644 new mode 100755 index 2e6fe8d3..3d18eadb --- a/test/thirdparty/catch/catch.hpp +++ b/test/thirdparty/catch/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.5.8 - * Generated: 2016-10-26 12:07:30.938259 + * Catch v1.5.9 + * Generated: 2016-11-29 12:14:38.049276 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -3428,6 +3428,7 @@ namespace Catch { #include <streambuf> #include <ostream> #include <fstream> +#include <memory> namespace Catch { @@ -3995,9 +3996,12 @@ namespace Clara { inline void convertInto( std::string const& _source, std::string& _dest ) { _dest = _source; } + char toLowerCh(char c) { + return static_cast<char>( ::tolower( c ) ); + } inline void convertInto( std::string const& _source, bool& _dest ) { std::string sourceLC = _source; - std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh ); if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) _dest = true; else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) @@ -7578,7 +7582,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 5, 8, "", 0 ); + Version libraryVersion( 1, 5, 9, "", 0 ); } @@ -9166,6 +9170,7 @@ namespace Catch { public: XmlReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), + m_xml(_config.stream()), m_sectionDepth( 0 ) { m_reporterPrefs.shouldRedirectStdOut = true; @@ -9185,7 +9190,6 @@ namespace Catch { virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testRunStarting( testInfo ); - m_xml.setStream( stream ); m_xml.startElement( "Catch" ); if( !m_config->name().empty() ) m_xml.writeAttribute( "name", m_config->name() ); From a084e90f392b6cbc4facb2bc993d21a88fe25ec9 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 22 Dec 2016 11:09:26 +0100 Subject: [PATCH 37/71] :hammer: split AFL test in driver and test file --- .gitignore | 2 + Makefile | 10 ++--- test/Makefile | 8 ++++ test/src/fuzz.cpp | 34 ----------------- test/src/fuzzer-driver_afl.cpp | 33 +++++++++++++++++ test/src/fuzzer-parse_json.cpp | 67 +++++++++++++++++++++++----------- 6 files changed, 91 insertions(+), 63 deletions(-) delete mode 100644 test/src/fuzz.cpp create mode 100644 test/src/fuzzer-driver_afl.cpp diff --git a/.gitignore b/.gitignore index 104befbe..eedc9641 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ cmake-build-debug test/test-* .svn + +test/thirdparty/Fuzzer/libFuzzer.a diff --git a/Makefile b/Makefile index fcce453e..8278dbf2 100644 --- a/Makefile +++ b/Makefile @@ -49,14 +49,10 @@ doctest: fuzz_testing: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) fuzz CXX=afl-clang++ - mv fuzz fuzz-testing + $(MAKE) parse_afl_fuzzer -C test CXX=afl-clang++ + mv test/fuzzer parse_afl_fuzzer find test/data/json_tests -size -5k -name *json | xargs -I{} cp "{}" fuzz-testing/testcases - @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzz" - -# the fuzzer binary -fuzz: test/src/fuzz.cpp src/json.hpp - $(CXX) -std=c++11 $(CXXFLAGS) $(FLAGS) $(CPPFLAGS) -I src $< $(LDFLAGS) -o $@ + @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" ########################################################################## diff --git a/test/Makefile b/test/Makefile index c1fb33f4..da679998 100644 --- a/test/Makefile +++ b/test/Makefile @@ -78,3 +78,11 @@ TEST_PATTERN = "*" TEST_PREFIX = "" check: $(TESTCASES) @cd .. ; for testcase in $(TESTCASES); do echo "Executing $$testcase..."; $(TEST_PREFIX)test/$$testcase $(TEST_PATTERN) || exit 1; done + + +############################################################################## +# fuzzer +############################################################################## + +parse_afl_fuzzer: + $(CXX) $(CXXFLAGS) $(CPPFLAGS) src/fuzzer-driver_afl.cpp src/fuzzer-parse_json.cpp -o $@ diff --git a/test/src/fuzz.cpp b/test/src/fuzz.cpp deleted file mode 100644 index ef403ea8..00000000 --- a/test/src/fuzz.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.0.9 -|_____|_____|_____|_|___| https://github.com/nlohmann/json - -Run "make fuzz_testing" and follow the instructions. - -Licensed under the MIT License <http://opensource.org/licenses/MIT>. -*/ - -#include <json.hpp> - -using json = nlohmann::json; - -int main() -{ -#ifdef __AFL_HAVE_MANUAL_CONTROL - while (__AFL_LOOP(1000)) - { -#endif - try - { - json j(std::cin); - std::cout << j << std::endl; - } - catch (std::invalid_argument& e) - { - std::cout << "Invalid argument in parsing" << e.what() << '\n'; - } -#ifdef __AFL_HAVE_MANUAL_CONTROL - } -#endif -} diff --git a/test/src/fuzzer-driver_afl.cpp b/test/src/fuzzer-driver_afl.cpp new file mode 100644 index 00000000..e386033a --- /dev/null +++ b/test/src/fuzzer-driver_afl.cpp @@ -0,0 +1,33 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ (fuzz test support) +| | |__ | | | | | | version 2.0.9 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on +an implementation of the `LLVMFuzzerTestOneInput` function which processes a +passed byte array. + +Licensed under the MIT License <http://opensource.org/licenses/MIT>. +*/ + +#include <sstream> +#include <cstdint> +#include <iostream> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); + +int main() +{ +#ifdef __AFL_HAVE_MANUAL_CONTROL + while (__AFL_LOOP(1000)) + { +#endif + // copy stdin to stringstream to pass it to fuzzer as byte array + std::stringstream ss; + ss << std::cin.rdbuf(); + LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t*>(ss.str().c_str()), ss.str().size()); +#ifdef __AFL_HAVE_MANUAL_CONTROL + } +#endif +} diff --git a/test/src/fuzzer-parse_json.cpp b/test/src/fuzzer-parse_json.cpp index 20a824db..51ac440d 100644 --- a/test/src/fuzzer-parse_json.cpp +++ b/test/src/fuzzer-parse_json.cpp @@ -1,16 +1,23 @@ -// Copyright 2016 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ (fuzz test support) +| | |__ | | | | | | version 2.0.9 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +This file implements a parser test suitable for fuzz testing. Given a byte +array data, it performs the following steps: + +- j1 = parse(data) +- s1 = serialize(j1) +- j2 = parse(s1) +- s2 = serialize(j2) +- assert(s1 == s2) + +The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer +drivers. + +Licensed under the MIT License <http://opensource.org/licenses/MIT>. +*/ #include <iostream> #include <sstream> @@ -18,25 +25,41 @@ using json = nlohmann::json; +// see http://llvm.org/docs/LibFuzzer.html extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { try { - std::stringstream s; - s << json::parse(data, data + size); + // step 1: parse input + json j1 = json::parse(data, data + size); + try { - auto j = json::parse(s.str()); - std::stringstream s2; - s2 << j; - assert(s.str() == s2.str()); - assert(j == json::parse(s.str())); + // step 2: round trip + + // first serialization + std::string s1 = j1.dump(); + + // parse serialization + json j2 = json::parse(s1); + + // second serialization + std::string s2 = j2.dump(); + + // serializations must match + assert(s1 == s2); } catch (const std::invalid_argument&) { - assert(0); + // parsing a JSON serialization must not fail + assert(false); } } - catch (const std::invalid_argument&) { } + catch (const std::invalid_argument&) + { + // parse errors are ok, because input may be random bytes + } + + // return 0 - non-zero return values are reserved for future use return 0; } From 33be4e7f1f19fea00279aa1733a3c72f475b1a12 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 22 Dec 2016 12:08:36 +0100 Subject: [PATCH 38/71] :construction: cleanup --- Makefile | 10 ++++- test/Makefile | 3 ++ test/src/fuzzer-parse_cbor.cpp | 68 ++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 test/src/fuzzer-parse_cbor.cpp diff --git a/Makefile b/Makefile index 8278dbf2..3e873cbc 100644 --- a/Makefile +++ b/Makefile @@ -50,10 +50,18 @@ fuzz_testing: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out $(MAKE) parse_afl_fuzzer -C test CXX=afl-clang++ - mv test/fuzzer parse_afl_fuzzer + mv test/parse_afl_fuzzer fuzz-testing/fuzzer find test/data/json_tests -size -5k -name *json | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" +fuzz_testing_cbor: + rm -fr fuzz-testing + mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out + $(MAKE) parse_cbor_fuzzer -C test CXX=afl-clang++ + mv test/parse_cbor_fuzzer fuzz-testing/fuzzer + find test/data -size -5k -name *cbor | xargs -I{} cp "{}" fuzz-testing/testcases + @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" + ########################################################################## # static analyzer diff --git a/test/Makefile b/test/Makefile index da679998..a063221a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -86,3 +86,6 @@ check: $(TESTCASES) parse_afl_fuzzer: $(CXX) $(CXXFLAGS) $(CPPFLAGS) src/fuzzer-driver_afl.cpp src/fuzzer-parse_json.cpp -o $@ + +parse_cbor_fuzzer: + $(CXX) $(CXXFLAGS) $(CPPFLAGS) src/fuzzer-driver_afl.cpp src/fuzzer-parse_cbor.cpp -o $@ diff --git a/test/src/fuzzer-parse_cbor.cpp b/test/src/fuzzer-parse_cbor.cpp new file mode 100644 index 00000000..42ce679c --- /dev/null +++ b/test/src/fuzzer-parse_cbor.cpp @@ -0,0 +1,68 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ (fuzz test support) +| | |__ | | | | | | version 2.0.9 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +This file implements a parser test suitable for fuzz testing. Given a byte +array data, it performs the following steps: + +- j1 = from_cbor(data) +- vec = to_cbor(j1) +- j2 = from_cbor(vec) +- assert(j1 == j2) + +The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer +drivers. + +Licensed under the MIT License <http://opensource.org/licenses/MIT>. +*/ + +#include <iostream> +#include <sstream> +#include <json.hpp> + +using json = nlohmann::json; + +// see http://llvm.org/docs/LibFuzzer.html +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + try + { + // step 1: parse input + std::vector<uint8_t> vec1(data, data + size); + json j1 = json::from_cbor(vec1); + + try + { + // step 2: round trip + std::vector<uint8_t> vec2 = json::to_cbor(j1); + + // parse serialization + json j2 = json::from_cbor(vec2); + + // deserializations must match + assert(j1 == j2); + } + catch (const std::invalid_argument&) + { + // parsing a CBOR serialization must not fail + assert(false); + } + } + catch (const std::invalid_argument&) + { + // parse errors are ok, because input may be random bytes + } + catch (const std::out_of_range&) + { + // parse errors are ok, because input may be random bytes + } + catch (const std::domain_error&) + { + // parse errors are ok, because input may be random bytes + } + + // return 0 - non-zero return values are reserved for future use + return 0; +} From f87f4c06f9dc3b3813fa859479d321508675a5c0 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 22 Dec 2016 12:10:52 +0100 Subject: [PATCH 39/71] :construction: cleanup --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3e873cbc..c99778af 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ all: # clean up clean: - rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM + rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM test/*.dSYM rm -fr benchmarks/files/numbers/*.json $(MAKE) clean -Cdoc $(MAKE) clean -Ctest From 6e129fbfb7a09856659763a13193d6ae1ee6ae0f Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 25 Dec 2016 14:39:08 +0100 Subject: [PATCH 40/71] :memo: some small documentation fixes --- doc/Makefile | 1 + src/json.hpp | 16 ++++++++++------ src/json.hpp.re2c | 16 ++++++++++------ 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 56198923..04a5cc7b 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -57,6 +57,7 @@ doxygen: create_output create_links $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html + $(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html upload: clean doxygen check_output cd html ; ../scripts/git-update-ghpages nlohmann/json diff --git a/src/json.hpp b/src/json.hpp index 23058bee..cb301643 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -3793,7 +3793,7 @@ class basic_json container `c`, the expression `c.front()` is equivalent to `*c.begin()`. @return In case of a structured type (array or object), a reference to the - first element is returned. In cast of number, string, or boolean values, a + first element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. @@ -3836,7 +3836,7 @@ class basic_json @endcode @return In case of a structured type (array or object), a reference to the - last element is returned. In cast of number, string, or boolean values, a + last element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. @@ -4187,10 +4187,14 @@ class basic_json element is not found or the JSON value is not an object, end() is returned. + @note This method always returns @ref end() when executed on a JSON type + that is not an object. + @param[in] key key value of the element to search for @return Iterator to an element with key equivalent to @a key. If no such - element is found, past-the-end (see end()) iterator is returned. + element is found or the JSON value is not an object, past-the-end (see + @ref end()) iterator is returned. @complexity Logarithmic in the size of the JSON object. @@ -4233,6 +4237,9 @@ class basic_json default `std::map` type, the return value will always be `0` (@a key was not found) or `1` (@a key was found). + @note This method always returns `0` when executed on a JSON type that is + not an object. + @param[in] key key value of the element to count @return Number of elements with key @a key. If the JSON value is not an @@ -4792,9 +4799,6 @@ class basic_json object | `{}` array | `[]` - @note Floating-point numbers are set to `0.0` which will be serialized to - `0`. The vale type remains @ref number_float_t. - @complexity Linear in the size of the JSON value. @liveexample{The example below shows the effect of `clear()` to different diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index ac9a3315..6723e75a 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -3793,7 +3793,7 @@ class basic_json container `c`, the expression `c.front()` is equivalent to `*c.begin()`. @return In case of a structured type (array or object), a reference to the - first element is returned. In cast of number, string, or boolean values, a + first element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. @@ -3836,7 +3836,7 @@ class basic_json @endcode @return In case of a structured type (array or object), a reference to the - last element is returned. In cast of number, string, or boolean values, a + last element is returned. In case of number, string, or boolean values, a reference to the value is returned. @complexity Constant. @@ -4187,10 +4187,14 @@ class basic_json element is not found or the JSON value is not an object, end() is returned. + @note This method always returns @ref end() when executed on a JSON type + that is not an object. + @param[in] key key value of the element to search for @return Iterator to an element with key equivalent to @a key. If no such - element is found, past-the-end (see end()) iterator is returned. + element is found or the JSON value is not an object, past-the-end (see + @ref end()) iterator is returned. @complexity Logarithmic in the size of the JSON object. @@ -4233,6 +4237,9 @@ class basic_json default `std::map` type, the return value will always be `0` (@a key was not found) or `1` (@a key was found). + @note This method always returns `0` when executed on a JSON type that is + not an object. + @param[in] key key value of the element to count @return Number of elements with key @a key. If the JSON value is not an @@ -4792,9 +4799,6 @@ class basic_json object | `{}` array | `[]` - @note Floating-point numbers are set to `0.0` which will be serialized to - `0`. The vale type remains @ref number_float_t. - @complexity Linear in the size of the JSON value. @liveexample{The example below shows the effect of `clear()` to different From dbdcb3fec8f4ac47d99ab283a5c60034b3297539 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 25 Dec 2016 16:06:36 +0100 Subject: [PATCH 41/71] :bug: fixed bug in CBOR/MessagePack deserialization --- src/json.hpp | 30 ++++++++++++++++++++++++++++++ src/json.hpp.re2c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/json.hpp b/src/json.hpp index 23058bee..1d92b51a 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6831,6 +6831,27 @@ class basic_json } } + /*! + @brief checks if a given length does not exceed the size of a given vector + + To secure the access to the byte vector during CBOR/MessagePack + deserialization, bytes are copied from the vector into buffers. This + function checks if the number of bytes to copy (@a len) does not exceed the + size of the given vector @a vec. + + @param[in] vec byte vector + @param[in] len length + + @throws out_of_range if `len > v.size()` + */ + static void check_length(const std::vector<uint8_t>& vec, const size_t& len) + { + if (len > vec.size()) + { + throw std::out_of_range("len out of range"); + } + } + /*! @brief create a JSON value from a given MessagePack vector @@ -6882,6 +6903,7 @@ class basic_json const size_t len = v[current_idx] & 0x1f; const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } } @@ -6985,6 +7007,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -6993,6 +7016,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7001,6 +7025,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7219,6 +7244,7 @@ class basic_json const auto len = static_cast<size_t>(v[current_idx] - 0x60); const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7227,6 +7253,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7235,6 +7262,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7243,6 +7271,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7251,6 +7280,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx)); const size_t offset = current_idx + 9; idx += len + 8; // skip 8 size bytes + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index ac9a3315..d5b05c01 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6831,6 +6831,27 @@ class basic_json } } + /*! + @brief checks if a given length does not exceed the size of a given vector + + To secure the access to the byte vector during CBOR/MessagePack + deserialization, bytes are copied from the vector into buffers. This + function checks if the number of bytes to copy (@a len) does not exceed the + size of the given vector @a vec. + + @param[in] vec byte vector + @param[in] len length + + @throws out_of_range if `len > v.size()` + */ + static void check_length(const std::vector<uint8_t>& vec, const size_t& len) + { + if (len > vec.size()) + { + throw std::out_of_range("len out of range"); + } + } + /*! @brief create a JSON value from a given MessagePack vector @@ -6882,6 +6903,7 @@ class basic_json const size_t len = v[current_idx] & 0x1f; const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } } @@ -6985,6 +7007,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -6993,6 +7016,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7001,6 +7025,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7219,6 +7244,7 @@ class basic_json const auto len = static_cast<size_t>(v[current_idx] - 0x60); const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7227,6 +7253,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7235,6 +7262,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7243,6 +7271,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7251,6 +7280,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx)); const size_t offset = current_idx + 9; idx += len + 8; // skip 8 size bytes + content bytes + check_length(v, len + offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } From 6de9d4035a3becaa7d92812ca3ededfaf9a0cb29 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 25 Dec 2016 16:06:56 +0100 Subject: [PATCH 42/71] :bug: fixed AFL driver to also read binary data --- test/src/fuzzer-driver_afl.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/test/src/fuzzer-driver_afl.cpp b/test/src/fuzzer-driver_afl.cpp index e386033a..eddeae41 100644 --- a/test/src/fuzzer-driver_afl.cpp +++ b/test/src/fuzzer-driver_afl.cpp @@ -11,9 +11,9 @@ passed byte array. Licensed under the MIT License <http://opensource.org/licenses/MIT>. */ -#include <sstream> -#include <cstdint> -#include <iostream> +#include <vector> // for vector +#include <cstdint> // for uint8_t +#include <iostream> // for cin extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); @@ -23,10 +23,15 @@ int main() while (__AFL_LOOP(1000)) { #endif - // copy stdin to stringstream to pass it to fuzzer as byte array - std::stringstream ss; - ss << std::cin.rdbuf(); - LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t*>(ss.str().c_str()), ss.str().size()); + // copy stdin to byte vector + std::vector<uint8_t> vec; + char c; + while (std::cin.get(c)) + { + vec.push_back(static_cast<uint8_t>(c)); + } + + LLVMFuzzerTestOneInput(vec.data(), vec.size()); #ifdef __AFL_HAVE_MANUAL_CONTROL } #endif From e4cc62e6538662e0526eb81689a0d55334c1ac33 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 25 Dec 2016 16:07:10 +0100 Subject: [PATCH 43/71] :bug: fixed Makefile to work with proper CBOR files --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c99778af..76e60170 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ fuzz_testing_cbor: mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out $(MAKE) parse_cbor_fuzzer -C test CXX=afl-clang++ mv test/parse_cbor_fuzzer fuzz-testing/fuzzer - find test/data -size -5k -name *cbor | xargs -I{} cp "{}" fuzz-testing/testcases + find test/data -size -5k -name *.cbor | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" From 1399abc58371978814e62b5eadc281ccbeb8dc96 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 25 Dec 2016 16:18:56 +0100 Subject: [PATCH 44/71] :construction: added MessagePack fuzz target --- Makefile | 8 ++++ test/Makefile | 3 ++ test/src/fuzzer-parse_msgpack.cpp | 68 +++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 test/src/fuzzer-parse_msgpack.cpp diff --git a/Makefile b/Makefile index 76e60170..8f196950 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,14 @@ fuzz_testing_cbor: find test/data -size -5k -name *.cbor | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" +fuzz_testing_msgpack: + rm -fr fuzz-testing + mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out + $(MAKE) parse_msgpack_fuzzer -C test CXX=afl-clang++ + mv test/parse_msgpack_fuzzer fuzz-testing/fuzzer + find test/data -size -5k -name *.msgpack | xargs -I{} cp "{}" fuzz-testing/testcases + @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" + ########################################################################## # static analyzer diff --git a/test/Makefile b/test/Makefile index a063221a..556ab0d7 100644 --- a/test/Makefile +++ b/test/Makefile @@ -89,3 +89,6 @@ parse_afl_fuzzer: parse_cbor_fuzzer: $(CXX) $(CXXFLAGS) $(CPPFLAGS) src/fuzzer-driver_afl.cpp src/fuzzer-parse_cbor.cpp -o $@ + +parse_msgpack_fuzzer: + $(CXX) $(CXXFLAGS) $(CPPFLAGS) src/fuzzer-driver_afl.cpp src/fuzzer-parse_msgpack.cpp -o $@ diff --git a/test/src/fuzzer-parse_msgpack.cpp b/test/src/fuzzer-parse_msgpack.cpp new file mode 100644 index 00000000..992697c2 --- /dev/null +++ b/test/src/fuzzer-parse_msgpack.cpp @@ -0,0 +1,68 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ (fuzz test support) +| | |__ | | | | | | version 2.0.9 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +This file implements a parser test suitable for fuzz testing. Given a byte +array data, it performs the following steps: + +- j1 = from_msgpack(data) +- vec = to_msgpack(j1) +- j2 = from_msgpack(vec) +- assert(j1 == j2) + +The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer +drivers. + +Licensed under the MIT License <http://opensource.org/licenses/MIT>. +*/ + +#include <iostream> +#include <sstream> +#include <json.hpp> + +using json = nlohmann::json; + +// see http://llvm.org/docs/LibFuzzer.html +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + try + { + // step 1: parse input + std::vector<uint8_t> vec1(data, data + size); + json j1 = json::from_msgpack(vec1); + + try + { + // step 2: round trip + std::vector<uint8_t> vec2 = json::to_msgpack(j1); + + // parse serialization + json j2 = json::from_msgpack(vec2); + + // deserializations must match + assert(j1 == j2); + } + catch (const std::invalid_argument&) + { + // parsing a MessagePack serialization must not fail + assert(false); + } + } + catch (const std::invalid_argument&) + { + // parse errors are ok, because input may be random bytes + } + catch (const std::out_of_range&) + { + // parse errors are ok, because input may be random bytes + } + catch (const std::domain_error&) + { + // parse errors are ok, because input may be random bytes + } + + // return 0 - non-zero return values are reserved for future use + return 0; +} From e3b036348b16c1cbfb41e0d746160a99cfee989c Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 25 Dec 2016 16:36:43 +0100 Subject: [PATCH 45/71] :construction: added targets for parallel AFL fuzzing --- Makefile | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Makefile b/Makefile index 8f196950..e2c120db 100644 --- a/Makefile +++ b/Makefile @@ -70,6 +70,19 @@ fuzz_testing_msgpack: find test/data -size -5k -name *.msgpack | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" +fuzzing-start: + afl-fuzz -S fuzzer1 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null & + afl-fuzz -S fuzzer2 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null & + afl-fuzz -S fuzzer3 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null & + afl-fuzz -S fuzzer4 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null & + afl-fuzz -S fuzzer5 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null & + afl-fuzz -S fuzzer6 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null & + afl-fuzz -S fuzzer7 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null & + afl-fuzz -M fuzzer0 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer + +fuzzing-stop: + -killall fuzzer + -killall afl-fuzz ########################################################################## # static analyzer From acb7e0558d2337ad42261ed81e67d37385679285 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 28 Dec 2016 12:09:15 +0100 Subject: [PATCH 46/71] :ambulance: fixed bugs detected by AFL-Fuzz --- src/json.hpp | 57 +++++++++++++ src/json.hpp.re2c | 57 +++++++++++++ ...0,sig:06,src:000223+000677,op:splice,rep:2 | 1 + ...id:000000,sig:06,src:000787,op:havoc,rep:8 | Bin 0 -> 19 bytes ...d:000000,sig:06,src:000833,op:havoc,rep:32 | Bin 0 -> 38 bytes ...d:000000,sig:06,src:000838,op:havoc,rep:64 | Bin 0 -> 842 bytes ...,sig:06,src:000846+001064,op:splice,rep:16 | Bin 0 -> 201 bytes ...id:000000,sig:06,src:000848,op:flip1,pos:0 | Bin 0 -> 263 bytes ...d:000000,sig:06,src:001435,op:havoc,rep:32 | Bin 0 -> 2488 bytes ...id:000000,sig:06,src:001436,op:havoc,rep:4 | Bin 0 -> 2579 bytes ...1,sig:06,src:000864+000903,op:splice,rep:2 | Bin 0 -> 33 bytes ...,sig:06,src:001310+001138,op:splice,rep:32 | 1 + ...,sig:06,src:001330+000569,op:splice,rep:64 | Bin 0 -> 1932 bytes ...d:000001,sig:06,src:001413,op:havoc,rep:32 | Bin 0 -> 1396 bytes ...id:000001,sig:06,src:001447,op:havoc,rep:4 | Bin 0 -> 1839 bytes ...1,sig:06,src:001465+000325,op:splice,rep:4 | Bin 0 -> 475 bytes ...id:000002,sig:06,src:000539,op:havoc,rep:8 | Bin 0 -> 140 bytes ...d:000002,sig:06,src:001301,op:havoc,rep:16 | Bin 0 -> 16 bytes ...2,sig:06,src:001317+000850,op:splice,rep:8 | Bin 0 -> 349 bytes ...:000002,sig:06,src:001382,op:havoc,rep:128 | Bin 0 -> 3116 bytes ...2,sig:06,src:001413+001036,op:splice,rep:4 | Bin 0 -> 395 bytes ...,sig:06,src:000846+000155,op:splice,rep:16 | Bin 0 -> 222 bytes ...:000004,sig:06,src:001445,op:havoc,rep:128 | Bin 0 -> 4382 bytes test/src/unit-cbor.cpp | 78 ++++++++++++++++++ 24 files changed, 194 insertions(+) create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32 create mode 100644 test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4 create mode 100644 test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4 create mode 100644 test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8 create mode 100644 test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16 create mode 100644 test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8 create mode 100644 test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128 create mode 100644 test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4 create mode 100644 test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16 create mode 100644 test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128 diff --git a/src/json.hpp b/src/json.hpp index cb301643..913f1966 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6835,6 +6835,44 @@ class basic_json } } + + /* + @brief checks if given lengths do not exceed the size of a given vector + + To secure the access to the byte vector during CBOR/MessagePack + deserialization, bytes are copied from the vector into buffers. This + function checks if the number of bytes to copy (@a len) does not exceed the + size @s size of the vector. Additionally, an @a offset is given from where + to start reading the bytes. + + This function checks whether reading the bytes is safe; that is, offset is a + valid index in the vector, offset+len + + @param[in] size size of the byte vector + @param[in] len number of bytes to read + @param[in] offset offset where to start reading + + vec: x x x x x X X X X X + ^ ^ ^ + 0 offset len + + @throws out_of_range if `len > v.size()` + */ + static void check_length(const size_t size, const size_t len, const size_t offset) + { + // simple case: requested length is greater than the vector's length + if (len > size or offset > size) + { + throw std::out_of_range("len out of range"); + } + + // second case: adding offset would result in overflow + if ((size > (std::numeric_limits<size_t>::max() - offset))) + { + throw std::out_of_range("len+offset out of range"); + } + } + /*! @brief create a JSON value from a given MessagePack vector @@ -6886,6 +6924,7 @@ class basic_json const size_t len = v[current_idx] & 0x1f; const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } } @@ -6989,6 +7028,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -6997,6 +7037,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7005,6 +7046,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7223,6 +7265,7 @@ class basic_json const auto len = static_cast<size_t>(v[current_idx] - 0x60); const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7231,6 +7274,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7239,6 +7283,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7247,6 +7292,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7255,6 +7301,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx)); const size_t offset = current_idx + 9; idx += len + 8; // skip 8 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7595,6 +7642,11 @@ class basic_json */ static basic_json from_msgpack(const std::vector<uint8_t>& v) { + if (v.empty()) + { + throw std::invalid_argument("empty vector"); + } + size_t i = 0; return from_msgpack_internal(v, i); } @@ -7652,6 +7704,11 @@ class basic_json */ static basic_json from_cbor(const std::vector<uint8_t>& v) { + if (v.empty()) + { + throw std::invalid_argument("empty vector"); + } + size_t i = 0; return from_cbor_internal(v, i); } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 6723e75a..3b598542 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6835,6 +6835,44 @@ class basic_json } } + + /* + @brief checks if given lengths do not exceed the size of a given vector + + To secure the access to the byte vector during CBOR/MessagePack + deserialization, bytes are copied from the vector into buffers. This + function checks if the number of bytes to copy (@a len) does not exceed the + size @s size of the vector. Additionally, an @a offset is given from where + to start reading the bytes. + + This function checks whether reading the bytes is safe; that is, offset is a + valid index in the vector, offset+len + + @param[in] size size of the byte vector + @param[in] len number of bytes to read + @param[in] offset offset where to start reading + + vec: x x x x x X X X X X + ^ ^ ^ + 0 offset len + + @throws out_of_range if `len > v.size()` + */ + static void check_length(const size_t size, const size_t len, const size_t offset) + { + // simple case: requested length is greater than the vector's length + if (len > size or offset > size) + { + throw std::out_of_range("len out of range"); + } + + // second case: adding offset would result in overflow + if ((size > (std::numeric_limits<size_t>::max() - offset))) + { + throw std::out_of_range("len+offset out of range"); + } + } + /*! @brief create a JSON value from a given MessagePack vector @@ -6886,6 +6924,7 @@ class basic_json const size_t len = v[current_idx] & 0x1f; const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } } @@ -6989,6 +7028,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -6997,6 +7037,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7005,6 +7046,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7223,6 +7265,7 @@ class basic_json const auto len = static_cast<size_t>(v[current_idx] - 0x60); const size_t offset = current_idx + 1; idx += len; // skip content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7231,6 +7274,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx)); const size_t offset = current_idx + 2; idx += len + 1; // skip size byte + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7239,6 +7283,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx)); const size_t offset = current_idx + 3; idx += len + 2; // skip 2 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7247,6 +7292,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx)); const size_t offset = current_idx + 5; idx += len + 4; // skip 4 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7255,6 +7301,7 @@ class basic_json const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx)); const size_t offset = current_idx + 9; idx += len + 8; // skip 8 size bytes + content bytes + check_length(v.size(), len, offset); return std::string(reinterpret_cast<const char*>(v.data()) + offset, len); } @@ -7595,6 +7642,11 @@ class basic_json */ static basic_json from_msgpack(const std::vector<uint8_t>& v) { + if (v.empty()) + { + throw std::invalid_argument("empty vector"); + } + size_t i = 0; return from_msgpack_internal(v, i); } @@ -7652,6 +7704,11 @@ class basic_json */ static basic_json from_cbor(const std::vector<uint8_t>& v) { + if (v.empty()) + { + throw std::invalid_argument("empty vector"); + } + size_t i = 0; return from_cbor_internal(v, i); } diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2 b/test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2 new file mode 100644 index 00000000..e30ed176 --- /dev/null +++ b/test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2 @@ -0,0 +1 @@ +�{�������������� \ No newline at end of file diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8 b/test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8 new file mode 100644 index 0000000000000000000000000000000000000000..8de7c9e50d18d64f7807ba158718d1f71895dcbb GIT binary patch literal 19 Ucmb>a4*~zI8JHLtY#4w50DwOT>;M1& literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32 b/test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32 new file mode 100644 index 0000000000000000000000000000000000000000..d2ae80c771595f1dd59d700664577524eb5b6c78 GIT binary patch literal 38 ncmb>a4+Yz{ZCko+8v~FsY*hH0R#}`{B9NAmvAB3qiNr4e3C$Nr literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64 b/test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64 new file mode 100644 index 0000000000000000000000000000000000000000..d1ef19b507738ecf9c8e939347afc9087aad6876 GIT binary patch literal 842 zcmb>a4+Yz{$)Db~EwwbYcH+c|^OvrjxCRUqz~oj20SI@^|MwFoPMEl8B2ZVup>5l? zIcx@MO4*SF)C2^Ltq}Tri3G#{2FAoJ=bXmcYz2?hq6UUU28Hyzs?@xav}6VbCWay_ zl7JCb)j?QAQ3Z>D76NTeElSBt%uP)xF3p3=V>c32GkLs{%#ywm?bHf|U`fU=_3}V# zvvU(O^Ww`h8Gs<Qq!_3GC@mG7Se%!eIsgtN;H||&7i_1B)3Ha3VOR!cLT6xPU?@&4 Hk@y7w=dWiJ literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16 b/test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16 new file mode 100644 index 0000000000000000000000000000000000000000..42b437e065a2056b4964bea5475518ae21df225e GIT binary patch literal 201 zcmb>a4+Y!6fB{6-9|Do5w{1(!O|6{>0&6F(K>}OX#DIW3n4CBfs(v$2eM)K)SpCFC u5Oo#;o<M2b)D4i-QQY!KGAS|T^$ZLQiMgqn#U*)$=^6fMX~n4}62Aa=JcT#_ literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0 b/test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0 new file mode 100644 index 0000000000000000000000000000000000000000..82f3520df29576b59353474e57367534541ac727 GIT binary patch literal 263 zcmb>a4+Y!6fB{6-9|Do5w{1%;O|6{>0&6F(K>}OhY_KGVfN9zc)RdB%1QBn9N}n&0 z_?41al9=V3lbM{Y;E`I?z>vtGke-*DnpcvR3?x#EQi?OHQYBOpbMsS*OY;mHGyKz9 zi&IM^(lRniBpJWd%O~chX6Ghm=Eaw1=B31xr<P;_p>}G8RB&QwU2&>{H!go<Cgw1r ST9pSh3v5dm(3TF6Ex!Pf-H5&b literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32 b/test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32 new file mode 100644 index 0000000000000000000000000000000000000000..679a1663ad992f2b5702463eddfb0279f06d3c8e GIT binary patch literal 2488 zcmeHJ&rcIU6khZsCy(`D+>0b6(hUX^LPGdafk>dNZ4(a0gz3!N-GSMi?aY+!s*&o| zo6*D@#Df?A0sjR42Tz_fF~JLHjL|x~Eu}PqH3ISAoaTG;_RV|W+q`d{)#i&!d9y^2 zLJQpOGYzRs8z}`MFheBe@Rs7`x`CDX!mLr{nZqV9@L@-7)kg>Sc0a!{SH3OX*tsx9 zc`&I$+oKE-VBuqmu9^0fl7IyEW&)Q6P~c^*<iJE_d1iX(R({qJsbPeaLxvRCf@6@9 ziyYfHydE8fDZ1bI?fTl`@rwutrg$Sf07vgW9DQ{B$<yPHpLZQU?81K!pR_}~dOcpO zumTV&04v=z-Rsei-Bqx(4nj}@y8YgY#0Yy(0zd7HEGjM_bDe$ZSZ_P_|F<X1z{@{f zCw%{zgqt*ay5>_)UZ?J4^p@?Z=W(VN{3G1=R`d7c+(bM^11&Rp<V|(xly|gFmAiB* zOUmo2H4$yYxM(C=^^s|nj4pBEW-)(XZ)BHaNo%p2jLrwBvC(KGgVaWN4Y^Q4t}K8f zK)Q2`ONm6R(}}KHRVggSF=CeDK1NCdS6Vslps2(-lUa?0Lm89=3Zw&KmNNn(8rlDH zv;Aca$`0{qFc%G4SdVw8D+?tCOMuVUVIrOE<GPT#p+#2?P%^%%!!M$!NbkW)(0U8( z<JB@0L1=B*W9{O#LTsueuYHTOe5suns3DvZa-~U#6M)Qm%Gaf(EVv+b1(;^Gt1U~L zm!`yQ`vm<!={}E>@+(O?DYiAyH7<x~TS_3+?J9`asY;kH+Pji~gQ`p|(2Hum)v1tC zqLOYTPmCm&D5Gg{XuAVr0?2d>DcOGCx$~*tstnsV-&uSY<#-Ut3~9=uty?K?Qla7k zAktqsD6ZLDufIz^lbY8uq(*4nFbplFI$VZCm(xV@bF5EW5B;C5zoavemSvDA%3@z; Gb3Xwc-m0Vk literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4 b/test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4 new file mode 100644 index 0000000000000000000000000000000000000000..bb32f698895c0584b1476a95e8db9b6272bef2f5 GIT binary patch literal 2579 zcmdT`&u<e)6t?N9oH)7%)D;3Gq{gf8LqbLo3WlVOOl)FT2yw~m&fDE_W_Q-}#__r! z63)H$4yRr!E}Z%&@SpSm;slkdBFvlhdPzti3Lt3b;(5<{&)>ZFeee0V(Mq?y>hw4> ztfj)L0yIvC83Q_TQieGH&?v7DzHvs*NSMf(cR)f6&&|W_i)UWG`1?<1{onS5=ifGj zN=}-z6A8&U$TSk{2dA@W5SaF(Ye^^)SW})dc-kA>ymn>or`07_=Z-q}QppT-wDJK_ z>89M;eeUlzr`Du6cV?G8pa1Oe?3ZDOFWqtf>eqXp9l@_<#^3)~=nmu>aG|NI)HLe# z#k~COP0(6!p!P@W=rccp9>n=q*fmN+?X0vsxn=J^Ynff@bI)(Y!q*B_U>Z1(2%54q zT({M3F1CJbcYBTb^XJZ8x=L{#TN1KNX#%CYJGg=M$iyoD)eZ|`*wf74s681L9)E+J zJr)*7p2QYOj%w9c0m}wc8}Pt5p2uy$t~h#8huA(+n(H!ikHm0e2zne05mvgL7sw%C zLupzOnptU5Dc&0P4Oz`sNg%>ysSueSH#G1oV`y5GQ`C<SefZHqSs7e|Km$fc-)YhG z;e7P!5QmGRh)tE$cy>HTzPc={l}d$>i-crJ6j}UeU2mF#L8Z2zN~&}Aozh|5SAT6! z>Nm$IM&r=d^DdigO(vFj9cq5j@ac2kmJ<zO@-0b~8)QADB=$uj%v{Peiyv)B6}E^+ z7I${a9inz6nbI{XCNCKwx_LA5&^p;Vu)NeP!2tA<k{on)eir$lj2wX%q$#>oBm;?Y z_eS}YtQuPWwCpUMUMkh9Me{7lPRw%7&{V29nj*kLq1hRWWH~!i{z~p}HN<KYF6Sgz zpqg%1XkOxJ!58`zb)98h@e8acMW&hE_n?~#@}(^MVC!aV(PkcWW2;&TX3o!h^Zm3p zK?3h+azAYyMCJb{bB|TL{|<A%3_nRNd-z$X<xBJP!Kd(3d~j#H-e+eVa`ua3W~CTv zH2ZnE2o9Y6)g#~7e>wF&rp2~W`Zh_GW^aNuJ{{+F_u*Bc&3FyiVZ_75HVtih%R!_3 NefxuDbw9>>^9`wVbX@=d literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2 b/test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2 new file mode 100644 index 0000000000000000000000000000000000000000..e94858106169ac59d0330ea1f59fcc42f09d2f2e GIT binary patch literal 33 ecmZ3OQa^bX!-NUe4Q2jmtlVHwUteGS9|i#A<`C`x literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32 b/test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32 new file mode 100644 index 00000000..92079a80 --- /dev/null +++ b/test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32 @@ -0,0 +1 @@ +�{������������������������������et� \ No newline at end of file diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64 b/test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64 new file mode 100644 index 0000000000000000000000000000000000000000..0e3f141f863bb079b063807cf5accd2f27fadc2f GIT binary patch literal 1932 zcmeHIy-ve05VlYsfHz=bth4X}s8Xg@0yR4v$tAe8<H|lDf}t$DL7xC-UWcb(Lr93l zByCWBV5t;ZRpO?*^Xa?KXWi$;;?8w%pX)*HvGwYk)s`PeN~B{n*AnSb+LhB!LE$tO z63<o%^?eXZur_nfBs|nHWIT*4_r(ZHh^Gd`WLXpFxwI3J3hK|mfO?)v?GJSbbEnhn z(7Uq6lX)mT(kcYXgTxM+M0YIu*fG8x(0yoI2blj5F5ggg-`>!z&SihA-D}NXYksfh zZ^r%gVUQ~6EERDR(#aTem2`T8LYV`trRBMlnnK3|1F4PC_*zD2vZJ4(dxIA*e_#<1 z40SSsY%Ff^ob`~Pm<*bCNvLM>l<)-TQd7?NEh#cUXua0h4s`Y7D9fuGmQ(%$hfzmd literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32 b/test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32 new file mode 100644 index 0000000000000000000000000000000000000000..0ce68701c4269554399e96dd393c063e3493f186 GIT binary patch literal 1396 zcmc(fy>1gh5XaBBA{C_@q^ppSz$i!{WQ0UwLcj|4VH=@9LDsi(zBPBZ=bf?dtRQSU zBpM1T8dA~l0z3;(Kt&ah5QW)W8!P^Z3kuk3=Qp!Eqn-cGyQI>nRqZBc#P(!6CjrTJ z7!fGzcFYhrk4UyU;F6u#i6GzJv>|{HzR}U>#>MZ)KR(+BziQXMoGl3%ZBgv_B48YX z*ca@Q?Q9VOQ?9==Xp0EyvLy*Gw7QRXwlCkW-o2s>DDqYuFak$O7Z9Z?2gCXGYTh)~ z;dpKt_IgF!49$g4jh`prEKqOWo;0R=SY&6cMRL0RY&h(%Tb<L7E_+^PXuQPpOJp@j zmhqbz`uOQqqZ`$M3#GfRn@VKmOnYj5P)cyn^6(GPWv&n7VQ5^~AgQ2mHOO?dpY0#1 zAide)Ew>bkdnSfFsTvb8M41?{=&yT_zxKUYdGh*7`tRU}EY<$Hd{5Rn`?h6SYXkm^ zlbOC(UFos3oAut<j-DHdR9wwSQ;(I0Jx~L$hfrxa$H+ndyb<k*b5sFt1QG{=QxhhN zD*6<r1y@Gn@zNjlM0+=oh)fMi3i$Q_%2@$n&dO(Fq}ah&7n7P|o<3k{Sw;~S_(ZY} zYXjbSuV_#Q#y7e~#|GBHQ-J=)B<@ck*i_7YUf>BABi#cnZGByVr{{HTo~Z5yIZbsT XBGS3D8Q8;xiw>uMgr!9{#QfLaIWB|R literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4 b/test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4 new file mode 100644 index 0000000000000000000000000000000000000000..35f3cb597438e5ac05686abe6588f769b8e233a4 GIT binary patch literal 1839 zcmcJQ&ubGw6vq>LvLJZOMO*|61)HU|LP;r7(;pgQ5|fCCm(K3I%}zSIlgvz-je?DM z^y0yj7kly|UOf3H^l$Jl@F1RAK`hp{n@vp8h+1?mnfJ}in>X)$-p-45u2L)*RZ29; zi&|2E(ng7B4bnFnM5*~bEv!1&+GrbXrd?y+01h5})_dKh*~5b`?~Sc*#cLnVW|;6- zb))1mPAKq(%g7a@w5k;lX}jy48uOtnETPqm)x5WUWA0XA!<3PbrdER!4J9dTP)f)w z-yI!KM$O22bUZR9tQeC<mdD1|A#r&5^I;>N!vyVrNslKxo|-J5P}?Vz-Dd;o^_!JS zlb3-qiFL)YVYQc{0u*;ZN=5+zaJQ6AY!|BFMSrP^77|idc}U9raDG?vV7X2$JL551 z3MCw!QBAHu?pQKon)zaOHGi{Msb=OE7Z#S+aGyms7$3OQj*yie9ezlMO1s(<(Wxa; zgH}}%dpot?iWPes#VV<Vk@RWpVVg)MZKByHKe%MJlr%Xy;ieXzO%h2iYRZi9PNRWz zdd%MpW=$J!4!$-c!Ia>M9k?DHwxYr7CXh&Vj?tAm?z&Ba3VR4!e(b4l*Da{vg+U&2 z+|#2NlP9zgT=f-YdSO;L=sBBXPX!l+tfg(?{Je9{#iZvzO}O*Bcy#-dv0pmf9OO)u z!I7Zc>9OMV+|u^Z??&JEKXrO^gc%=BFw&D1eu@Th#-#9wB;MO?%yb@$7eX0a9<Qaw z!eTA6!XZI5%x_pu>4Zc{;wuN_hTs%ru-M=EDyBf2ZLpk1Lk((va+i(HlC`+JNijke zMstF!IGR(FHFFBGo@zI7{D)-G(Qb;!Vw1ZG`+DD_<U5IayntYmpc!5)vP(#8TSzJg zN);c8J1vkMr==iQDIF*Z4ry_nXXkYeXw(J`&ZzExJ;GRm6gHg0YMWdrMPw%<f!^pK z2zZ*8JTn!(0O`7F3{HN4O@^5GDn)xZhhGJ?_EPFj8OYxdN?A9NNDQdE5Cu}$<VjR9 U5a#3A(ew4I{vkoy_SDqJA7y<u2LJ#7 literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4 b/test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4 new file mode 100644 index 0000000000000000000000000000000000000000..64812d4f4540f9794ab32226c6a42988c207836a GIT binary patch literal 475 zcmZ3OGHdcIh6xj_8_N9CSa<znHC~ijY$%W~X_Ny5)(X}F)?U`W?$-YyAT=*H4X*-L z2~25{4XZ}7Ek8cB#42S+NJe^cer|4RUP-RLzJk7kf{miCi2?%;0|UeFl#-&-)UTPT znkaxFF{eU4!Em~wgR+WhoSK%Qk+F%XnYo2!BG??)-|oz;P5&KoQ;Y8oGQb$jz#zao zU8FR%ur$9UHAg8eKPf9Uxul`OQa?uNO+j9IW@1iedIu;p(vpEhYEepFVs2_macQ1m OdWL^mT5)QL#4i8}qWaVT literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8 b/test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8 new file mode 100644 index 0000000000000000000000000000000000000000..5c537f8d79df076878d1fc1f8a37152d2e810812 GIT binary patch literal 140 zcmZ3OR-T!Xo?5abHHCqZfgveBulhfB@Kb<+f#K)RlAS53#c`EsetD@4#=kQ265l4L zmZVmc2ry*$rzIw5mKYdlDjZWtNi0ds$xJWFO=S>ZNL9}$kyOZ=n9C0|A}^(6ngipP Xw8GTP^qdk&qc16WiMcu1h7!L3r4T|{ literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16 b/test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16 new file mode 100644 index 0000000000000000000000000000000000000000..0bde9e5dafffd9b12824980438be7148cc5b4cbd GIT binary patch literal 16 OcmeC4QvDwR7=!?C;0&Sw literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8 b/test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8 new file mode 100644 index 0000000000000000000000000000000000000000..0a004d9e5d88a9143366bb06355f4802b8978194 GIT binary patch literal 349 zcmbPI{hvs1k4SY?SM~;I;<nV3)TD`E&<LR>o-dL3m6BMJnB|<4nVhZQky_NikjS8r zo|l`NSCW<tBvOk~iZiQHB~%h~^HYjT^9&m^{L@;CQ%fY$GBQde8NbxaC+4PR=O*Um z#g}L1rNoq{mSh5<c4~!GaAIg(ajJqh)HmC}Km<hA9|Dn?i8+j@R^<WB0^1S>w50=N G%P#;ZUH69o literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128 b/test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128 new file mode 100644 index 0000000000000000000000000000000000000000..6ff4823ae78f780f81f09637fa08249459c2338e GIT binary patch literal 3116 zcmZ3OGHdcIh6xj_8_N9CSa<znl~|NoY$%W~X_S+b(-fg#EnsYG?dxv+9|BVIa+`q) zJfRA5tbq!wy{vP=3V#3ppITU&Uy+)q#M<=VBR92}F_?itfML2wsRB^E1Sp;c)ff-a zSWw7NTvFOzo?ewwQdFAyH8E8a9h5UNFfjP)<<}SIr|V~A73b%bR9BSr8&*SI1f*CP zAnf$yn%vUVypkw=eFc371sg?O69onyp!VMk42%q^Uo%0bW3dNAc}j^G&@s4_LtRLO z!(dKKPtMQHO=S?kbQsJgb`)<jB<B1FI(wy}gR+WhoSK%Qk+F%XfVqWbBG4TFJlEgu z%;*8UYTv7MTX~pxITH-)bj4L1{M58GAd&W_d*AC-0ti{4nMktr|AA4OwkQ=Pih+E1 z8pw$TMzJ<5ia|bV06MK06r!Lc0!snD?%*Wj3FAXj1V}kJMPVvON>OQxfC&fTihD=^ zmJ%^tfy3DRUvO8cB0Cy~a;PgFg01&Mcv=CJu6<DxesX@ie~A@5wUg>MMh2i|+M{4J z1V%$(Gz11o2!IMPXxWP>{NN>izN8&e5ucl8EdW*zD$+f`HGmqDG@=Gk0GH(m^Pr6c zgaS}$>mQ$5VwJKZBm+`8LTYUXNUaU4$cV10vcb(2j7s7$j#3}ex<RX|2Cj7iYXnf- zI$;oiHzSZ*C$Tu1O^~?!{~tL5P@7Fqhhan$14`p69MM{WSPyJ)VTgfc1VHT?9){_P zkg7Bb6#IRkrV+L_8y+JVfJT6uMzH22G%5=awt$q-$d<`eX|%#Z|9=r0NGO6eqSK0! zvQm>v8Y(RH1(cqw1~%i68hNn1;TEs0`+oC0P`eK(1T%FDknsW7PGcy~EXhzXRLD)u zO-e0NvWiwpEH7fH)Bp=xDtP6j=B8$pD8<(1DikXeD6p`yvAa3?xVd|HdU^Z!`uPV4 Q1_g(N&g}dzz`*bU07#X%a{vGU literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4 b/test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4 new file mode 100644 index 0000000000000000000000000000000000000000..d32904abc2805ce51238f7023c52ab0f6152b0f2 GIT binary patch literal 395 zcmbPI?iK9srx22oSd!?IpU#+{T3n(KkXTZZT9l_ykXT%7xS%9IDJwO(M4?=vJhLQ2 z!B8PJCp9<qUCDw53(c=zzU@#*`0a0ci_<DIKhLqGARr?%Cov^8rywIUQAZ)bv7|UP zu_!siwK6?3FEuDXDZivxEvYcv)k)XW&rQDwETET?RFIQck{VEypPX7;oL}UeQ;!N7 zQMnM_|N8$(0GkRFv1%m6aOO`q>;Hdb)f138V78{F0|P^1PKA7eVe0gX!Xt~-fC3^Y z0%|$G4;=P#ZGV0s&o?DAJ+masz|hDzH!nRiF()%UFE=HxB(3IYDllwQN)vNaQ;JI& Q8PYTS)6$AlOC){)06NLQRsaA1 literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16 b/test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16 new file mode 100644 index 0000000000000000000000000000000000000000..156afe0f177baf655b54b410a2128abd6b8002f9 GIT binary patch literal 222 zcmb>a4+XUofnf65i7(bnYy`5-mq`3dNi0dsa?Z(2&Q|b9Eoxv$WKc-Y%T3KINh{Ax zDap`f{F0WDnwjpDotsf2$@nEDFEJO$PRz`UFVD<N$uCbW$t=l9t&j>%%q_?{qTrpM zmzJ1Rnv+<PU!)M8nUbDblA4*Dn4Y>cz05x?4To@XD$phMKu6|zg48zX2k*_(E67XF hOw7rIx+WOtq|_pi^{FYvrFn)r89?KTQ+p(S0RTe0Vu%0$ literal 0 HcmV?d00001 diff --git a/test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128 b/test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128 new file mode 100644 index 0000000000000000000000000000000000000000..e342979eb1b875aadac159e722c4259527aec25c GIT binary patch literal 4382 zcmeHKPmkL~6rTvhp{E|h0V$VqKs3?P3Zbl!*zTXgDrCbZ)p9}Ei9NPwGw~!dlg6Q? zUdoOCLWm>ni3<Xu{S^HGd<T%Y(!)xK@WzfECwAO4pzVcs@q2GP_M4gae(yKmj`o`e z^-{~k3fD@gz=>3)23Cp)x75c{Zah@Hb3zPN8kI&=IVC@qk7I47+?hN{{GDee5ZbDL zuV)2`R-K(Sc_Ygi`q1g}vHwTH9l+i`=S-Fvw}nL+X$kB~i-<jrZ6d)kXz|g|z=lH_ z*yw_@g>BhXT#(|Uo{9g)b%R^jGjyg0?gnJ{hznCho>~i%|2>n4u{D&t`_0Cm(j*oh zGBx>PX;z;nMrLK;-%aR|`i<|Oot>GN2Gb}%Ao7q{;(h5{l7Xv5dVPjfxSVd$9Q~D) zuaZVuH|ca;+uSXh-b)5|En2_H3J4)Fu2L7iOu4(I`VEINY!cRYD1Non*fJ%-!f<w7 zo4VwXces)-cLqnhH?F=@->ZngQ8s(G6}k7R4zD4&L8Rp34+dN4y~u@KHu!I+lk(A6 z($Uz~>$r<2{$#Rn9D2D#+BX@O5<^f@K}-g~jl(OJ*U|@kLS3q^_OZadpSp0^HEslP zdsiw$DJl$1R#ChMUNCG~+196;&W#dE<wkT4emmAyR_vAE%z2SUWA`E@cz!)+t!I1| zPy6A=H=6@?NK7gSB!5OW#II&4PxGPtv{Fw_t906Yj@@ZgA7w=s_>k{Ej0S&yF4BT0 zME`y0NN$6nXv2k;_J*#m!oh7K1T_IBlyjUYyicI;LcDm5X-L@A*l|lRZ}Y_L7}Xv% z1ee@WRXJdi2>431Qm7qlZ`IyDXtt^w*RNgM+<|!=yr=PLTFc7fqM4{KS$0$pk~qLA zn+!E_b&EgeAlJ04L--o#$e1E`T0&QISQWn}ssd+JMLQ2M<Na&L+R6%4#dqP$-FQv} zIk96wd11j$oAcF?9?$e>n65ceMf=`oG%}8e-gB=QAYu$Yw*)b7jG;a(45*xvUs9eV zbVJLTLH7)c*T>++Vo9`#xqs=riIy02y^CuTL5Q!XWT8!TpiP8bY<Zj5joO5DVQm5- zXhs=rBBBtzl_*324`CtZ@CZ1d8IK@q@(7j8@^;ej7kNY?LGJ%YJVI|*M(0=&@UP_Y z2uP3#LYL=xME7ZU#J{7&wI$PSc_`OpC;3byO0fh>jgNDBu%p=VI7{MDt;{nKi-4=G z{p-qFXq)@9ObW5{EV&3m1(Zc`5jsT?#m(X(c@!3*=QXcRQP@}3q_6?|&A8q$xR7|) zBl7zoAirOdV^<S_8n@rYUXy-Ej!!zI8IY34zz(JW3<T!^k(HiiD{SHF1LS-%z4}C4 z<U$~@MlY-VX@Jn9&A4I5*P<z$k>%GSlb)jUJei!IBea-sCLCCN6?zNQEfqBJg&*w! N4a8pAxG&4w{{SA`b1?t_ literal 0 HcmV?d00001 diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 14944cff..5769ac98 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1186,6 +1186,84 @@ TEST_CASE("single CBOR roundtrip") } } +TEST_CASE("CBOR regressions") +{ + SECTION("fuzz test results") + { + /* + The following test cases were found during a two-day session with + AFL-Fuzz. As a result, empty byte vectors and excessive lengths are + detected. + */ + for (std::string filename : + { + "test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2", + "test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8", + "test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32", + "test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64", + "test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16", + "test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0", + "test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32", + "test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4v", + "test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2", + "test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32", + "test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64", + "test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32", + "test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4", + "test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4", + "test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8", + "test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16", + "test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8", + "test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128", + "test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4", + "test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16", + "test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128" + }) + { + CAPTURE(filename); + + try + { + // parse CBOR file + std::ifstream f_cbor(filename, std::ios::binary); + std::vector<uint8_t> vec1( + (std::istreambuf_iterator<char>(f_cbor)), + std::istreambuf_iterator<char>()); + json j1 = json::from_cbor(vec1); + + try + { + // step 2: round trip + std::vector<uint8_t> vec2 = json::to_cbor(j1); + + // parse serialization + json j2 = json::from_cbor(vec2); + + // deserializations must match + CHECK(j1 == j2); + } + catch (const std::invalid_argument&) + { + // parsing a CBOR serialization must not fail + CHECK(false); + } + } + catch (const std::invalid_argument&) + { + // parse errors are ok, because input may be random bytes + } + catch (const std::out_of_range&) + { + // parse errors are ok, because input may be random bytes + } + catch (const std::domain_error&) + { + // parse errors are ok, because input may be random bytes + } + } + } +} + TEST_CASE("CBOR roundtrips", "[hide]") { SECTION("input from flynn") From 888f5b9f60591579f72339dc653e614562eb6e31 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 28 Dec 2016 12:18:48 +0100 Subject: [PATCH 47/71] :truck: renamed test files to allow windows build --- ...c:000223+000677,op:splice,rep:2 => test01} | 0 ...ig:06,src:000787,op:havoc,rep:8 => test02} | Bin ...g:06,src:000833,op:havoc,rep:32 => test03} | Bin ...g:06,src:000838,op:havoc,rep:64 => test04} | Bin ...:000846+001064,op:splice,rep:16 => test05} | Bin ...ig:06,src:000848,op:flip1,pos:0 => test06} | Bin ...g:06,src:001435,op:havoc,rep:32 => test07} | Bin ...ig:06,src:001436,op:havoc,rep:4 => test08} | Bin ...c:000864+000903,op:splice,rep:2 => test09} | Bin ...:001310+001138,op:splice,rep:32 => test10} | 0 ...:001330+000569,op:splice,rep:64 => test11} | Bin ...g:06,src:001413,op:havoc,rep:32 => test12} | Bin ...ig:06,src:001447,op:havoc,rep:4 => test13} | Bin ...c:001465+000325,op:splice,rep:4 => test14} | Bin ...ig:06,src:000539,op:havoc,rep:8 => test15} | Bin ...:06,src:001445,op:havoc,rep:128 => test16} | Bin ...g:06,src:001301,op:havoc,rep:16 => test17} | Bin ...c:001317+000850,op:splice,rep:8 => test18} | Bin ...:06,src:001382,op:havoc,rep:128 => test19} | Bin ...c:001413+001036,op:splice,rep:4 => test20} | Bin ...:000846+000155,op:splice,rep:16 => test21} | Bin test/src/unit-cbor.cpp | 42 +++++++++--------- 22 files changed, 21 insertions(+), 21 deletions(-) rename test/data/cbor_regression/{id:000000,sig:06,src:000223+000677,op:splice,rep:2 => test01} (100%) rename test/data/cbor_regression/{id:000000,sig:06,src:000787,op:havoc,rep:8 => test02} (100%) rename test/data/cbor_regression/{id:000000,sig:06,src:000833,op:havoc,rep:32 => test03} (100%) rename test/data/cbor_regression/{id:000000,sig:06,src:000838,op:havoc,rep:64 => test04} (100%) rename test/data/cbor_regression/{id:000000,sig:06,src:000846+001064,op:splice,rep:16 => test05} (100%) rename test/data/cbor_regression/{id:000000,sig:06,src:000848,op:flip1,pos:0 => test06} (100%) rename test/data/cbor_regression/{id:000000,sig:06,src:001435,op:havoc,rep:32 => test07} (100%) rename test/data/cbor_regression/{id:000000,sig:06,src:001436,op:havoc,rep:4 => test08} (100%) rename test/data/cbor_regression/{id:000001,sig:06,src:000864+000903,op:splice,rep:2 => test09} (100%) rename test/data/cbor_regression/{id:000001,sig:06,src:001310+001138,op:splice,rep:32 => test10} (100%) rename test/data/cbor_regression/{id:000001,sig:06,src:001330+000569,op:splice,rep:64 => test11} (100%) rename test/data/cbor_regression/{id:000001,sig:06,src:001413,op:havoc,rep:32 => test12} (100%) rename test/data/cbor_regression/{id:000001,sig:06,src:001447,op:havoc,rep:4 => test13} (100%) rename test/data/cbor_regression/{id:000001,sig:06,src:001465+000325,op:splice,rep:4 => test14} (100%) rename test/data/cbor_regression/{id:000002,sig:06,src:000539,op:havoc,rep:8 => test15} (100%) rename test/data/cbor_regression/{id:000004,sig:06,src:001445,op:havoc,rep:128 => test16} (100%) rename test/data/cbor_regression/{id:000002,sig:06,src:001301,op:havoc,rep:16 => test17} (100%) rename test/data/cbor_regression/{id:000002,sig:06,src:001317+000850,op:splice,rep:8 => test18} (100%) rename test/data/cbor_regression/{id:000002,sig:06,src:001382,op:havoc,rep:128 => test19} (100%) rename test/data/cbor_regression/{id:000002,sig:06,src:001413+001036,op:splice,rep:4 => test20} (100%) rename test/data/cbor_regression/{id:000003,sig:06,src:000846+000155,op:splice,rep:16 => test21} (100%) diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2 b/test/data/cbor_regression/test01 similarity index 100% rename from test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2 rename to test/data/cbor_regression/test01 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8 b/test/data/cbor_regression/test02 similarity index 100% rename from test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8 rename to test/data/cbor_regression/test02 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32 b/test/data/cbor_regression/test03 similarity index 100% rename from test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32 rename to test/data/cbor_regression/test03 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64 b/test/data/cbor_regression/test04 similarity index 100% rename from test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64 rename to test/data/cbor_regression/test04 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16 b/test/data/cbor_regression/test05 similarity index 100% rename from test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16 rename to test/data/cbor_regression/test05 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0 b/test/data/cbor_regression/test06 similarity index 100% rename from test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0 rename to test/data/cbor_regression/test06 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32 b/test/data/cbor_regression/test07 similarity index 100% rename from test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32 rename to test/data/cbor_regression/test07 diff --git a/test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4 b/test/data/cbor_regression/test08 similarity index 100% rename from test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4 rename to test/data/cbor_regression/test08 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2 b/test/data/cbor_regression/test09 similarity index 100% rename from test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2 rename to test/data/cbor_regression/test09 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32 b/test/data/cbor_regression/test10 similarity index 100% rename from test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32 rename to test/data/cbor_regression/test10 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64 b/test/data/cbor_regression/test11 similarity index 100% rename from test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64 rename to test/data/cbor_regression/test11 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32 b/test/data/cbor_regression/test12 similarity index 100% rename from test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32 rename to test/data/cbor_regression/test12 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4 b/test/data/cbor_regression/test13 similarity index 100% rename from test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4 rename to test/data/cbor_regression/test13 diff --git a/test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4 b/test/data/cbor_regression/test14 similarity index 100% rename from test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4 rename to test/data/cbor_regression/test14 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8 b/test/data/cbor_regression/test15 similarity index 100% rename from test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8 rename to test/data/cbor_regression/test15 diff --git a/test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128 b/test/data/cbor_regression/test16 similarity index 100% rename from test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128 rename to test/data/cbor_regression/test16 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16 b/test/data/cbor_regression/test17 similarity index 100% rename from test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16 rename to test/data/cbor_regression/test17 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8 b/test/data/cbor_regression/test18 similarity index 100% rename from test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8 rename to test/data/cbor_regression/test18 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128 b/test/data/cbor_regression/test19 similarity index 100% rename from test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128 rename to test/data/cbor_regression/test19 diff --git a/test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4 b/test/data/cbor_regression/test20 similarity index 100% rename from test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4 rename to test/data/cbor_regression/test20 diff --git a/test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16 b/test/data/cbor_regression/test21 similarity index 100% rename from test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16 rename to test/data/cbor_regression/test21 diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 5769ac98..9c41dc2f 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1197,27 +1197,27 @@ TEST_CASE("CBOR regressions") */ for (std::string filename : { - "test/data/cbor_regression/id:000000,sig:06,src:000223+000677,op:splice,rep:2", - "test/data/cbor_regression/id:000000,sig:06,src:000787,op:havoc,rep:8", - "test/data/cbor_regression/id:000000,sig:06,src:000833,op:havoc,rep:32", - "test/data/cbor_regression/id:000000,sig:06,src:000838,op:havoc,rep:64", - "test/data/cbor_regression/id:000000,sig:06,src:000846+001064,op:splice,rep:16", - "test/data/cbor_regression/id:000000,sig:06,src:000848,op:flip1,pos:0", - "test/data/cbor_regression/id:000000,sig:06,src:001435,op:havoc,rep:32", - "test/data/cbor_regression/id:000000,sig:06,src:001436,op:havoc,rep:4v", - "test/data/cbor_regression/id:000001,sig:06,src:000864+000903,op:splice,rep:2", - "test/data/cbor_regression/id:000001,sig:06,src:001310+001138,op:splice,rep:32", - "test/data/cbor_regression/id:000001,sig:06,src:001330+000569,op:splice,rep:64", - "test/data/cbor_regression/id:000001,sig:06,src:001413,op:havoc,rep:32", - "test/data/cbor_regression/id:000001,sig:06,src:001447,op:havoc,rep:4", - "test/data/cbor_regression/id:000001,sig:06,src:001465+000325,op:splice,rep:4", - "test/data/cbor_regression/id:000002,sig:06,src:000539,op:havoc,rep:8", - "test/data/cbor_regression/id:000002,sig:06,src:001301,op:havoc,rep:16", - "test/data/cbor_regression/id:000002,sig:06,src:001317+000850,op:splice,rep:8", - "test/data/cbor_regression/id:000002,sig:06,src:001382,op:havoc,rep:128", - "test/data/cbor_regression/id:000002,sig:06,src:001413+001036,op:splice,rep:4", - "test/data/cbor_regression/id:000003,sig:06,src:000846+000155,op:splice,rep:16", - "test/data/cbor_regression/id:000004,sig:06,src:001445,op:havoc,rep:128" + "test/data/cbor_regression/test01", + "test/data/cbor_regression/test02", + "test/data/cbor_regression/test03", + "test/data/cbor_regression/test04", + "test/data/cbor_regression/test05", + "test/data/cbor_regression/test06", + "test/data/cbor_regression/test07", + "test/data/cbor_regression/test08", + "test/data/cbor_regression/test09", + "test/data/cbor_regression/test10", + "test/data/cbor_regression/test11", + "test/data/cbor_regression/test12", + "test/data/cbor_regression/test13", + "test/data/cbor_regression/test14", + "test/data/cbor_regression/test15", + "test/data/cbor_regression/test16", + "test/data/cbor_regression/test17", + "test/data/cbor_regression/test18", + "test/data/cbor_regression/test19", + "test/data/cbor_regression/test20", + "test/data/cbor_regression/test21" }) { CAPTURE(filename); From 8381cd6020c57db59cf359ba4384424b93e51018 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 28 Dec 2016 14:19:08 +0100 Subject: [PATCH 48/71] :ambulance: removed unsafe call to strerror #403 --- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 67d05cf2..4515ca67 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9077,7 +9077,7 @@ class basic_json // immediately abort if stream is erroneous if (s.fail()) { - throw std::invalid_argument("stream error: " + std::string(strerror(errno))); + throw std::invalid_argument("stream error"); } // fill buffer diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index cbd8b220..6d649db3 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -9077,7 +9077,7 @@ class basic_json // immediately abort if stream is erroneous if (s.fail()) { - throw std::invalid_argument("stream error: " + std::string(strerror(errno))); + throw std::invalid_argument("stream error"); } // fill buffer From 871cebaf84d4f896bc730a92937f8d02e09b0023 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 29 Dec 2016 15:39:16 +0100 Subject: [PATCH 49/71] :ambulance: fix for #405 --- src/json.hpp | 6 ++++++ src/json.hpp.re2c | 6 ++++++ test/src/unit-regression.cpp | 7 +++++++ 3 files changed, 19 insertions(+) diff --git a/src/json.hpp b/src/json.hpp index 4515ca67..76824cf8 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6871,6 +6871,12 @@ class basic_json { throw std::out_of_range("len+offset out of range"); } + + // last case: reading past the end of the vector + if (len + offset > size) + { + throw std::out_of_range("len+offset out of range"); + } } /*! diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 6d649db3..10bfaf57 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6871,6 +6871,12 @@ class basic_json { throw std::out_of_range("len+offset out of range"); } + + // last case: reading past the end of the vector + if (len + offset > size) + { + throw std::out_of_range("len+offset out of range"); + } } /*! diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 1e720ddb..033041ab 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -540,4 +540,11 @@ TEST_CASE("regression tests") CHECK(j.is_number_float()); CHECK(j.dump() == "1.66020696663386e+20"); } + + SECTION("issue #405 - Heap-buffer-overflow (OSS-Fuzz issue 342)") + { + // original test case + std::vector<uint8_t> vec {0x65, 0xf5, 0x0a, 0x48, 0x21}; + CHECK_THROWS_AS(json::from_cbor(vec), std::out_of_range); + } } From 383a29a924af973e4cf9d5d2054a60f7d718f0d3 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 29 Dec 2016 16:14:15 +0100 Subject: [PATCH 50/71] :ambulance: fix for #407 --- src/json.hpp | 5 +++++ src/json.hpp.re2c | 5 +++++ test/src/unit-regression.cpp | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/src/json.hpp b/src/json.hpp index 76824cf8..aab3b34f 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6981,6 +6981,7 @@ class basic_json case 0xca: // float 32 { // copy bytes in reverse order into the double variable + check_length(v.size(), sizeof(float), 1); float res; for (size_t byte = 0; byte < sizeof(float); ++byte) { @@ -6993,6 +6994,7 @@ class basic_json case 0xcb: // float 64 { // copy bytes in reverse order into the double variable + check_length(v.size(), sizeof(double), 1); double res; for (size_t byte = 0; byte < sizeof(double); ++byte) { @@ -7558,6 +7560,7 @@ class basic_json case 0xf9: // Half-Precision Float (two-byte IEEE 754) { + check_length(v.size(), 2, 1); idx += 2; // skip two content bytes // code from RFC 7049, Appendix D, Figure 3: @@ -7589,6 +7592,7 @@ class basic_json case 0xfa: // Single-Precision Float (four-byte IEEE 754) { // copy bytes in reverse order into the float variable + check_length(v.size(), sizeof(float), 1); float res; for (size_t byte = 0; byte < sizeof(float); ++byte) { @@ -7600,6 +7604,7 @@ class basic_json case 0xfb: // Double-Precision Float (eight-byte IEEE 754) { + check_length(v.size(), sizeof(double), 1); // copy bytes in reverse order into the double variable double res; for (size_t byte = 0; byte < sizeof(double); ++byte) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 10bfaf57..7b6b7ec4 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6981,6 +6981,7 @@ class basic_json case 0xca: // float 32 { // copy bytes in reverse order into the double variable + check_length(v.size(), sizeof(float), 1); float res; for (size_t byte = 0; byte < sizeof(float); ++byte) { @@ -6993,6 +6994,7 @@ class basic_json case 0xcb: // float 64 { // copy bytes in reverse order into the double variable + check_length(v.size(), sizeof(double), 1); double res; for (size_t byte = 0; byte < sizeof(double); ++byte) { @@ -7558,6 +7560,7 @@ class basic_json case 0xf9: // Half-Precision Float (two-byte IEEE 754) { + check_length(v.size(), 2, 1); idx += 2; // skip two content bytes // code from RFC 7049, Appendix D, Figure 3: @@ -7589,6 +7592,7 @@ class basic_json case 0xfa: // Single-Precision Float (four-byte IEEE 754) { // copy bytes in reverse order into the float variable + check_length(v.size(), sizeof(float), 1); float res; for (size_t byte = 0; byte < sizeof(float); ++byte) { @@ -7600,6 +7604,7 @@ class basic_json case 0xfb: // Double-Precision Float (eight-byte IEEE 754) { + check_length(v.size(), sizeof(double), 1); // copy bytes in reverse order into the double variable double res; for (size_t byte = 0; byte < sizeof(double); ++byte) diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 033041ab..6123352d 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -547,4 +547,27 @@ TEST_CASE("regression tests") std::vector<uint8_t> vec {0x65, 0xf5, 0x0a, 0x48, 0x21}; CHECK_THROWS_AS(json::from_cbor(vec), std::out_of_range); } + + SECTION("issue #407 - Heap-buffer-overflow (OSS-Fuzz issue 343)") + { + // original test case: incomplete float64 + std::vector<uint8_t> vec1 {0xcb, 0x8f, 0x0a}; + CHECK_THROWS_AS(json::from_msgpack(vec1), std::out_of_range); + + // related test case: incomplete float32 + std::vector<uint8_t> vec2 {0xca, 0x8f, 0x0a}; + CHECK_THROWS_AS(json::from_msgpack(vec2), std::out_of_range); + + // related test case: incomplete Half-Precision Float (CBOR) + std::vector<uint8_t> vec3 {0xf9, 0x8f}; + CHECK_THROWS_AS(json::from_cbor(vec3), std::out_of_range); + + // related test case: incomplete Single-Precision Float (CBOR) + std::vector<uint8_t> vec4 {0xfa, 0x8f, 0x0a}; + CHECK_THROWS_AS(json::from_cbor(vec4), std::out_of_range); + + // related test case: incomplete Double-Precision Float (CBOR) + std::vector<uint8_t> vec5 {0xfb, 0x8f, 0x0a}; + CHECK_THROWS_AS(json::from_cbor(vec5), std::out_of_range); + } } From f0edab2363ae7dd50ee04bfacdb56f47ed6e7fb7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Thu, 29 Dec 2016 17:00:02 +0100 Subject: [PATCH 51/71] :ambulance: fix for #408 --- src/json.hpp | 37 ++++++--------------------------- src/json.hpp.re2c | 37 ++++++--------------------------- test/src/unit-regression.cpp | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 62 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index aab3b34f..f8d948f1 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6879,27 +6879,6 @@ class basic_json } } - /*! - @brief checks if a given length does not exceed the size of a given vector - - To secure the access to the byte vector during CBOR/MessagePack - deserialization, bytes are copied from the vector into buffers. This - function checks if the number of bytes to copy (@a len) does not exceed the - size of the given vector @a vec. - - @param[in] vec byte vector - @param[in] len length - - @throws out_of_range if `len > v.size()` - */ - static void check_length(const std::vector<uint8_t>& vec, const size_t& len) - { - if (len > vec.size()) - { - throw std::out_of_range("len out of range"); - } - } - /*! @brief create a JSON value from a given MessagePack vector @@ -6916,6 +6895,9 @@ class basic_json */ static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx) { + // make sure reading 1 byte is safe + check_length(v.size(), 1, idx); + // store and increment index const size_t current_idx = idx++; @@ -7153,6 +7135,9 @@ class basic_json */ static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx) { + // make sure reading 1 byte is safe + check_length(v.size(), 1, idx); + // store and increment index const size_t current_idx = idx++; @@ -7674,11 +7659,6 @@ class basic_json */ static basic_json from_msgpack(const std::vector<uint8_t>& v) { - if (v.empty()) - { - throw std::invalid_argument("empty vector"); - } - size_t i = 0; return from_msgpack_internal(v, i); } @@ -7736,11 +7716,6 @@ class basic_json */ static basic_json from_cbor(const std::vector<uint8_t>& v) { - if (v.empty()) - { - throw std::invalid_argument("empty vector"); - } - size_t i = 0; return from_cbor_internal(v, i); } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 7b6b7ec4..2faf3858 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6879,27 +6879,6 @@ class basic_json } } - /*! - @brief checks if a given length does not exceed the size of a given vector - - To secure the access to the byte vector during CBOR/MessagePack - deserialization, bytes are copied from the vector into buffers. This - function checks if the number of bytes to copy (@a len) does not exceed the - size of the given vector @a vec. - - @param[in] vec byte vector - @param[in] len length - - @throws out_of_range if `len > v.size()` - */ - static void check_length(const std::vector<uint8_t>& vec, const size_t& len) - { - if (len > vec.size()) - { - throw std::out_of_range("len out of range"); - } - } - /*! @brief create a JSON value from a given MessagePack vector @@ -6916,6 +6895,9 @@ class basic_json */ static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx) { + // make sure reading 1 byte is safe + check_length(v.size(), 1, idx); + // store and increment index const size_t current_idx = idx++; @@ -7153,6 +7135,9 @@ class basic_json */ static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx) { + // make sure reading 1 byte is safe + check_length(v.size(), 1, idx); + // store and increment index const size_t current_idx = idx++; @@ -7674,11 +7659,6 @@ class basic_json */ static basic_json from_msgpack(const std::vector<uint8_t>& v) { - if (v.empty()) - { - throw std::invalid_argument("empty vector"); - } - size_t i = 0; return from_msgpack_internal(v, i); } @@ -7736,11 +7716,6 @@ class basic_json */ static basic_json from_cbor(const std::vector<uint8_t>& v) { - if (v.empty()) - { - throw std::invalid_argument("empty vector"); - } - size_t i = 0; return from_cbor_internal(v, i); } diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 6123352d..421a386c 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -570,4 +570,44 @@ TEST_CASE("regression tests") std::vector<uint8_t> vec5 {0xfb, 0x8f, 0x0a}; CHECK_THROWS_AS(json::from_cbor(vec5), std::out_of_range); } + + SECTION("issue #408 - Heap-buffer-overflow (OSS-Fuzz issue 344)") + { + // original test case + std::vector<uint8_t> vec1 {0x87}; + CHECK_THROWS_AS(json::from_msgpack(vec1), std::out_of_range); + + // more test cases for MessagePack + for (uint8_t b : + { + 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, // fixmap + 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, // fixarray + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, // fixstr + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf + }) + { + std::vector<uint8_t> vec(1, b); + CHECK_THROWS_AS(json::from_msgpack(vec), std::out_of_range); + } + + // more test cases for CBOR + for (uint8_t b : + { + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // UTF-8 string + 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, // array + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 // map + }) + { + std::vector<uint8_t> vec(1, b); + CHECK_THROWS_AS(json::from_cbor(vec), std::out_of_range); + } + + // special case: empty input + std::vector<uint8_t> vec2; + CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range); + CHECK_THROWS_AS(json::from_msgpack(vec2), std::out_of_range); + } } From d7029c37aad0e93033242123e7a7a05a1c76bed4 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Fri, 30 Dec 2016 13:04:33 +0100 Subject: [PATCH 52/71] :white_check_mark: improved test coverage --- test/src/unit-cbor.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 9c41dc2f..49a54999 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -28,6 +28,7 @@ SOFTWARE. #include "catch.hpp" +#define private public #include "json.hpp" using nlohmann::json; @@ -1262,6 +1263,12 @@ TEST_CASE("CBOR regressions") } } } + + SECTION("improve code coverage") + { + // exotic edge case + CHECK_THROWS_AS(json::check_length(0xffffffffffffffff, 0xfffffffffffffff0, 0xff), std::out_of_range); + } } TEST_CASE("CBOR roundtrips", "[hide]") From 010ea126f3662c76e2d484e9710be2b8fcd53785 Mon Sep 17 00:00:00 2001 From: Daniel Cohen <daniel.cohen599@gmail.com> Date: Sun, 25 Dec 2016 14:04:04 +0200 Subject: [PATCH 53/71] going to try clang_sanitize with libstdc++ with g++-6 implementation Conflicts: .travis.yml Makefile --- .travis.yml | 22 ++++++++++++++-------- Makefile | 3 ++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 006647ed..6bf2297e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,14 +42,20 @@ matrix: - make check TEST_PREFIX="valgrind --error-exitcode=1 --leak-check=full " TEST_PATTERN="" # cLang sanitizer - - #- os: linux - # env: - # - LLVM_VERSION=3.8.1 - # - SPECIAL=sanitizer - # compiler: clang - # before_script: - # - make clang_sanitize + # note: sadly clang's libc++ has errors when running with sanitize, + # so we use clang with gcc's libstdc++ which doesn't give those error. + # that's why we need to install g++-6 to get the lastest version + - os: linux + env: + - LLVM_VERSION=3.8.1 + - SPECIAL=sanitizer + addons: + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: g++-6 + compiler: clang + before_script: + - make clang_sanitize # cppcheck diff --git a/Makefile b/Makefile index e2c120db..c16d9d9b 100644 --- a/Makefile +++ b/Makefile @@ -92,8 +92,9 @@ fuzzing-stop: cppcheck: cppcheck --enable=warning --inconclusive --force --std=c++11 src/json.hpp --error-exitcode=1 +# run clang sanitize (we are overrding the CXXFLAGS provided by travis in order to use gcc's libstdc++) clang_sanitize: clean - CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE) + CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE) check -C test ########################################################################## From ff3221a37573e3313d52d46fd3b94ec658ff66e8 Mon Sep 17 00:00:00 2001 From: Daniel Cohen <daniel.cohen599@gmail.com> Date: Sun, 25 Dec 2016 22:52:37 +0200 Subject: [PATCH 54/71] #394 fixed memory leak in unit-allocator, found by clang's fsanitize --- test/src/unit-allocator.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index 25fd3349..c439c1c3 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -111,6 +111,16 @@ struct my_allocator : std::allocator<T> } }; +// allows deletion of raw pointer, usually hold by json_value +template<class T> +void my_allocator_clean_up(T* p) +{ + assert(p != nullptr); + my_allocator<T> alloc; + alloc.destroy(p); + alloc.deallocate(p, 1); +} + TEST_CASE("controlled bad_alloc") { // create JSON type using the throwing allocator @@ -131,7 +141,8 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; auto t = my_json::value_t::object; - CHECK_NOTHROW(my_json::json_value j(t)); + auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.object); }; + CHECK_NOTHROW(my_json::json_value j(t); clean_up(j)); next_construct_fails = true; CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc); next_construct_fails = false; @@ -140,7 +151,8 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; auto t = my_json::value_t::array; - CHECK_NOTHROW(my_json::json_value j(t)); + auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.array); }; + CHECK_NOTHROW(my_json::json_value j(t); clean_up(j)); next_construct_fails = true; CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc); next_construct_fails = false; @@ -149,7 +161,8 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; auto t = my_json::value_t::string; - CHECK_NOTHROW(my_json::json_value j(t)); + auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.string); }; + CHECK_NOTHROW(my_json::json_value j(t); clean_up(j)); next_construct_fails = true; CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc); next_construct_fails = false; @@ -160,7 +173,8 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; my_json::string_t v("foo"); - CHECK_NOTHROW(my_json::json_value j(v)); + auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.string); }; + CHECK_NOTHROW(my_json::json_value j(v); clean_up(j)); next_construct_fails = true; CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc); next_construct_fails = false; From cf9bf2d9136a9d1c2131f83aa493bb03f36849ab Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 1 Jan 2017 15:28:01 +0100 Subject: [PATCH 55/71] :ambulance: fix for #411 and #412 --- src/json.hpp | 11 +++----- src/json.hpp.re2c | 11 +++----- test/src/unit-regression.cpp | 53 ++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index f8d948f1..5dc8e67c 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -7135,13 +7135,10 @@ class basic_json */ static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx) { - // make sure reading 1 byte is safe - check_length(v.size(), 1, idx); - // store and increment index const size_t current_idx = idx++; - switch (v[current_idx]) + switch (v.at(current_idx)) { // Integer 0x00..0x17 (0..23) case 0x00: @@ -7322,7 +7319,7 @@ class basic_json case 0x7f: // UTF-8 string (indefinite length) { std::string result; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { string_t s = from_cbor_internal(v, idx); result += s; @@ -7418,7 +7415,7 @@ class basic_json case 0x9f: // array (indefinite length) { basic_json result = value_t::array; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { result.push_back(from_cbor_internal(v, idx)); } @@ -7518,7 +7515,7 @@ class basic_json case 0xbf: // map (indefinite length) { basic_json result = value_t::object; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 2faf3858..49bccb02 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -7135,13 +7135,10 @@ class basic_json */ static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx) { - // make sure reading 1 byte is safe - check_length(v.size(), 1, idx); - // store and increment index const size_t current_idx = idx++; - switch (v[current_idx]) + switch (v.at(current_idx)) { // Integer 0x00..0x17 (0..23) case 0x00: @@ -7322,7 +7319,7 @@ class basic_json case 0x7f: // UTF-8 string (indefinite length) { std::string result; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { string_t s = from_cbor_internal(v, idx); result += s; @@ -7418,7 +7415,7 @@ class basic_json case 0x9f: // array (indefinite length) { basic_json result = value_t::array; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { result.push_back(from_cbor_internal(v, idx)); } @@ -7518,7 +7515,7 @@ class basic_json case 0xbf: // map (indefinite length) { basic_json result = value_t::object; - while (v[idx] != 0xff) + while (v.at(idx) != 0xff) { std::string key = from_cbor_internal(v, idx); result[key] = from_cbor_internal(v, idx); diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 421a386c..89b27e0e 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -610,4 +610,57 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range); CHECK_THROWS_AS(json::from_msgpack(vec2), std::out_of_range); } + + SECTION("issue #411 - Heap-buffer-overflow (OSS-Fuzz issue 366)") + { + // original test case: empty UTF-8 string (indefinite length) + std::vector<uint8_t> vec1 {0x7f}; + CHECK_THROWS_AS(json::from_cbor(vec1), std::out_of_range); + + // related test case: empty array (indefinite length) + std::vector<uint8_t> vec2 {0x9f}; + CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range); + + // related test case: empty map (indefinite length) + std::vector<uint8_t> vec3 {0xbf}; + CHECK_THROWS_AS(json::from_cbor(vec3), std::out_of_range); + } + + SECTION("issue #412 - Heap-buffer-overflow (OSS-Fuzz issue 367)") + { + // original test case + std::vector<uint8_t> vec + { + 0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00, + 0x60, 0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xa0, 0x9f, + 0x9f, 0x97, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60 + }; + CHECK_THROWS_AS(json::from_cbor(vec), std::out_of_range); + + // related test case: nonempty UTF-8 string (indefinite length) + std::vector<uint8_t> vec1 {0x7f, 0x61, 0x61}; + CHECK_THROWS_AS(json::from_cbor(vec1), std::out_of_range); + + // related test case: nonempty array (indefinite length) + std::vector<uint8_t> vec2 {0x9f, 0x01}; + CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range); + + // related test case: nonempty map (indefinite length) + std::vector<uint8_t> vec3 {0xbf, 0x61, 0x61, 0x01}; + CHECK_THROWS_AS(json::from_cbor(vec3), std::out_of_range); + } } From ab7d55e7ae7c9fab666912876aaa9d9e20d1b618 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 1 Jan 2017 19:38:54 +0100 Subject: [PATCH 56/71] :construction_worker: removed failing test suites --- .doozer.json | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/.doozer.json b/.doozer.json index 589dccc3..7dbaa5d2 100644 --- a/.doozer.json +++ b/.doozer.json @@ -1,30 +1,5 @@ { "targets": { - "jessie-i386": { - "buildenv": "jessie-i386", - "builddeps": ["build-essential", "cmake", "clang"], - "buildcmd": ["mkdir cm", "cd cm", "CXX=clang++ cmake ..", "cmake --build .", "ctest --output-on-failure"] - }, - "precise-i386": { - "buildenv": "precise-i386", - "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] - }, - "precise-amd64": { - "buildenv": "precise-amd64", - "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] - }, - "trusty-i386": { - "buildenv": "trusty-i386", - "builddeps": ["build-essential", "cmake", "clang"], - "buildcmd": ["make check CXX=clang++"] - }, - "trusty-amd64": { - "buildenv": "trusty-amd64", - "builddeps": ["build-essential", "cmake", "clang"], - "buildcmd": ["make check CXX=clang++"] - }, "xenial-i386": { "buildenv": "xenial-i386", "builddeps": ["build-essential", "cmake"], @@ -40,11 +15,6 @@ "builddeps": ["cmake", "make", "clang"], "buildcmd": ["mkdir cm", "cd cm", "CXX=clang++ cmake ..", "cmake --build .", "ctest --output-on-failure"] }, - "centos7-x86_64": { - "buildenv": "centos7-x86_64", - "builddeps": ["build-essential", "cmake"], - "buildcmd": ["mkdir cm", "cd cm", "cmake ..", "cmake --build .", "ctest --output-on-failure"] - }, "osx": { "buildenv": "osx", "builddeps": ["build-essential"], From db33629990c0125bde0fb61e894e00496e1e22b0 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 1 Jan 2017 21:34:58 +0100 Subject: [PATCH 57/71] :lipstick: cleanup after #410 --- Makefile | 2 +- README.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c16d9d9b..56cbdb0c 100644 --- a/Makefile +++ b/Makefile @@ -94,7 +94,7 @@ cppcheck: # run clang sanitize (we are overrding the CXXFLAGS provided by travis in order to use gcc's libstdc++) clang_sanitize: clean - CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE) check -C test + CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE) ########################################################################## diff --git a/README.md b/README.md index 16c7eabf..06dca7ff 100644 --- a/README.md +++ b/README.md @@ -586,6 +586,7 @@ I deeply appreciate the help of the following people. - [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning. - [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check. - [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one. +- [Daniel599](https://github.com/Daniel599) helped to get Travis execute the tests with Clang's sanitizers. Thanks a lot for helping out! From a3063c24194df831cc95b6429a648ea3a6739fcf Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Sun, 1 Jan 2017 21:51:36 +0100 Subject: [PATCH 58/71] :construction: added target to build all fuzzers --- .gitignore | 6 ++++++ test/Makefile | 2 ++ 2 files changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index eedc9641..6e15abc4 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,9 @@ test/test-* .svn test/thirdparty/Fuzzer/libFuzzer.a + +test/parse_afl_fuzzer + +test/parse_cbor_fuzzer + +test/parse_msgpack_fuzzer diff --git a/test/Makefile b/test/Makefile index 556ab0d7..68520bd3 100644 --- a/test/Makefile +++ b/test/Makefile @@ -84,6 +84,8 @@ check: $(TESTCASES) # fuzzer ############################################################################## +fuzzers: parse_afl_fuzzer parse_cbor_fuzzer parse_msgpack_fuzzer + parse_afl_fuzzer: $(CXX) $(CXXFLAGS) $(CPPFLAGS) src/fuzzer-driver_afl.cpp src/fuzzer-parse_json.cpp -o $@ From d1735172127c37bfee7a816d96d34647cfff6494 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Mon, 2 Jan 2017 09:21:26 +0100 Subject: [PATCH 59/71] :lipstick: clean up --- src/json.hpp | 9 +++++++++ src/json.hpp.re2c | 9 +++++++++ test/src/unit-allocator.cpp | 20 ++++++++++++++++---- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 5dc8e67c..afa35baa 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -873,8 +873,17 @@ class basic_json break; } + case value_t::null: + { + break; + } + default: { + if (t == value_t::null) + { + throw std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21"); // LCOV_EXCL_LINE + } break; } } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 49bccb02..db0b4c88 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -873,8 +873,17 @@ class basic_json break; } + case value_t::null: + { + break; + } + default: { + if (t == value_t::null) + { + throw std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21"); // LCOV_EXCL_LINE + } break; } } diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index c439c1c3..04f6ac9d 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -141,7 +141,10 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; auto t = my_json::value_t::object; - auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.object); }; + auto clean_up = [](my_json::json_value & j) + { + my_allocator_clean_up(j.object); + }; CHECK_NOTHROW(my_json::json_value j(t); clean_up(j)); next_construct_fails = true; CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc); @@ -151,7 +154,10 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; auto t = my_json::value_t::array; - auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.array); }; + auto clean_up = [](my_json::json_value & j) + { + my_allocator_clean_up(j.array); + }; CHECK_NOTHROW(my_json::json_value j(t); clean_up(j)); next_construct_fails = true; CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc); @@ -161,7 +167,10 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; auto t = my_json::value_t::string; - auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.string); }; + auto clean_up = [](my_json::json_value & j) + { + my_allocator_clean_up(j.string); + }; CHECK_NOTHROW(my_json::json_value j(t); clean_up(j)); next_construct_fails = true; CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc); @@ -173,7 +182,10 @@ TEST_CASE("controlled bad_alloc") { next_construct_fails = false; my_json::string_t v("foo"); - auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.string); }; + auto clean_up = [](my_json::json_value & j) + { + my_allocator_clean_up(j.string); + }; CHECK_NOTHROW(my_json::json_value j(v); clean_up(j)); next_construct_fails = true; CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc); From 60b3703c62bdc3740ca7564bd8c28abb5337a2b4 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Mon, 2 Jan 2017 09:35:57 +0100 Subject: [PATCH 60/71] :bookmark: version bump to 2.0.10 --- CMakeLists.txt | 2 +- doc/Doxyfile | 2 +- doc/index.md | 2 +- src/json.hpp | 4 ++-- src/json.hpp.re2c | 4 ++-- test/src/fuzzer-driver_afl.cpp | 2 +- test/src/fuzzer-parse_cbor.cpp | 2 +- test/src/fuzzer-parse_json.cpp | 2 +- test/src/fuzzer-parse_msgpack.cpp | 2 +- test/src/unit-algorithms.cpp | 2 +- test/src/unit-allocator.cpp | 2 +- test/src/unit-capacity.cpp | 2 +- test/src/unit-cbor.cpp | 2 +- test/src/unit-class_const_iterator.cpp | 2 +- test/src/unit-class_iterator.cpp | 2 +- test/src/unit-class_lexer.cpp | 2 +- test/src/unit-class_parser.cpp | 2 +- test/src/unit-comparison.cpp | 2 +- test/src/unit-concepts.cpp | 2 +- test/src/unit-constructor1.cpp | 2 +- test/src/unit-constructor2.cpp | 2 +- test/src/unit-convenience.cpp | 2 +- test/src/unit-conversions.cpp | 2 +- test/src/unit-deserialization.cpp | 2 +- test/src/unit-element_access1.cpp | 2 +- test/src/unit-element_access2.cpp | 2 +- test/src/unit-inspection.cpp | 2 +- test/src/unit-iterator_wrapper.cpp | 2 +- test/src/unit-iterators1.cpp | 2 +- test/src/unit-iterators2.cpp | 2 +- test/src/unit-json_patch.cpp | 2 +- test/src/unit-json_pointer.cpp | 2 +- test/src/unit-modifiers.cpp | 2 +- test/src/unit-msgpack.cpp | 2 +- test/src/unit-pointer_access.cpp | 2 +- test/src/unit-readme.cpp | 2 +- test/src/unit-reference_access.cpp | 2 +- test/src/unit-regression.cpp | 2 +- test/src/unit-serialization.cpp | 2 +- test/src/unit-testsuites.cpp | 2 +- test/src/unit-unicode.cpp | 2 +- test/src/unit.cpp | 2 +- 42 files changed, 44 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80770367..9f9931c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.0) # define the project -project(nlohmann_json VERSION 2.0.9 LANGUAGES CXX) +project(nlohmann_json VERSION 2.0.10 LANGUAGES CXX) enable_testing() diff --git a/doc/Doxyfile b/doc/Doxyfile index 17c81d8b..5064a0a0 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "JSON for Modern C++" -PROJECT_NUMBER = 2.0.9 +PROJECT_NUMBER = 2.0.10 PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = . diff --git a/doc/index.md b/doc/index.md index 8292fe65..cc5cd793 100644 --- a/doc/index.md +++ b/doc/index.md @@ -277,4 +277,4 @@ The container functions known from STL have been extended to support the differe @author [Niels Lohmann](http://nlohmann.me) @see https://github.com/nlohmann/json to download the source code -@version 2.0.9 +@version 2.0.10 diff --git a/src/json.hpp b/src/json.hpp index afa35baa..471b9ec7 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. @@ -882,7 +882,7 @@ class basic_json { if (t == value_t::null) { - throw std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21"); // LCOV_EXCL_LINE + throw std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.0.10"); // LCOV_EXCL_LINE } break; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index db0b4c88..9a7c2043 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. @@ -882,7 +882,7 @@ class basic_json { if (t == value_t::null) { - throw std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21"); // LCOV_EXCL_LINE + throw std::domain_error("961c151d2e87f2686a955a9be24d316f1362bf21 2.0.10"); // LCOV_EXCL_LINE } break; } diff --git a/test/src/fuzzer-driver_afl.cpp b/test/src/fuzzer-driver_afl.cpp index eddeae41..0c173b45 100644 --- a/test/src/fuzzer-driver_afl.cpp +++ b/test/src/fuzzer-driver_afl.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on diff --git a/test/src/fuzzer-parse_cbor.cpp b/test/src/fuzzer-parse_cbor.cpp index 42ce679c..bba56747 100644 --- a/test/src/fuzzer-parse_cbor.cpp +++ b/test/src/fuzzer-parse_cbor.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/fuzzer-parse_json.cpp b/test/src/fuzzer-parse_json.cpp index 51ac440d..f61df56d 100644 --- a/test/src/fuzzer-parse_json.cpp +++ b/test/src/fuzzer-parse_json.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/fuzzer-parse_msgpack.cpp b/test/src/fuzzer-parse_msgpack.cpp index 992697c2..0355db3b 100644 --- a/test/src/fuzzer-parse_msgpack.cpp +++ b/test/src/fuzzer-parse_msgpack.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp index 31be6556..04704847 100644 --- a/test/src/unit-algorithms.cpp +++ b/test/src/unit-algorithms.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index 04f6ac9d..00eb5b9a 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-capacity.cpp b/test/src/unit-capacity.cpp index 7fc3d49c..4664f1bf 100644 --- a/test/src/unit-capacity.cpp +++ b/test/src/unit-capacity.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 49a54999..d01019d9 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp index 2970b865..2097e830 100644 --- a/test/src/unit-class_const_iterator.cpp +++ b/test/src/unit-class_const_iterator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-class_iterator.cpp b/test/src/unit-class_iterator.cpp index 14c6828b..bd64cbf8 100644 --- a/test/src/unit-class_iterator.cpp +++ b/test/src/unit-class_iterator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp index 6dec3f82..5656942f 100644 --- a/test/src/unit-class_lexer.cpp +++ b/test/src/unit-class_lexer.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 7bf23d50..3e11d80c 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-comparison.cpp b/test/src/unit-comparison.cpp index 73c31abc..81c3066d 100644 --- a/test/src/unit-comparison.cpp +++ b/test/src/unit-comparison.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-concepts.cpp b/test/src/unit-concepts.cpp index dea6b510..cf60b5c1 100644 --- a/test/src/unit-concepts.cpp +++ b/test/src/unit-concepts.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp index 23c0db38..114ae5b3 100644 --- a/test/src/unit-constructor1.cpp +++ b/test/src/unit-constructor1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-constructor2.cpp b/test/src/unit-constructor2.cpp index 0bbd13cf..ae5ba3b7 100644 --- a/test/src/unit-constructor2.cpp +++ b/test/src/unit-constructor2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-convenience.cpp b/test/src/unit-convenience.cpp index 94341be1..1aedea44 100644 --- a/test/src/unit-convenience.cpp +++ b/test/src/unit-convenience.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 72c3bf60..77d476bd 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index 605c596b..f0cf2e15 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp index 0a1715e7..04265244 100644 --- a/test/src/unit-element_access1.cpp +++ b/test/src/unit-element_access1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index 29be17a1..f2758a59 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-inspection.cpp b/test/src/unit-inspection.cpp index 1660c719..1051d2f5 100644 --- a/test/src/unit-inspection.cpp +++ b/test/src/unit-inspection.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-iterator_wrapper.cpp b/test/src/unit-iterator_wrapper.cpp index 96928eb4..784fa77a 100644 --- a/test/src/unit-iterator_wrapper.cpp +++ b/test/src/unit-iterator_wrapper.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-iterators1.cpp b/test/src/unit-iterators1.cpp index 60f7c2fa..bf14435b 100644 --- a/test/src/unit-iterators1.cpp +++ b/test/src/unit-iterators1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp index da0fc937..5c04826d 100644 --- a/test/src/unit-iterators2.cpp +++ b/test/src/unit-iterators2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp index 880bc46d..4983aab2 100644 --- a/test/src/unit-json_patch.cpp +++ b/test/src/unit-json_patch.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index 91d003ab..4268c3c0 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp index 02ffa6a5..2db3f291 100644 --- a/test/src/unit-modifiers.cpp +++ b/test/src/unit-modifiers.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index 46997e27..eab4dcac 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-pointer_access.cpp b/test/src/unit-pointer_access.cpp index e1c9caab..f5d934d3 100644 --- a/test/src/unit-pointer_access.cpp +++ b/test/src/unit-pointer_access.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp index 92b13222..bddcd0d6 100644 --- a/test/src/unit-readme.cpp +++ b/test/src/unit-readme.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-reference_access.cpp b/test/src/unit-reference_access.cpp index 4a8047f8..321907a5 100644 --- a/test/src/unit-reference_access.cpp +++ b/test/src/unit-reference_access.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 89b27e0e..0bfdc91a 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp index 8385a4a4..3375a1c4 100644 --- a/test/src/unit-serialization.cpp +++ b/test/src/unit-serialization.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index 92b6e5aa..dfc75936 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp index 4cb51e21..69f4a9ee 100644 --- a/test/src/unit-unicode.cpp +++ b/test/src/unit-unicode.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. diff --git a/test/src/unit.cpp b/test/src/unit.cpp index 1a278868..e7a7a799 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 2.0.9 +| | |__ | | | | | | version 2.0.10 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. From 6a207900562cededec7189c548c86743c65902cd Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Mon, 2 Jan 2017 09:36:30 +0100 Subject: [PATCH 61/71] :memo: updated test count --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06dca7ff..a0534615 100644 --- a/README.md +++ b/README.md @@ -610,7 +610,7 @@ To compile and run the tests, you need to execute $ make check =============================================================================== -All tests passed (11201893 assertions in 43 test cases) +All tests passed (11202040 assertions in 44 test cases) ``` Alternatively, you can use [CMake](https://cmake.org) and run From 8b46eb8ec0abd05535520fc25e2bdbd3a2c71820 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Mon, 2 Jan 2017 09:40:00 +0100 Subject: [PATCH 62/71] :page_facing_up: it's 2017 already --- LICENSE.MIT | 2 +- doc/index.md | 2 +- src/json.hpp | 2 +- src/json.hpp.re2c | 2 +- test/src/unit-algorithms.cpp | 2 +- test/src/unit-allocator.cpp | 2 +- test/src/unit-capacity.cpp | 2 +- test/src/unit-cbor.cpp | 2 +- test/src/unit-class_const_iterator.cpp | 2 +- test/src/unit-class_iterator.cpp | 2 +- test/src/unit-class_lexer.cpp | 2 +- test/src/unit-class_parser.cpp | 2 +- test/src/unit-comparison.cpp | 2 +- test/src/unit-concepts.cpp | 2 +- test/src/unit-constructor1.cpp | 2 +- test/src/unit-constructor2.cpp | 2 +- test/src/unit-convenience.cpp | 2 +- test/src/unit-conversions.cpp | 2 +- test/src/unit-deserialization.cpp | 2 +- test/src/unit-element_access1.cpp | 2 +- test/src/unit-element_access2.cpp | 2 +- test/src/unit-inspection.cpp | 2 +- test/src/unit-iterator_wrapper.cpp | 2 +- test/src/unit-iterators1.cpp | 2 +- test/src/unit-iterators2.cpp | 2 +- test/src/unit-json_patch.cpp | 2 +- test/src/unit-json_pointer.cpp | 2 +- test/src/unit-modifiers.cpp | 2 +- test/src/unit-msgpack.cpp | 2 +- test/src/unit-pointer_access.cpp | 2 +- test/src/unit-readme.cpp | 2 +- test/src/unit-reference_access.cpp | 2 +- test/src/unit-regression.cpp | 2 +- test/src/unit-serialization.cpp | 2 +- test/src/unit-testsuites.cpp | 2 +- test/src/unit-unicode.cpp | 2 +- test/src/unit.cpp | 2 +- 37 files changed, 37 insertions(+), 37 deletions(-) diff --git a/LICENSE.MIT b/LICENSE.MIT index 79145efa..c4ce40d1 100644 --- a/LICENSE.MIT +++ b/LICENSE.MIT @@ -1,7 +1,7 @@ JSON for Modern C++ is licensed under the MIT License <http://opensource.org/licenses/MIT>: -Copyright (c) 2013-2016 Niels Lohmann +Copyright (c) 2013-2017 Niels Lohmann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/doc/index.md b/doc/index.md index cc5cd793..f7ef3554 100644 --- a/doc/index.md +++ b/doc/index.md @@ -272,7 +272,7 @@ The container functions known from STL have been extended to support the differe </tr> </table> -@copyright Copyright © 2013-2016 Niels Lohmann. The code is licensed under the [MIT License](http://opensource.org/licenses/MIT). +@copyright Copyright © 2013-2017 Niels Lohmann. The code is licensed under the [MIT License](http://opensource.org/licenses/MIT). @author [Niels Lohmann](http://nlohmann.me) @see https://github.com/nlohmann/json to download the source code diff --git a/src/json.hpp b/src/json.hpp index 471b9ec7..9d48e7a6 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 9a7c2043..e1a43b54 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp index 04704847..0905d05e 100644 --- a/test/src/unit-algorithms.cpp +++ b/test/src/unit-algorithms.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index 00eb5b9a..f11d8538 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-capacity.cpp b/test/src/unit-capacity.cpp index 4664f1bf..d3ee33d2 100644 --- a/test/src/unit-capacity.cpp +++ b/test/src/unit-capacity.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index d01019d9..92238b79 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp index 2097e830..13ce7c3f 100644 --- a/test/src/unit-class_const_iterator.cpp +++ b/test/src/unit-class_const_iterator.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-class_iterator.cpp b/test/src/unit-class_iterator.cpp index bd64cbf8..640bc816 100644 --- a/test/src/unit-class_iterator.cpp +++ b/test/src/unit-class_iterator.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp index 5656942f..33ea610a 100644 --- a/test/src/unit-class_lexer.cpp +++ b/test/src/unit-class_lexer.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 3e11d80c..09515042 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-comparison.cpp b/test/src/unit-comparison.cpp index 81c3066d..7f89729e 100644 --- a/test/src/unit-comparison.cpp +++ b/test/src/unit-comparison.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-concepts.cpp b/test/src/unit-concepts.cpp index cf60b5c1..1c04b62b 100644 --- a/test/src/unit-concepts.cpp +++ b/test/src/unit-concepts.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp index 114ae5b3..6bfb4402 100644 --- a/test/src/unit-constructor1.cpp +++ b/test/src/unit-constructor1.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-constructor2.cpp b/test/src/unit-constructor2.cpp index ae5ba3b7..ab1e43cc 100644 --- a/test/src/unit-constructor2.cpp +++ b/test/src/unit-constructor2.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-convenience.cpp b/test/src/unit-convenience.cpp index 1aedea44..cd78f83a 100644 --- a/test/src/unit-convenience.cpp +++ b/test/src/unit-convenience.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 77d476bd..b82127bb 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index f0cf2e15..21e3bb44 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp index 04265244..a596ac21 100644 --- a/test/src/unit-element_access1.cpp +++ b/test/src/unit-element_access1.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index f2758a59..1ba6aa61 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-inspection.cpp b/test/src/unit-inspection.cpp index 1051d2f5..9e114718 100644 --- a/test/src/unit-inspection.cpp +++ b/test/src/unit-inspection.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-iterator_wrapper.cpp b/test/src/unit-iterator_wrapper.cpp index 784fa77a..f4255f99 100644 --- a/test/src/unit-iterator_wrapper.cpp +++ b/test/src/unit-iterator_wrapper.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-iterators1.cpp b/test/src/unit-iterators1.cpp index bf14435b..a6fd2df9 100644 --- a/test/src/unit-iterators1.cpp +++ b/test/src/unit-iterators1.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp index 5c04826d..6f1b6251 100644 --- a/test/src/unit-iterators2.cpp +++ b/test/src/unit-iterators2.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp index 4983aab2..b7987509 100644 --- a/test/src/unit-json_patch.cpp +++ b/test/src/unit-json_patch.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index 4268c3c0..67257943 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp index 2db3f291..3e8d9600 100644 --- a/test/src/unit-modifiers.cpp +++ b/test/src/unit-modifiers.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index eab4dcac..89fa450d 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-pointer_access.cpp b/test/src/unit-pointer_access.cpp index f5d934d3..4771c508 100644 --- a/test/src/unit-pointer_access.cpp +++ b/test/src/unit-pointer_access.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp index bddcd0d6..5c62e850 100644 --- a/test/src/unit-readme.cpp +++ b/test/src/unit-readme.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-reference_access.cpp b/test/src/unit-reference_access.cpp index 321907a5..54db1a86 100644 --- a/test/src/unit-reference_access.cpp +++ b/test/src/unit-reference_access.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 0bfdc91a..401867c2 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp index 3375a1c4..72d9ae6c 100644 --- a/test/src/unit-serialization.cpp +++ b/test/src/unit-serialization.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index dfc75936..a43e1997 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp index 69f4a9ee..0b1c0e5e 100644 --- a/test/src/unit-unicode.cpp +++ b/test/src/unit-unicode.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/test/src/unit.cpp b/test/src/unit.cpp index e7a7a799..096a2973 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -5,7 +5,7 @@ |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License <http://opensource.org/licenses/MIT>. -Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>. +Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 4d3bf433b45d8f445536f51585ad0644611277f7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Mon, 2 Jan 2017 09:56:21 +0100 Subject: [PATCH 63/71] :bookmark: updated ChangeLog --- ChangeLog.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 92545768..ce82d14b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,26 @@ # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [v2.0.10](https://github.com/nlohmann/json/releases/tag/v2.0.10) (2017-01-02) +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.9...v2.0.10) + +- Heap-buffer-overflow \(OSS-Fuzz issue 367\) [\#412](https://github.com/nlohmann/json/issues/412) +- Heap-buffer-overflow \(OSS-Fuzz issue 366\) [\#411](https://github.com/nlohmann/json/issues/411) +- Use-of-uninitialized-value \(OSS-Fuzz issue 347\) [\#409](https://github.com/nlohmann/json/issues/409) +- Heap-buffer-overflow \(OSS-Fuzz issue 344\) [\#408](https://github.com/nlohmann/json/issues/408) +- Heap-buffer-overflow \(OSS-Fuzz issue 343\) [\#407](https://github.com/nlohmann/json/issues/407) +- Heap-buffer-overflow \(OSS-Fuzz issue 342\) [\#405](https://github.com/nlohmann/json/issues/405) +- strerror throwing error in compiler VS2015 [\#403](https://github.com/nlohmann/json/issues/403) +- json::parse of std::string being underlined by Visual Studio [\#402](https://github.com/nlohmann/json/issues/402) +- Explicitly getting string without .dump\(\) [\#401](https://github.com/nlohmann/json/issues/401) +- Possible to speed up json::parse? [\#398](https://github.com/nlohmann/json/issues/398) +- the alphabetic order in the code influence console\_output. [\#396](https://github.com/nlohmann/json/issues/396) +- Execute tests with clang sanitizers [\#394](https://github.com/nlohmann/json/issues/394) +- Check if library can be used with ETL [\#361](https://github.com/nlohmann/json/issues/361) + +- Feature/clang sanitize [\#410](https://github.com/nlohmann/json/pull/410) ([Daniel599](https://github.com/Daniel599)) +- Add Doozer build badge [\#400](https://github.com/nlohmann/json/pull/400) ([andoma](https://github.com/andoma)) + ## [v2.0.9](https://github.com/nlohmann/json/releases/tag/v2.0.9) (2016-12-16) [Full Changelog](https://github.com/nlohmann/json/compare/v2.0.8...v2.0.9) From 69c615e1274ddb8ba07b3ba19eee951946bd5ddb Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Mon, 2 Jan 2017 10:00:44 +0100 Subject: [PATCH 64/71] :bookmark: version bump to 2.0.10 --- doc/json.gif | Bin 1325973 -> 1331326 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/json.gif b/doc/json.gif index 7d3bf81645496c9a72e4f187e21a3ce2ba9223ef..efd2ee634a0704653811c31714f7cc1757c02966 100644 GIT binary patch delta 50413 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Ⓢ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 G8~+DEH)a9= delta 44999 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�hzIEzI6Z~tJ>Uj>Be6qjLnaY}Ex>Pwe;=0mG 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 MkX?c^d;!<~4|z~G%m4rY From 7e2c4b3ead030e4d0b628db78f52affece41059a Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Mon, 2 Jan 2017 16:37:29 +0100 Subject: [PATCH 65/71] :memo: updated online link --- README.md | 2 +- doc/examples/README.link | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a0534615..498d1bbe 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [](https://doozer.io/user/nlohmann/json) [](https://coveralls.io/r/nlohmann/json) [](https://scan.coverity.com/projects/nlohmann-json) -[](http://melpon.org/wandbox/permlink/8soFCqS532vOyZcK) +[](http://melpon.org/wandbox/permlink/IoZNMHqubixQx2dN) [](http://nlohmann.github.io/json) [](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) [](https://github.com/nlohmann/json/releases) diff --git a/doc/examples/README.link b/doc/examples/README.link index 128ab1dc..58daac88 100644 --- a/doc/examples/README.link +++ b/doc/examples/README.link @@ -1 +1 @@ -<a target="_blank" href="http://melpon.org/wandbox/permlink/8soFCqS532vOyZcK"><b>online</b></a> \ No newline at end of file +<a target="_blank" href="http://melpon.org/wandbox/permlink/IoZNMHqubixQx2dN"><b>online</b></a> \ No newline at end of file From 245a69d554425407a97374c133445f54d7d05952 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 3 Jan 2017 21:33:23 +0100 Subject: [PATCH 66/71] :lipstick: ran clang-tidy --- src/json.hpp | 218 +++++++++++++-------------------- src/json.hpp.re2c | 218 +++++++++++++-------------------- test/src/unit-allocator.cpp | 2 +- test/src/unit-constructor1.cpp | 2 +- 4 files changed, 174 insertions(+), 266 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 9d48e7a6..4e043ad5 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -128,7 +128,7 @@ struct has_mapped_type std::is_integral<decltype(detect(std::declval<T>()))>::value; }; -} +} // namespace /*! @brief a class to store JSON values @@ -767,7 +767,7 @@ class basic_json }; std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward<Args>(args)...); - assert(object.get() != nullptr); + assert(object != nullptr); return object.release(); } @@ -2583,29 +2583,25 @@ class basic_json template<class T, typename std::enable_if< std::is_convertible<typename object_t::key_type, typename T::key_type>::value and std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0> - T get_impl(T*) const + T get_impl(T* /*unused*/) const { if (is_object()) { return T(m_value.object->begin(), m_value.object->end()); } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } + + throw std::domain_error("type must be object, but is " + type_name()); } /// get an object (explicit) - object_t get_impl(object_t*) const + object_t get_impl(object_t* /*unused*/) const { if (is_object()) { return *(m_value.object); } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } + + throw std::domain_error("type must be object, but is " + type_name()); } /// get an array (explicit) @@ -2615,7 +2611,7 @@ class basic_json not std::is_arithmetic<T>::value and not std::is_convertible<std::string, T>::value and not has_mapped_type<T>::value, int>::type = 0> - T get_impl(T*) const + T get_impl(T* /*unused*/) const { if (is_array()) { @@ -2627,17 +2623,15 @@ class basic_json }); return to_vector; } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + + throw std::domain_error("type must be array, but is " + type_name()); } /// get an array (explicit) template<class T, typename std::enable_if< std::is_convertible<basic_json_t, T>::value and not std::is_same<basic_json_t, T>::value, int>::type = 0> - std::vector<T> get_impl(std::vector<T>*) const + std::vector<T> get_impl(std::vector<T>* /*unused*/) const { if (is_array()) { @@ -2650,60 +2644,52 @@ class basic_json }); return to_vector; } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + + throw std::domain_error("type must be array, but is " + type_name()); } /// get an array (explicit) template<class T, typename std::enable_if< std::is_same<basic_json, typename T::value_type>::value and not has_mapped_type<T>::value, int>::type = 0> - T get_impl(T*) const + T get_impl(T* /*unused*/) const { if (is_array()) { return T(m_value.array->begin(), m_value.array->end()); } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + + throw std::domain_error("type must be array, but is " + type_name()); } /// get an array (explicit) - array_t get_impl(array_t*) const + array_t get_impl(array_t* /*unused*/) const { if (is_array()) { return *(m_value.array); } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + + throw std::domain_error("type must be array, but is " + type_name()); } /// get a string (explicit) template<typename T, typename std::enable_if< std::is_convertible<string_t, T>::value, int>::type = 0> - T get_impl(T*) const + T get_impl(T* /*unused*/) const { if (is_string()) { return *m_value.string; } - else - { - throw std::domain_error("type must be string, but is " + type_name()); - } + + throw std::domain_error("type must be string, but is " + type_name()); } /// get a number (explicit) template<typename T, typename std::enable_if< std::is_arithmetic<T>::value, int>::type = 0> - T get_impl(T*) const + T get_impl(T* /*unused*/) const { switch (m_type) { @@ -2730,7 +2716,7 @@ class basic_json } /// get a boolean (explicit) - constexpr boolean_t get_impl(boolean_t*) const + constexpr boolean_t get_impl(boolean_t* /*unused*/) const { return is_boolean() ? m_value.boolean @@ -2738,85 +2724,85 @@ class basic_json } /// get a pointer to the value (object) - object_t* get_impl_ptr(object_t*) noexcept + object_t* get_impl_ptr(object_t* /*unused*/) noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (object) - constexpr const object_t* get_impl_ptr(const object_t*) const noexcept + constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (array) - array_t* get_impl_ptr(array_t*) noexcept + array_t* get_impl_ptr(array_t* /*unused*/) noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (array) - constexpr const array_t* get_impl_ptr(const array_t*) const noexcept + constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (string) - string_t* get_impl_ptr(string_t*) noexcept + string_t* get_impl_ptr(string_t* /*unused*/) noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (string) - constexpr const string_t* get_impl_ptr(const string_t*) const noexcept + constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (boolean) - boolean_t* get_impl_ptr(boolean_t*) noexcept + boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (boolean) - constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept + constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (integer number) - number_integer_t* get_impl_ptr(number_integer_t*) noexcept + number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) - constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept + constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) - number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept + number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (unsigned number) - constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept + constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (floating-point number) - number_float_t* get_impl_ptr(number_float_t*) noexcept + number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept { return is_number_float() ? &m_value.number_float : nullptr; } /// get a pointer to the value (floating-point number) - constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept + constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { return is_number_float() ? &m_value.number_float : nullptr; } @@ -2845,11 +2831,9 @@ class basic_json { return *ptr; } - else - { - throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); - } + + throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + + obj.type_name()); } public: @@ -3349,10 +3333,8 @@ class basic_json return m_value.array->operator[](idx); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3381,10 +3363,8 @@ class basic_json { return m_value.array->operator[](idx); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3429,10 +3409,8 @@ class basic_json { return m_value.object->operator[](key); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3473,10 +3451,8 @@ class basic_json assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3590,10 +3566,8 @@ class basic_json { return m_value.object->operator[](key); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3635,10 +3609,8 @@ class basic_json assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3702,10 +3674,8 @@ class basic_json { return *it; } - else - { - return default_value; - } + + return default_value; } else { @@ -4131,10 +4101,8 @@ class basic_json { return m_value.object->erase(key); } - else - { - throw std::domain_error("cannot use erase() with " + type_name()); - } + + throw std::domain_error("cannot use erase() with " + type_name()); } /*! @@ -5186,10 +5154,8 @@ class basic_json result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } - else - { - throw std::domain_error("cannot use insert() with " + type_name()); - } + + throw std::domain_error("cannot use insert() with " + type_name()); } /*! @@ -5241,10 +5207,8 @@ class basic_json result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } - else - { - throw std::domain_error("cannot use insert() with " + type_name()); - } + + throw std::domain_error("cannot use insert() with " + type_name()); } /*! @@ -6122,7 +6086,7 @@ class basic_json { // assertion to check that the iterator range is indeed contiguous, // see http://stackoverflow.com/a/35008842/266378 for more discussion - assert(std::accumulate(first, last, std::make_pair<bool, int>(true, 0), + assert(std::accumulate(first, last, std::pair<bool, int>(true, 0), [&first](std::pair<bool, int> res, decltype(*first) val) { res.first &= (val == *(std::next(std::addressof(*first), res.second++))); @@ -6327,7 +6291,7 @@ class basic_json } T result; - uint8_t* ptr = reinterpret_cast<uint8_t*>(&result); + auto* ptr = reinterpret_cast<uint8_t*>(&result); for (size_t i = 0; i < sizeof(T); ++i) { *ptr++ = vec[current_index + sizeof(T) - i]; @@ -6473,7 +6437,7 @@ class basic_json { // float 64 v.push_back(0xcb); - const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float)); + const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float)); for (size_t i = 0; i < 8; ++i) { v.push_back(helper[7 - i]); @@ -6716,7 +6680,7 @@ class basic_json { // Double-Precision Float v.push_back(0xfb); - const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float)); + const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float)); for (size_t i = 0; i < 8; ++i) { v.push_back(helper[7 - i]); @@ -6916,7 +6880,7 @@ class basic_json { return v[current_idx]; } - else if (v[current_idx] <= 0x8f) // fixmap + if (v[current_idx] <= 0x8f) // fixmap { basic_json result = value_t::object; const size_t len = v[current_idx] & 0x0f; @@ -7577,7 +7541,7 @@ class basic_json { val = mant == 0 ? INFINITY : NAN; } - return half & 0x8000 ? -val : val; + return (half & 0x8000) != 0 ? -val : val; } case 0xfa: // Single-Precision Float (four-byte IEEE 754) @@ -7800,10 +7764,8 @@ class basic_json // from c (1 byte) to \uxxxx (6 bytes) return res + 5; } - else - { - return res; - } + + return res; } } }); @@ -8509,10 +8471,8 @@ class basic_json { return *m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + throw std::out_of_range("cannot get value"); } } } @@ -8545,10 +8505,8 @@ class basic_json { return m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + throw std::out_of_range("cannot get value"); } } } @@ -8861,10 +8819,8 @@ class basic_json { return *m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + throw std::out_of_range("cannot get value"); } } } @@ -8881,10 +8837,8 @@ class basic_json { return m_it.object_iterator->first; } - else - { - throw std::domain_error("cannot use key() for non-object iterators"); - } + + throw std::domain_error("cannot use key() for non-object iterators"); } /*! @@ -10209,7 +10163,7 @@ basic_json_parser_66: assert(m_marker == nullptr or m_marker <= m_limit); // number of processed characters (p) - const size_t num_processed_chars = static_cast<size_t>(m_start - m_content); + const auto num_processed_chars = static_cast<size_t>(m_start - m_content); // offset for m_marker wrt. to m_start const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start; // number of unprocessed characters (u) @@ -10601,7 +10555,7 @@ basic_json_parser_66: else { // parse with strtod - result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL); + result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), nullptr); // replace infinity and NAN by null if (not std::isfinite(result.m_value.number_float)) @@ -11336,7 +11290,7 @@ basic_json_parser_66: // - start: position after the previous slash for ( // search for the first slash after the first character - size_t slash = reference_string.find_first_of("/", 1), + size_t slash = reference_string.find_first_of('/', 1), // set the beginning of the first reference token start = 1; // we can stop if start == string::npos+1 = 0 @@ -11345,16 +11299,16 @@ basic_json_parser_66: // (will eventually be 0 if slash == std::string::npos) start = slash + 1, // find next slash - slash = reference_string.find_first_of("/", start)) + slash = reference_string.find_first_of('/', start)) { // use the text between the beginning of the reference token // (start) and the last slash (slash). auto reference_token = reference_string.substr(start, slash - start); // check reference tokens are properly escaped - for (size_t pos = reference_token.find_first_of("~"); + for (size_t pos = reference_token.find_first_of('~'); pos != std::string::npos; - pos = reference_token.find_first_of("~", pos + 1)) + pos = reference_token.find_first_of('~', pos + 1)) { assert(reference_token[pos] == '~'); @@ -12188,7 +12142,7 @@ uses the standard template types. @since version 1.0.0 */ using json = basic_json<>; -} +} // namespace nlohmann /////////////////////// @@ -12229,7 +12183,7 @@ struct hash<nlohmann::json> return h(j.dump()); } }; -} +} // namespace std /*! @brief user-defined string literal for JSON values diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index e1a43b54..a64762b9 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -128,7 +128,7 @@ struct has_mapped_type std::is_integral<decltype(detect(std::declval<T>()))>::value; }; -} +} // namespace /*! @brief a class to store JSON values @@ -767,7 +767,7 @@ class basic_json }; std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter); alloc.construct(object.get(), std::forward<Args>(args)...); - assert(object.get() != nullptr); + assert(object != nullptr); return object.release(); } @@ -2583,29 +2583,25 @@ class basic_json template<class T, typename std::enable_if< std::is_convertible<typename object_t::key_type, typename T::key_type>::value and std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0> - T get_impl(T*) const + T get_impl(T* /*unused*/) const { if (is_object()) { return T(m_value.object->begin(), m_value.object->end()); } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } + + throw std::domain_error("type must be object, but is " + type_name()); } /// get an object (explicit) - object_t get_impl(object_t*) const + object_t get_impl(object_t* /*unused*/) const { if (is_object()) { return *(m_value.object); } - else - { - throw std::domain_error("type must be object, but is " + type_name()); - } + + throw std::domain_error("type must be object, but is " + type_name()); } /// get an array (explicit) @@ -2615,7 +2611,7 @@ class basic_json not std::is_arithmetic<T>::value and not std::is_convertible<std::string, T>::value and not has_mapped_type<T>::value, int>::type = 0> - T get_impl(T*) const + T get_impl(T* /*unused*/) const { if (is_array()) { @@ -2627,17 +2623,15 @@ class basic_json }); return to_vector; } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + + throw std::domain_error("type must be array, but is " + type_name()); } /// get an array (explicit) template<class T, typename std::enable_if< std::is_convertible<basic_json_t, T>::value and not std::is_same<basic_json_t, T>::value, int>::type = 0> - std::vector<T> get_impl(std::vector<T>*) const + std::vector<T> get_impl(std::vector<T>* /*unused*/) const { if (is_array()) { @@ -2650,60 +2644,52 @@ class basic_json }); return to_vector; } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + + throw std::domain_error("type must be array, but is " + type_name()); } /// get an array (explicit) template<class T, typename std::enable_if< std::is_same<basic_json, typename T::value_type>::value and not has_mapped_type<T>::value, int>::type = 0> - T get_impl(T*) const + T get_impl(T* /*unused*/) const { if (is_array()) { return T(m_value.array->begin(), m_value.array->end()); } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + + throw std::domain_error("type must be array, but is " + type_name()); } /// get an array (explicit) - array_t get_impl(array_t*) const + array_t get_impl(array_t* /*unused*/) const { if (is_array()) { return *(m_value.array); } - else - { - throw std::domain_error("type must be array, but is " + type_name()); - } + + throw std::domain_error("type must be array, but is " + type_name()); } /// get a string (explicit) template<typename T, typename std::enable_if< std::is_convertible<string_t, T>::value, int>::type = 0> - T get_impl(T*) const + T get_impl(T* /*unused*/) const { if (is_string()) { return *m_value.string; } - else - { - throw std::domain_error("type must be string, but is " + type_name()); - } + + throw std::domain_error("type must be string, but is " + type_name()); } /// get a number (explicit) template<typename T, typename std::enable_if< std::is_arithmetic<T>::value, int>::type = 0> - T get_impl(T*) const + T get_impl(T* /*unused*/) const { switch (m_type) { @@ -2730,7 +2716,7 @@ class basic_json } /// get a boolean (explicit) - constexpr boolean_t get_impl(boolean_t*) const + constexpr boolean_t get_impl(boolean_t* /*unused*/) const { return is_boolean() ? m_value.boolean @@ -2738,85 +2724,85 @@ class basic_json } /// get a pointer to the value (object) - object_t* get_impl_ptr(object_t*) noexcept + object_t* get_impl_ptr(object_t* /*unused*/) noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (object) - constexpr const object_t* get_impl_ptr(const object_t*) const noexcept + constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept { return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (array) - array_t* get_impl_ptr(array_t*) noexcept + array_t* get_impl_ptr(array_t* /*unused*/) noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (array) - constexpr const array_t* get_impl_ptr(const array_t*) const noexcept + constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept { return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (string) - string_t* get_impl_ptr(string_t*) noexcept + string_t* get_impl_ptr(string_t* /*unused*/) noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (string) - constexpr const string_t* get_impl_ptr(const string_t*) const noexcept + constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept { return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (boolean) - boolean_t* get_impl_ptr(boolean_t*) noexcept + boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (boolean) - constexpr const boolean_t* get_impl_ptr(const boolean_t*) const noexcept + constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept { return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (integer number) - number_integer_t* get_impl_ptr(number_integer_t*) noexcept + number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) - constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept + constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) - number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept + number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (unsigned number) - constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t*) const noexcept + constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept { return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (floating-point number) - number_float_t* get_impl_ptr(number_float_t*) noexcept + number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept { return is_number_float() ? &m_value.number_float : nullptr; } /// get a pointer to the value (floating-point number) - constexpr const number_float_t* get_impl_ptr(const number_float_t*) const noexcept + constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { return is_number_float() ? &m_value.number_float : nullptr; } @@ -2845,11 +2831,9 @@ class basic_json { return *ptr; } - else - { - throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); - } + + throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + + obj.type_name()); } public: @@ -3349,10 +3333,8 @@ class basic_json return m_value.array->operator[](idx); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3381,10 +3363,8 @@ class basic_json { return m_value.array->operator[](idx); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3429,10 +3409,8 @@ class basic_json { return m_value.object->operator[](key); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3473,10 +3451,8 @@ class basic_json assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3590,10 +3566,8 @@ class basic_json { return m_value.object->operator[](key); } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3635,10 +3609,8 @@ class basic_json assert(m_value.object->find(key) != m_value.object->end()); return m_value.object->find(key)->second; } - else - { - throw std::domain_error("cannot use operator[] with " + type_name()); - } + + throw std::domain_error("cannot use operator[] with " + type_name()); } /*! @@ -3702,10 +3674,8 @@ class basic_json { return *it; } - else - { - return default_value; - } + + return default_value; } else { @@ -4131,10 +4101,8 @@ class basic_json { return m_value.object->erase(key); } - else - { - throw std::domain_error("cannot use erase() with " + type_name()); - } + + throw std::domain_error("cannot use erase() with " + type_name()); } /*! @@ -5186,10 +5154,8 @@ class basic_json result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val); return result; } - else - { - throw std::domain_error("cannot use insert() with " + type_name()); - } + + throw std::domain_error("cannot use insert() with " + type_name()); } /*! @@ -5241,10 +5207,8 @@ class basic_json result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); return result; } - else - { - throw std::domain_error("cannot use insert() with " + type_name()); - } + + throw std::domain_error("cannot use insert() with " + type_name()); } /*! @@ -6122,7 +6086,7 @@ class basic_json { // assertion to check that the iterator range is indeed contiguous, // see http://stackoverflow.com/a/35008842/266378 for more discussion - assert(std::accumulate(first, last, std::make_pair<bool, int>(true, 0), + assert(std::accumulate(first, last, std::pair<bool, int>(true, 0), [&first](std::pair<bool, int> res, decltype(*first) val) { res.first &= (val == *(std::next(std::addressof(*first), res.second++))); @@ -6327,7 +6291,7 @@ class basic_json } T result; - uint8_t* ptr = reinterpret_cast<uint8_t*>(&result); + auto* ptr = reinterpret_cast<uint8_t*>(&result); for (size_t i = 0; i < sizeof(T); ++i) { *ptr++ = vec[current_index + sizeof(T) - i]; @@ -6473,7 +6437,7 @@ class basic_json { // float 64 v.push_back(0xcb); - const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float)); + const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float)); for (size_t i = 0; i < 8; ++i) { v.push_back(helper[7 - i]); @@ -6716,7 +6680,7 @@ class basic_json { // Double-Precision Float v.push_back(0xfb); - const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float)); + const auto* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float)); for (size_t i = 0; i < 8; ++i) { v.push_back(helper[7 - i]); @@ -6916,7 +6880,7 @@ class basic_json { return v[current_idx]; } - else if (v[current_idx] <= 0x8f) // fixmap + if (v[current_idx] <= 0x8f) // fixmap { basic_json result = value_t::object; const size_t len = v[current_idx] & 0x0f; @@ -7577,7 +7541,7 @@ class basic_json { val = mant == 0 ? INFINITY : NAN; } - return half & 0x8000 ? -val : val; + return (half & 0x8000) != 0 ? -val : val; } case 0xfa: // Single-Precision Float (four-byte IEEE 754) @@ -7800,10 +7764,8 @@ class basic_json // from c (1 byte) to \uxxxx (6 bytes) return res + 5; } - else - { - return res; - } + + return res; } } }); @@ -8509,10 +8471,8 @@ class basic_json { return *m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + throw std::out_of_range("cannot get value"); } } } @@ -8545,10 +8505,8 @@ class basic_json { return m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + throw std::out_of_range("cannot get value"); } } } @@ -8861,10 +8819,8 @@ class basic_json { return *m_object; } - else - { - throw std::out_of_range("cannot get value"); - } + + throw std::out_of_range("cannot get value"); } } } @@ -8881,10 +8837,8 @@ class basic_json { return m_it.object_iterator->first; } - else - { - throw std::domain_error("cannot use key() for non-object iterators"); - } + + throw std::domain_error("cannot use key() for non-object iterators"); } /*! @@ -9359,7 +9313,7 @@ class basic_json assert(m_marker == nullptr or m_marker <= m_limit); // number of processed characters (p) - const size_t num_processed_chars = static_cast<size_t>(m_start - m_content); + const auto num_processed_chars = static_cast<size_t>(m_start - m_content); // offset for m_marker wrt. to m_start const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start; // number of unprocessed characters (u) @@ -9751,7 +9705,7 @@ class basic_json else { // parse with strtod - result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), NULL); + result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(nullptr), nullptr); // replace infinity and NAN by null if (not std::isfinite(result.m_value.number_float)) @@ -10486,7 +10440,7 @@ class basic_json // - start: position after the previous slash for ( // search for the first slash after the first character - size_t slash = reference_string.find_first_of("/", 1), + size_t slash = reference_string.find_first_of('/', 1), // set the beginning of the first reference token start = 1; // we can stop if start == string::npos+1 = 0 @@ -10495,16 +10449,16 @@ class basic_json // (will eventually be 0 if slash == std::string::npos) start = slash + 1, // find next slash - slash = reference_string.find_first_of("/", start)) + slash = reference_string.find_first_of('/', start)) { // use the text between the beginning of the reference token // (start) and the last slash (slash). auto reference_token = reference_string.substr(start, slash - start); // check reference tokens are properly escaped - for (size_t pos = reference_token.find_first_of("~"); + for (size_t pos = reference_token.find_first_of('~'); pos != std::string::npos; - pos = reference_token.find_first_of("~", pos + 1)) + pos = reference_token.find_first_of('~', pos + 1)) { assert(reference_token[pos] == '~'); @@ -11338,7 +11292,7 @@ uses the standard template types. @since version 1.0.0 */ using json = basic_json<>; -} +} // namespace nlohmann /////////////////////// @@ -11379,7 +11333,7 @@ struct hash<nlohmann::json> return h(j.dump()); } }; -} +} // namespace std /*! @brief user-defined string literal for JSON values diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index f11d8538..76f9a16b 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -80,7 +80,7 @@ struct my_allocator : std::allocator<T> } else { - ::new(reinterpret_cast<void*>(p)) T(std::forward<Args>(args)...); + ::new (reinterpret_cast<void*>(p)) T(std::forward<Args>(args)...); } } diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp index 6bfb4402..d03a5f40 100644 --- a/test/src/unit-constructor1.cpp +++ b/test/src/unit-constructor1.cpp @@ -912,7 +912,7 @@ TEST_CASE("constructors") SECTION("array") { - json j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} , 13 }; + json j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }; CHECK(j.type() == json::value_t::array); } } From f8d640b185c4b34bfb651250eb3b7113caf0317b Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 3 Jan 2017 22:35:31 +0100 Subject: [PATCH 67/71] :construction_worker: better support for OSS-Fuzz --- test/Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/Makefile b/test/Makefile index 68520bd3..678276ba 100644 --- a/test/Makefile +++ b/test/Makefile @@ -51,7 +51,7 @@ TESTCASES = $(patsubst src/unit-%.cpp,test-%,$(wildcard src/unit-*.cpp)) all: $(TESTCASES) clean: - rm -fr json_unit $(OBJECTS) $(SOURCES:.cpp=.gcno) $(SOURCES:.cpp=.gcda) $(TESTCASES) + rm -fr json_unit $(OBJECTS) $(SOURCES:.cpp=.gcno) $(SOURCES:.cpp=.gcda) $(TESTCASES) parse_afl_fuzzer parse_cbor_fuzzer parse_msgpack_fuzzer ############################################################################## # single test file @@ -84,13 +84,14 @@ check: $(TESTCASES) # fuzzer ############################################################################## +FUZZER_ENGINE = src/fuzzer-driver_afl.cpp fuzzers: parse_afl_fuzzer parse_cbor_fuzzer parse_msgpack_fuzzer parse_afl_fuzzer: - $(CXX) $(CXXFLAGS) $(CPPFLAGS) src/fuzzer-driver_afl.cpp src/fuzzer-parse_json.cpp -o $@ + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(FUZZER_ENGINE) src/fuzzer-parse_json.cpp -o $@ parse_cbor_fuzzer: - $(CXX) $(CXXFLAGS) $(CPPFLAGS) src/fuzzer-driver_afl.cpp src/fuzzer-parse_cbor.cpp -o $@ + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(FUZZER_ENGINE) src/fuzzer-parse_cbor.cpp -o $@ parse_msgpack_fuzzer: - $(CXX) $(CXXFLAGS) $(CPPFLAGS) src/fuzzer-driver_afl.cpp src/fuzzer-parse_msgpack.cpp -o $@ + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(FUZZER_ENGINE) src/fuzzer-parse_msgpack.cpp -o $@ From 767637877b6004ed16a0474ed3e3aa022fb493da Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 3 Jan 2017 22:37:07 +0100 Subject: [PATCH 68/71] :lipstick: cleanup --- src/json.hpp | 52 ++++++++++++++++++++++++----------------------- src/json.hpp.re2c | 52 ++++++++++++++++++++++++----------------------- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 4e043ad5..f3b77a41 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -153,7 +153,8 @@ default) @requirement The class satisfies the following concept requirements: - Basic - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible): - JSON values can be default constructed. The result will be a JSON null value. + JSON values can be default constructed. The result will be a JSON null + value. - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible): A JSON value can be constructed from an rvalue argument. - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible): @@ -168,8 +169,8 @@ default) - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType): JSON values have [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout): - All non-static data members are private and standard layout types, the class - has no virtual functions or (virtual) base classes. + All non-static data members are private and standard layout types, the + class has no virtual functions or (virtual) base classes. - Library-wide - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable): JSON values can be compared with `==`, see @ref @@ -1894,13 +1895,15 @@ class basic_json case value_t::object: { - m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator); + m_value.object = create<object_t>(first.m_it.object_iterator, + last.m_it.object_iterator); break; } case value_t::array: { - m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator); + m_value.array = create<array_t>(first.m_it.array_iterator, + last.m_it.array_iterator); break; } @@ -3084,7 +3087,7 @@ class basic_json template < typename ValueType, typename std::enable_if < not std::is_pointer<ValueType>::value and not std::is_same<ValueType, typename string_t::value_type>::value -#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 +#ifndef _MSC_VER // fix for issue #167 operator<< abiguity under VS2015 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value #endif , int >::type = 0 > @@ -3750,10 +3753,8 @@ class basic_json return default_value; } } - else - { - throw std::domain_error("cannot use value() with " + type_name()); - } + + throw std::domain_error("cannot use value() with " + type_name()); } /*! @@ -5065,8 +5066,8 @@ class basic_json /*! @brief add an object to an object if key does not exist - Inserts a new element into a JSON object constructed in-place with the given - @a args if there is no element with the key in the container. If the + Inserts a new element into a JSON object constructed in-place with the + given @a args if there is no element with the key in the container. If the function is called on a JSON null value, an empty object is created before appending the value created from @a args. @@ -5131,8 +5132,8 @@ class basic_json @throw std::domain_error if @a pos is not an iterator of *this; example: `"iterator does not fit current value"` - @complexity Constant plus linear in the distance between pos and end of the - container. + @complexity Constant plus linear in the distance between pos and end of + the container. @liveexample{The example shows how `insert()` is used.,insert} @@ -5358,8 +5359,8 @@ class basic_json @param[in,out] other array to exchange the contents with - @throw std::domain_error when JSON value is not an array; example: `"cannot - use swap() with string"` + @throw std::domain_error when JSON value is not an array; example: + `"cannot use swap() with string"` @complexity Constant. @@ -6332,8 +6333,9 @@ class basic_json if (j.m_value.number_integer >= 0) { // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we used - // the code from the value_t::number_unsigned case here. + // signed integers and unsigned integers. Therefore, we + // used the code from the value_t::number_unsigned case + // here. if (j.m_value.number_unsigned < 128) { // positive fixnum @@ -6608,8 +6610,8 @@ class basic_json } else { - // The conversions below encode the sign in the first byte, - // and the value is converted to a positive number. + // The conversions below encode the sign in the first + // byte, and the value is converted to a positive number. const auto positive_number = -1 - j.m_value.number_integer; if (j.m_value.number_integer >= -24) { @@ -6814,12 +6816,12 @@ class basic_json To secure the access to the byte vector during CBOR/MessagePack deserialization, bytes are copied from the vector into buffers. This - function checks if the number of bytes to copy (@a len) does not exceed the - size @s size of the vector. Additionally, an @a offset is given from where - to start reading the bytes. + function checks if the number of bytes to copy (@a len) does not exceed + the size @s size of the vector. Additionally, an @a offset is given from + where to start reading the bytes. - This function checks whether reading the bytes is safe; that is, offset is a - valid index in the vector, offset+len + This function checks whether reading the bytes is safe; that is, offset is + a valid index in the vector, offset+len @param[in] size size of the byte vector @param[in] len number of bytes to read diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index a64762b9..42459f4e 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -153,7 +153,8 @@ default) @requirement The class satisfies the following concept requirements: - Basic - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible): - JSON values can be default constructed. The result will be a JSON null value. + JSON values can be default constructed. The result will be a JSON null + value. - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible): A JSON value can be constructed from an rvalue argument. - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible): @@ -168,8 +169,8 @@ default) - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType): JSON values have [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout): - All non-static data members are private and standard layout types, the class - has no virtual functions or (virtual) base classes. + All non-static data members are private and standard layout types, the + class has no virtual functions or (virtual) base classes. - Library-wide - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable): JSON values can be compared with `==`, see @ref @@ -1894,13 +1895,15 @@ class basic_json case value_t::object: { - m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator); + m_value.object = create<object_t>(first.m_it.object_iterator, + last.m_it.object_iterator); break; } case value_t::array: { - m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator); + m_value.array = create<array_t>(first.m_it.array_iterator, + last.m_it.array_iterator); break; } @@ -3084,7 +3087,7 @@ class basic_json template < typename ValueType, typename std::enable_if < not std::is_pointer<ValueType>::value and not std::is_same<ValueType, typename string_t::value_type>::value -#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 +#ifndef _MSC_VER // fix for issue #167 operator<< abiguity under VS2015 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value #endif , int >::type = 0 > @@ -3750,10 +3753,8 @@ class basic_json return default_value; } } - else - { - throw std::domain_error("cannot use value() with " + type_name()); - } + + throw std::domain_error("cannot use value() with " + type_name()); } /*! @@ -5065,8 +5066,8 @@ class basic_json /*! @brief add an object to an object if key does not exist - Inserts a new element into a JSON object constructed in-place with the given - @a args if there is no element with the key in the container. If the + Inserts a new element into a JSON object constructed in-place with the + given @a args if there is no element with the key in the container. If the function is called on a JSON null value, an empty object is created before appending the value created from @a args. @@ -5131,8 +5132,8 @@ class basic_json @throw std::domain_error if @a pos is not an iterator of *this; example: `"iterator does not fit current value"` - @complexity Constant plus linear in the distance between pos and end of the - container. + @complexity Constant plus linear in the distance between pos and end of + the container. @liveexample{The example shows how `insert()` is used.,insert} @@ -5358,8 +5359,8 @@ class basic_json @param[in,out] other array to exchange the contents with - @throw std::domain_error when JSON value is not an array; example: `"cannot - use swap() with string"` + @throw std::domain_error when JSON value is not an array; example: + `"cannot use swap() with string"` @complexity Constant. @@ -6332,8 +6333,9 @@ class basic_json if (j.m_value.number_integer >= 0) { // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we used - // the code from the value_t::number_unsigned case here. + // signed integers and unsigned integers. Therefore, we + // used the code from the value_t::number_unsigned case + // here. if (j.m_value.number_unsigned < 128) { // positive fixnum @@ -6608,8 +6610,8 @@ class basic_json } else { - // The conversions below encode the sign in the first byte, - // and the value is converted to a positive number. + // The conversions below encode the sign in the first + // byte, and the value is converted to a positive number. const auto positive_number = -1 - j.m_value.number_integer; if (j.m_value.number_integer >= -24) { @@ -6814,12 +6816,12 @@ class basic_json To secure the access to the byte vector during CBOR/MessagePack deserialization, bytes are copied from the vector into buffers. This - function checks if the number of bytes to copy (@a len) does not exceed the - size @s size of the vector. Additionally, an @a offset is given from where - to start reading the bytes. + function checks if the number of bytes to copy (@a len) does not exceed + the size @s size of the vector. Additionally, an @a offset is given from + where to start reading the bytes. - This function checks whether reading the bytes is safe; that is, offset is a - valid index in the vector, offset+len + This function checks whether reading the bytes is safe; that is, offset is + a valid index in the vector, offset+len @param[in] size size of the byte vector @param[in] len number of bytes to read From cdd3b5a68c9cae62815808e36486aab60fe87ffe Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Tue, 3 Jan 2017 23:52:01 +0100 Subject: [PATCH 69/71] :ambulance: fix for #416 --- src/json.hpp | 12 ++++-------- src/json.hpp.re2c | 15 +++++---------- test/src/unit-regression.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index f3b77a41..4aa293d2 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6938,11 +6938,10 @@ class basic_json case 0xca: // float 32 { // copy bytes in reverse order into the double variable - check_length(v.size(), sizeof(float), 1); float res; for (size_t byte = 0; byte < sizeof(float); ++byte) { - reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte]; + reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(float); // skip content bytes return res; @@ -6951,11 +6950,10 @@ class basic_json case 0xcb: // float 64 { // copy bytes in reverse order into the double variable - check_length(v.size(), sizeof(double), 1); double res; for (size_t byte = 0; byte < sizeof(double); ++byte) { - reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte]; + reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(double); // skip content bytes return res; @@ -7549,11 +7547,10 @@ class basic_json case 0xfa: // Single-Precision Float (four-byte IEEE 754) { // copy bytes in reverse order into the float variable - check_length(v.size(), sizeof(float), 1); float res; for (size_t byte = 0; byte < sizeof(float); ++byte) { - reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte]; + reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(float); // skip content bytes return res; @@ -7561,12 +7558,11 @@ class basic_json case 0xfb: // Double-Precision Float (eight-byte IEEE 754) { - check_length(v.size(), sizeof(double), 1); // copy bytes in reverse order into the double variable double res; for (size_t byte = 0; byte < sizeof(double); ++byte) { - reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte]; + reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(double); // skip content bytes return res; diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 42459f4e..73c4131a 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6938,11 +6938,10 @@ class basic_json case 0xca: // float 32 { // copy bytes in reverse order into the double variable - check_length(v.size(), sizeof(float), 1); float res; for (size_t byte = 0; byte < sizeof(float); ++byte) { - reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte]; + reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(float); // skip content bytes return res; @@ -6951,11 +6950,10 @@ class basic_json case 0xcb: // float 64 { // copy bytes in reverse order into the double variable - check_length(v.size(), sizeof(double), 1); double res; for (size_t byte = 0; byte < sizeof(double); ++byte) { - reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte]; + reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(double); // skip content bytes return res; @@ -7517,7 +7515,6 @@ class basic_json case 0xf9: // Half-Precision Float (two-byte IEEE 754) { - check_length(v.size(), 2, 1); idx += 2; // skip two content bytes // code from RFC 7049, Appendix D, Figure 3: @@ -7527,7 +7524,7 @@ class basic_json // include at least decoding support for them even without such // support. An example of a small decoder for half-precision // floating-point numbers in the C language is shown in Fig. 3. - const int half = (v[current_idx + 1] << 8) + v[current_idx + 2]; + const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2); const int exp = (half >> 10) & 0x1f; const int mant = half & 0x3ff; double val; @@ -7549,11 +7546,10 @@ class basic_json case 0xfa: // Single-Precision Float (four-byte IEEE 754) { // copy bytes in reverse order into the float variable - check_length(v.size(), sizeof(float), 1); float res; for (size_t byte = 0; byte < sizeof(float); ++byte) { - reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte]; + reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(float); // skip content bytes return res; @@ -7561,12 +7557,11 @@ class basic_json case 0xfb: // Double-Precision Float (eight-byte IEEE 754) { - check_length(v.size(), sizeof(double), 1); // copy bytes in reverse order into the double variable double res; for (size_t byte = 0; byte < sizeof(double); ++byte) { - reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte]; + reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v.at(current_idx + 1 + byte); } idx += sizeof(double); // skip content bytes return res; diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 401867c2..7cb9169f 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -663,4 +663,31 @@ TEST_CASE("regression tests") std::vector<uint8_t> vec3 {0xbf, 0x61, 0x61, 0x01}; CHECK_THROWS_AS(json::from_cbor(vec3), std::out_of_range); } + + SECTION("issue #416 - Use-of-uninitialized-value (OSS-Fuzz issue 377)") + { + // original test case + std::vector<uint8_t> vec1 + { + 0x94, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, + 0x3a, 0x96, 0x96, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x71, + 0xb4, 0xb4, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a, + 0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfa + }; + CHECK_THROWS_AS(json::from_cbor(vec1), std::out_of_range); + + // related test case: double-precision + std::vector<uint8_t> vec2 + { + 0x94, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, + 0x3a, 0x96, 0x96, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x71, + 0xb4, 0xb4, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a, + 0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb + }; + CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range); + } } From 476507031890fd6effb7b447a156168803b0bd37 Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 4 Jan 2017 18:07:46 +0100 Subject: [PATCH 70/71] :memo: added documentation wrt. UTF-8 strings #406 --- README.md | 1 + src/json.hpp | 9 +++++++-- src/json.hpp.re2c | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 498d1bbe..071d847a 100644 --- a/README.md +++ b/README.md @@ -600,6 +600,7 @@ Thanks a lot for helping out! - Other encodings such as Latin-1, UTF-16, or UTF-32 are not supported and will yield parse errors. - [Unicode noncharacters](http://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library. - Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors. + - The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs. ## Execute unit tests diff --git a/src/json.hpp b/src/json.hpp index 4aa293d2..6b1dc663 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -450,6 +450,12 @@ class basic_json std::string @endcode + #### Encoding + + Strings are stored in UTF-8 encoding. Therefore, functions like + `std::string::size()` or `std::string::length()` return the number of + bytes in the string rather than the number of characters or glyphs. + #### String comparison [RFC 7159](http://rfc7159.net/rfc7159) states: @@ -7515,7 +7521,6 @@ class basic_json case 0xf9: // Half-Precision Float (two-byte IEEE 754) { - check_length(v.size(), 2, 1); idx += 2; // skip two content bytes // code from RFC 7049, Appendix D, Figure 3: @@ -7525,7 +7530,7 @@ class basic_json // include at least decoding support for them even without such // support. An example of a small decoder for half-precision // floating-point numbers in the C language is shown in Fig. 3. - const int half = (v[current_idx + 1] << 8) + v[current_idx + 2]; + const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2); const int exp = (half >> 10) & 0x1f; const int mant = half & 0x3ff; double val; diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 73c4131a..0eed0e6d 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -450,6 +450,12 @@ class basic_json std::string @endcode + #### Encoding + + Strings are stored in UTF-8 encoding. Therefore, functions like + `std::string::size()` or `std::string::length()` return the number of + bytes in the string rather than the number of characters or glyphs. + #### String comparison [RFC 7159](http://rfc7159.net/rfc7159) states: From 9f6c86f23317ccc67429be779a6f17855c6e5a0b Mon Sep 17 00:00:00 2001 From: Niels Lohmann <niels.lohmann@gmail.com> Date: Wed, 4 Jan 2017 18:54:44 +0100 Subject: [PATCH 71/71] :bug: fix for #417 --- src/json.hpp | 6 ++---- src/json.hpp.re2c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 6b1dc663..e8861926 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -58,13 +58,11 @@ SOFTWARE. // exclude unsupported compilers #if defined(__clang__) - #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) - #if CLANG_VERSION < 30400 + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif #elif defined(__GNUC__) - #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) - #if GCC_VERSION < 40900 + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 0eed0e6d..3a12a78d 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -58,13 +58,11 @@ SOFTWARE. // exclude unsupported compilers #if defined(__clang__) - #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) - #if CLANG_VERSION < 30400 + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif #elif defined(__GNUC__) - #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) - #if GCC_VERSION < 40900 + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" #endif #endif