From 4d46e16ad7da36185732d021b756289bb37eeb1b Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Mon, 12 Apr 2021 17:36:30 +0900 Subject: [PATCH 01/18] Extract common code from runtime implementations. Signed-off-by: Takeshi Yoneda --- include/proxy-wasm/null_vm.h | 1 - include/proxy-wasm/wasm_vm.h | 8 -- src/common/wasm_util.cc | 159 ++++++++++++++++++++++++++++++ src/common/wasm_util.h | 69 ++++++++++++++ src/null/null_vm.cc | 5 - src/v8/v8.cc | 175 ++++------------------------------ src/wasmtime/wasmtime.cc | 124 ++++-------------------- src/wavm/wavm.cc | 10 -- test/BUILD | 2 + test/common/BUILD | 17 ++++ test/common/wasm_util_test.cc | 124 ++++++++++++++++++++++++ test/null_vm_test.cc | 1 - test/runtime_test.cc | 15 --- test/utility.cc | 9 ++ test/utility.h | 18 +--- 15 files changed, 421 insertions(+), 316 deletions(-) create mode 100644 src/common/wasm_util.cc create mode 100644 src/common/wasm_util.h create mode 100644 test/common/BUILD create mode 100644 test/common/wasm_util_test.cc diff --git a/include/proxy-wasm/null_vm.h b/include/proxy-wasm/null_vm.h index d731060a2..a1a2f73d5 100644 --- a/include/proxy-wasm/null_vm.h +++ b/include/proxy-wasm/null_vm.h @@ -44,7 +44,6 @@ struct NullVm : public WasmVm { bool setWord(uint64_t pointer, Word data) override; bool getWord(uint64_t pointer, Word *data) override; size_t getWordSize() override; - std::string_view getCustomSection(std::string_view name) override; std::string_view getPrecompiledSectionName() override; #define _FORWARD_GET_FUNCTION(_T) \ diff --git a/include/proxy-wasm/wasm_vm.h b/include/proxy-wasm/wasm_vm.h index e88aa3784..c794e6f4c 100644 --- a/include/proxy-wasm/wasm_vm.h +++ b/include/proxy-wasm/wasm_vm.h @@ -248,14 +248,6 @@ class WasmVm { */ virtual size_t getWordSize() = 0; - /** - * Get the contents of the custom section with the given name or "" if it does not exist. - * @param name the name of the custom section to get. - * @return the contents of the custom section (if any). The result will be empty if there - * is no such section. - */ - virtual std::string_view getCustomSection(std::string_view name) = 0; - /** * Get the name of the custom section that contains precompiled module. * @return the name of the custom section that contains precompiled module. diff --git a/src/common/wasm_util.cc b/src/common/wasm_util.cc new file mode 100644 index 000000000..a620fffca --- /dev/null +++ b/src/common/wasm_util.cc @@ -0,0 +1,159 @@ +// Copyright 2021 Google LLC +// +// 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 "src/common/wasm_util.h" +#include +#include + +namespace proxy_wasm { +namespace common { + +bool WasmUtil::getCustomSection(const char *begin, const char *end, std::string_view name, + std::string_view &ret) { + // Skip the Wasm header. + const char *pos = begin + 8; + while (pos < end) { + if (pos + 1 > end) { + return false; + } + const auto section_type = *pos++; + uint32_t section_len = 0; + if (!parseVarint(pos, end, section_len) || pos + section_len > end) { + return false; + } + if (section_type == 0) { + // Custom section. + const auto section_data_start = pos; + uint32_t section_name_len = 0; + if (!WasmUtil::parseVarint(pos, end, section_name_len) || pos + section_name_len > end) { + return false; + } + if (section_name_len == name.size() && ::memcmp(pos, name.data(), section_name_len) == 0) { + pos += section_name_len; + ret = {pos, static_cast(section_data_start + section_len - pos)}; + return true; + } + pos = section_data_start + section_len; + } else { + // Skip other sections. + pos += section_len; + } + } + return true; +}; + +bool WasmUtil::getFunctionNameIndex(const char *begin, const char *end, + std::unordered_map &ret) { + std::string_view name_section = {}; + if (!WasmUtil::getCustomSection(begin, end, "name", name_section)) { + return false; + }; + if (!name_section.empty()) { + const char *pos = name_section.data(); + const char *end = name_section.data() + name_section.size(); + while (pos < end) { + const auto subsection_id = *pos++; + uint32_t subsection_size = 0; + if (!parseVarint(pos, end, subsection_size) || pos + subsection_size > end) { + return false; + } + + if (subsection_id != 1) { + // Skip other subsctions. + pos += subsection_size; + } else { + // Enters function name subsection. + const auto start = pos; + uint32_t namemap_vector_size = 0; + if (!parseVarint(pos, end, namemap_vector_size) || pos + namemap_vector_size > end) { + return false; + } + for (uint32_t i = 0; i < namemap_vector_size; i++) { + uint32_t func_index = 0; + if (!parseVarint(pos, end, func_index)) { + return false; + } + + uint32_t func_name_size = 0; + if (!parseVarint(pos, end, func_name_size) || pos + func_name_size > end) { + return false; + } + ret.insert({func_index, std::string(pos, func_name_size)}); + pos += func_name_size; + } + if (start + subsection_size != pos) { + return false; + } + } + } + } + return true; +} + +bool WasmUtil::getStrippedSource(const char *begin, const char *end, std::vector &ret) { + // Skip the Wasm header. + const char *pos = begin + 8; + while (pos < end) { + const auto section_start = pos; + if (pos + 1 > end) { + return false; + } + const auto section_type = *pos++; + uint32_t section_len = 0; + if (!parseVarint(pos, end, section_len) || pos + section_len > end) { + return false; + } + if (section_type == 0 /* custom section */) { + const auto section_data_start = pos; + uint32_t section_name_len = 0; + if (!parseVarint(pos, end, section_name_len) || pos + section_name_len > end) { + return false; + } + auto section_name = std::string_view(pos, section_name_len); + if (section_name.find("precompiled_") != std::string::npos) { + // If this is the first "precompiled_" section, then save everything + // before it, otherwise skip it. + if (ret.empty()) { + const char *start = begin; + ret.insert(ret.end(), start, section_start); + } + } + pos = section_data_start + section_len; + } else { + pos += section_len; + // Save this section if we already saw a custom "precompiled_" section. + if (!ret.empty()) { + ret.insert(ret.end(), section_start, pos /* section end */); + } + } + } + return true; +} + +bool WasmUtil::parseVarint(const char *&pos, const char *end, uint32_t &ret) { + uint32_t shift = 0; + char b; + do { + if (pos + 1 > end) { + return false; + } + b = *pos++; + ret += (b & 0x7f) << shift; + shift += 7; + } while ((b & 0x80) != 0); + return ret != static_cast(-1); +} + +} // namespace common +} // namespace proxy_wasm diff --git a/src/common/wasm_util.h b/src/common/wasm_util.h new file mode 100644 index 000000000..f19e0196a --- /dev/null +++ b/src/common/wasm_util.h @@ -0,0 +1,69 @@ +// Copyright 2021 Google LLC +// +// 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. +#pragma once + +#include +#include +#include + +namespace proxy_wasm { +namespace common { + +// Utilitiy functions which directly operate on Wasm bytecodes. +class WasmUtil { +public: + /** + * getCustomSection extract the view of the custom section for a given name. + * @param begin is the beggining of bytecode. + * @param end is the end of bytecode. + * @param name is the name of the custom section. + * @param ret is the reference to store the resulting view to the custom section. + * @return indicates whether parsing succeeded or not. + */ + static bool getCustomSection(const char *begin, const char *end, std::string_view name, + std::string_view &ret); + + /** + * getFunctionNameIndex constructs the map from function indexes to function names stored in + * the function name subsection in "name" custom section. + * See https://webassembly.github.io/spec/core/appendix/custom.html#binary-funcnamesec for detail. + * @param begin is the beggining of bytecode. + * @param end is the end of bytecode. + * @param ret the reference to store map from function indexes to function names. + * @return indicates whether parsing succeeded or not. + */ + static bool getFunctionNameIndex(const char *begin, const char *end, + std::unordered_map &ret); + + /** + * getStrippedSource gets Wasm module without Custom Sections to save some memory in workers. + * @param begin is the beggining of original bytecode. + * @param end is the end of original bytecode. + * @param ret the reference to the stripped bytecode. + * @return indicates whether parsing succeeded or not. + */ + static bool getStrippedSource(const char *begin, const char *end, std::vector &ret); + + /** + * parseVarint parses the bytecode following LEB128. + * @param begin is the postion where parsing starts. + * @param end is the end of bytecode. + * @param ret is the reference to store the resulting value. + * @return indicates whether parsing succeeded or not. + */ + static bool parseVarint(const char *&begin, const char *end, uint32_t &ret); +}; + +} // namespace common +} // namespace proxy_wasm diff --git a/src/null/null_vm.cc b/src/null/null_vm.cc index 80a2210e0..a048c7da4 100644 --- a/src/null/null_vm.cc +++ b/src/null/null_vm.cc @@ -104,11 +104,6 @@ bool NullVm::getWord(uint64_t pointer, Word *data) { size_t NullVm::getWordSize() { return sizeof(uint64_t); } -std::string_view NullVm::getCustomSection(std::string_view /* name */) { - // Return nothing: there is no WASM file. - return {}; -} - std::string_view NullVm::getPrecompiledSectionName() { // Return nothing: there is no WASM file. return {}; diff --git a/src/v8/v8.cc b/src/v8/v8.cc index 986ce10f1..150afbf31 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -25,6 +25,8 @@ #include #include +#include "src/common/wasm_util.h" + #include "v8.h" #include "v8-version.h" #include "wasm-api/wasm.hh" @@ -64,7 +66,6 @@ class V8 : public WasmVm { bool load(const std::string &code, bool allow_precompiled) override; AbiVersion getAbiVersion() override; - std::string_view getCustomSection(std::string_view name) override; std::string_view getPrecompiledSectionName() override; bool link(std::string_view debug_name) override; @@ -94,8 +95,6 @@ class V8 : public WasmVm { #undef _GET_MODULE_FUNCTION private: - void buildFunctionNameIndex(); - wasm::vec getStrippedSource(); std::string getFailMessage(std::string_view function_name, wasm::own trap); template @@ -208,21 +207,6 @@ static bool equalValTypes(const wasm::ownvec &left, return true; } -static uint32_t parseVarint(const byte_t *&pos, const byte_t *end) { - uint32_t n = 0; - uint32_t shift = 0; - byte_t b; - do { - if (pos + 1 > end) { - abort(); - } - b = *pos++; - n += (b & 0x7f) << shift; - shift += 7; - } while ((b & 0x80) != 0); - return n; -} - // Template magic. template struct ConvertWordType { @@ -279,10 +263,17 @@ bool V8::load(const std::string &code, bool allow_precompiled) { source_ = wasm::vec::make_uninitialized(code.size()); ::memcpy(source_.get(), code.data(), code.size()); + const char *source_begin = source_.get(); + const char *source_end = source_begin + source_.size(); if (allow_precompiled) { const auto section_name = getPrecompiledSectionName(); if (!section_name.empty()) { - const auto precompiled = getCustomSection(section_name); + string_view precompiled = {}; + if (!common::WasmUtil::getCustomSection(source_begin, source_end, section_name, + precompiled)) { + fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); + return false; + } if (!precompiled.empty()) { auto vec = wasm::vec::make_uninitialized(precompiled.size()); ::memcpy(vec.get(), precompiled.data(), precompiled.size()); @@ -298,8 +289,11 @@ bool V8::load(const std::string &code, bool allow_precompiled) { } if (!module_) { - const auto stripped_source = getStrippedSource(); - module_ = wasm::Module::make(store_.get(), stripped_source ? stripped_source : source_); + const std::vector stripped = + common::WasmUtil::getStrippedSource(source_begin, source_end); + module_ = wasm::Module::make( + store_.get(), + stripped.empty() ? source_ : wasm::vec::make(stripped.size(), stripped.data())); } if (module_) { @@ -307,58 +301,12 @@ bool V8::load(const std::string &code, bool allow_precompiled) { assert((shared_module_ != nullptr)); } - buildFunctionNameIndex(); - + if (!common::WasmUtil::getFunctionNameIndex(source_begin, source_end, function_names_index_)) { + fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); + }; return module_ != nullptr; } -void V8::buildFunctionNameIndex() { - // build function index -> function name map for backtrace - // https://webassembly.github.io/spec/core/appendix/custom.html#binary-namesubsection - auto name_section = getCustomSection("name"); - if (name_section.size()) { - const byte_t *pos = name_section.data(); - const byte_t *end = name_section.data() + name_section.size(); - while (pos < end) { - if (*pos++ != 1) { - pos += parseVarint(pos, end); - } else { - const auto size = parseVarint(pos, end); - if (size == static_cast(-1) || pos + size > end) { - function_names_index_ = {}; - return; - } - const auto start = pos; - const auto namemap_vector_size = parseVarint(pos, end); - if (namemap_vector_size == static_cast(-1) || pos + namemap_vector_size > end) { - function_names_index_ = {}; - return; - } - for (auto i = 0; i < namemap_vector_size; i++) { - const auto func_index = parseVarint(pos, end); - if (func_index == static_cast(-1)) { - function_names_index_ = {}; - return; - } - - const auto func_name_size = parseVarint(pos, end); - if (func_name_size == static_cast(-1) || pos + func_name_size > end) { - function_names_index_ = {}; - return; - } - function_names_index_.insert({func_index, std::string(pos, func_name_size)}); - pos += func_name_size; - } - - if (start + size != pos) { - function_names_index_ = {}; - return; - } - } - } - } -} - std::unique_ptr V8::clone() { assert(shared_module_ != nullptr); @@ -372,93 +320,6 @@ std::unique_ptr V8::clone() { return clone; } -// Get Wasm module without Custom Sections to save some memory in workers. -wasm::vec V8::getStrippedSource() { - assert(source_.get() != nullptr); - - std::vector stripped; - - const byte_t *pos = source_.get() + 8 /* Wasm header */; - const byte_t *end = source_.get() + source_.size(); - while (pos < end) { - const auto section_start = pos; - if (pos + 1 > end) { - return wasm::vec::invalid(); - } - const auto section_type = *pos++; - const auto section_len = parseVarint(pos, end); - if (section_len == static_cast(-1) || pos + section_len > end) { - return wasm::vec::invalid(); - } - if (section_type == 0 /* custom section */) { - const auto section_data_start = pos; - const auto section_name_len = parseVarint(pos, end); - if (section_name_len == static_cast(-1) || pos + section_name_len > end) { - return wasm::vec::invalid(); - } - auto section_name = std::string_view(pos, section_name_len); - if (section_name.find("precompiled_") != std::string::npos) { - // If this is the first "precompiled_" section, then save everything - // before it, otherwise skip it. - if (stripped.empty()) { - const byte_t *start = source_.get(); - stripped.insert(stripped.end(), start, section_start); - } - } - pos = section_data_start + section_len; - } else { - pos += section_len; - // Save this section if we already saw a custom "precompiled_" section. - if (!stripped.empty()) { - stripped.insert(stripped.end(), section_start, pos /* section end */); - } - } - } - - // No custom sections found, use the original source. - if (stripped.empty()) { - return wasm::vec::invalid(); - } - - // Return stripped source, without custom sections. - return wasm::vec::make(stripped.size(), stripped.data()); -} - -std::string_view V8::getCustomSection(std::string_view name) { - assert(source_.get() != nullptr); - - const byte_t *pos = source_.get() + 8 /* Wasm header */; - const byte_t *end = source_.get() + source_.size(); - while (pos < end) { - if (pos + 1 > end) { - fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); - return ""; - } - const auto section_type = *pos++; - const auto section_len = parseVarint(pos, end); - if (section_len == static_cast(-1) || pos + section_len > end) { - fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); - return ""; - } - if (section_type == 0 /* custom section */) { - const auto section_data_start = pos; - const auto section_name_len = parseVarint(pos, end); - if (section_name_len == static_cast(-1) || pos + section_name_len > end) { - fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); - return ""; - } - if (section_name_len == name.size() && ::memcmp(pos, name.data(), section_name_len) == 0) { - pos += section_name_len; - return {pos, static_cast(section_data_start + section_len - pos)}; - } - pos = section_data_start + section_len; - } else { - pos += section_len; - } - } - return ""; -} - #if defined(__linux__) && defined(__x86_64__) #define WEE8_PLATFORM "linux_x86_64" #else diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index dec8ecbbb..06d1baf3e 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -25,7 +25,9 @@ #include #include "include/proxy-wasm/wasm_vm.h" +#include "src/common/wasm_util.h" #include "src/wasmtime/types.h" + #include "wasmtime/include/wasm.h" namespace proxy_wasm { @@ -57,7 +59,6 @@ class Wasmtime : public WasmVm { bool load(const std::string &code, bool allow_precompiled = false) override; AbiVersion getAbiVersion() override; - std::string_view getCustomSection(std::string_view name) override; bool link(std::string_view debug_name) override; std::unique_ptr clone() override; uint64_t getMemorySize() override; @@ -82,8 +83,6 @@ class Wasmtime : public WasmVm { FOR_ALL_WASM_VM_EXPORTS(_GET_MODULE_FUNCTION) #undef _GET_MODULE_FUNCTION private: - bool getStrippedSource(WasmByteVec *out); - template void registerHostFunctionImpl(std::string_view module_name, std::string_view function_name, void (*function)(void *, Args...)); @@ -113,22 +112,6 @@ class Wasmtime : public WasmVm { std::unordered_map module_functions_; }; -// TODO(mathetake): move to proxy_wasm::common::* -static uint32_t parseVarint(const byte_t *&pos, const byte_t *end) { - uint32_t n = 0; - uint32_t shift = 0; - byte_t b; - do { - if (pos + 1 > end) { - abort(); - } - b = *pos++; - n += (b & 0x7f) << shift; - shift += 7; - } while ((b & 0x80) != 0); - return n; -} - bool Wasmtime::load(const std::string &code, bool allow_precompiled) { store_ = wasm_store_new(engine()); @@ -141,9 +124,22 @@ bool Wasmtime::load(const std::string &code, bool allow_precompiled) { wasm_byte_vec_new_uninitialized(source_.get(), code.size()); ::memcpy(source_.get()->data, code.data(), code.size()); - WasmByteVec stripped; - module_ = - wasm_module_new(store_.get(), getStrippedSource(&stripped) ? stripped.get() : source_.get()); + std::vector stripped_vec; + if (!common::WasmUtil::getStrippedSource( + source_.get()->data, source_.get()->data + source_.get()->size, stripped_vec)) { + fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); + }; + + if (stripped_vec.empty()) { + // Use the original source. + module_ = wasm_module_new(store_.get(), source_.get()); + } else { + // Othewise pass the stripped source code. + WasmByteVec stripped; + wasm_byte_vec_new_uninitialized(stripped.get(), stripped_vec.size()); + ::memcpy(stripped.get()->data, stripped_vec.data(), stripped_vec.size()); + module_ = wasm_module_new(store_.get(), stripped.get()); + } if (module_) { shared_module_ = wasm_module_share(module_.get()); @@ -163,55 +159,6 @@ std::unique_ptr Wasmtime::clone() { return clone; } -// TODO(mathetake): move to proxy_wasm::common::* -bool Wasmtime::getStrippedSource(WasmByteVec *out) { - std::vector stripped; - - const byte_t *pos = source_.get()->data + 8 /* Wasm header */; - const byte_t *end = source_.get()->data + source_.get()->size; - while (pos < end) { - const auto section_start = pos; - if (pos + 1 > end) { - return false; - } - const auto section_type = *pos++; - const auto section_len = parseVarint(pos, end); - if (section_len == static_cast(-1) || pos + section_len > end) { - return false; - } - if (section_type == 0 /* custom section */) { - const auto section_data_start = pos; - const auto section_name_len = parseVarint(pos, end); - if (section_name_len == static_cast(-1) || pos + section_name_len > end) { - return false; - } - auto section_name = std::string_view(pos, section_name_len); - if (section_name.find("precompiled_") != std::string::npos) { - // If this is the first "precompiled_" section, then save everything - // before it, otherwise skip it. - if (stripped.empty()) { - const byte_t *start = source_.get()->data; - stripped.insert(stripped.end(), start, section_start); - } - } - pos = section_data_start + section_len; - } else { - pos += section_len; - // Save this section if we already saw a custom "precompiled_" section. - if (!stripped.empty()) { - stripped.insert(stripped.end(), section_start, pos /* section end */); - } - } - } - - if (!stripped.empty()) { - wasm_byte_vec_new_uninitialized(out->get(), stripped.size()); - ::memcpy(out->get()->data, stripped.data(), stripped.size()); - return true; - } - return false; -} - static bool equalValTypes(const wasm_valtype_vec_t *left, const wasm_valtype_vec_t *right) { if (left->size != right->size) { return false; @@ -400,41 +347,6 @@ bool Wasmtime::link(std::string_view debug_name) { return true; } -std::string_view Wasmtime::getCustomSection(std::string_view name) { - const byte_t *pos = source_.get()->data + 8 /* Wasm header */; - const byte_t *end = source_.get()->data + source_.get()->size; - while (pos < end) { - if (pos + 1 > end) { - fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); - return ""; - } - const auto section_type = *pos++; - const auto section_len = parseVarint(pos, end); - if (section_len == static_cast(-1) || pos + section_len > end) { - fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); - return ""; - } - - if (section_type == 0 /* custom section */) { - const auto section_data_start = pos; - const auto section_name_len = parseVarint(pos, end); - if (section_name_len == static_cast(-1) || pos + section_name_len > end) { - fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); - return ""; - } - if (section_name_len == name.size() && ::memcmp(pos, name.data(), section_name_len) == 0) { - pos += section_name_len; - return {pos, static_cast(section_data_start + section_len - pos)}; - } - pos = section_data_start + section_len; - } else { - pos += section_len; - } - } - - return ""; -} - uint64_t Wasmtime::getMemorySize() { return wasm_memory_data_size(memory_.get()); } std::optional Wasmtime::getMemory(uint64_t pointer, uint64_t size) { diff --git a/src/wavm/wavm.cc b/src/wavm/wavm.cc index f96b334fb..108dafac3 100644 --- a/src/wavm/wavm.cc +++ b/src/wavm/wavm.cc @@ -230,7 +230,6 @@ struct Wavm : public WasmVm { bool getWord(uint64_t pointer, Word *data) override; bool setWord(uint64_t pointer, Word data) override; size_t getWordSize() override { return sizeof(uint32_t); }; - std::string_view getCustomSection(std::string_view name) override; std::string_view getPrecompiledSectionName() override; AbiVersion getAbiVersion() override; @@ -400,15 +399,6 @@ bool Wavm::setWord(uint64_t pointer, Word data) { return setMemory(pointer, sizeof(uint32_t), &data32); } -std::string_view Wavm::getCustomSection(std::string_view name) { - for (auto §ion : ir_module_.customSections) { - if (section.name == name) { - return {reinterpret_cast(section.data.data()), section.data.size()}; - } - } - return {}; -} - std::string_view Wavm::getPrecompiledSectionName() { return "wavm.precompiled_object"; } } // namespace Wavm diff --git a/test/BUILD b/test/BUILD index 52b6113d0..0fad5ceb6 100644 --- a/test/BUILD +++ b/test/BUILD @@ -1,6 +1,8 @@ load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") load("@proxy_wasm_cpp_host//bazel:variables.bzl", "COPTS", "LINKOPTS") +package(default_visibility = ["//visibility:public"]) + cc_test( name = "null_vm_test", srcs = ["null_vm_test.cc"], diff --git a/test/common/BUILD b/test/common/BUILD new file mode 100644 index 000000000..c06b9723a --- /dev/null +++ b/test/common/BUILD @@ -0,0 +1,17 @@ +load("@rules_cc//cc:defs.bzl", "cc_test") +load("@proxy_wasm_cpp_host//bazel:variables.bzl", "COPTS") + +cc_test( + name = "wasm_util_test", + srcs = ["wasm_util_test.cc"], + copts = COPTS, + data = [ + "//test/test_data:abi_export.wasm", + ], + deps = [ + "//:lib", + "//test:utility_lib", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/test/common/wasm_util_test.cc b/test/common/wasm_util_test.cc new file mode 100644 index 000000000..e4610a53f --- /dev/null +++ b/test/common/wasm_util_test.cc @@ -0,0 +1,124 @@ +#include "src/common/wasm_util.h" + +#include +#include +#include + +#include "test/utility.h" + +#include "gtest/gtest.h" + +namespace proxy_wasm { +namespace common { + +TEST(TestWasmCommonUtil, getCustomSection) { + std::vector custom_section = { + 0x00, 0x61, 0x73, 0x6d, // Wasm magic + 0x01, 0x00, 0x00, 0x00, // Wasm version + 0x00, // custom section id + 0x0a, // section length + 0x04, 0x68, 0x65, 0x79, 0x21, // section name: "hey!" + 0x68, 0x65, 0x6c, 0x6c, 0x6f, // content: "hello" + }; + std::string_view section = {}; + + // OK. + EXPECT_TRUE(WasmUtil::getCustomSection( + custom_section.data(), custom_section.data() + custom_section.size(), "hey!", section)); + EXPECT_EQ(std::string(section), "hello"); + section = {}; + + // Non exist. + EXPECT_TRUE(WasmUtil::getCustomSection( + custom_section.data(), custom_section.data() + custom_section.size(), "non-exist", section)); + EXPECT_EQ(section, ""); + + // Fail due to the corrupted bytecode. + // TODO(@mathetake): here we haven't covered all the parsing failure branches. Add more cases. + EXPECT_FALSE(WasmUtil::getCustomSection( + custom_section.data(), custom_section.data() + custom_section.size() - 3, "hey", section)); + EXPECT_FALSE(WasmUtil::getCustomSection( + custom_section.data() + 1, custom_section.data() + custom_section.size(), "hey", section)); +} + +TEST(TestWasmCommonUtil, getFunctionNameIndex) { + const auto source = readTestWasmFile("abi_export.wasm"); + std::unordered_map actual; + // OK. + EXPECT_TRUE(WasmUtil::getFunctionNameIndex(source.data(), source.data() + source.size(), actual)); + EXPECT_FALSE(actual.empty()); + EXPECT_EQ(actual.find(0)->second, "proxy_abi_version_0_2_0"); + + // Fail due to the corrupted bytecode. + // TODO(@mathetake): here we haven't covered all the parsing failure branches. Add more cases. + actual = {}; + std::string_view name_section = {}; + EXPECT_TRUE(WasmUtil::getCustomSection(source.data(), source.data() + source.size(), "name", + name_section)); + // Passing module with malformed custom section. + EXPECT_FALSE(WasmUtil::getFunctionNameIndex(source.data(), name_section.data() + 1, actual)); + EXPECT_TRUE(actual.empty()); +} + +TEST(TestWasmCommonUtil, getStrippedSource) { + // Unmodified case. + auto source = readTestWasmFile("abi_export.wasm"); + std::vector actual; + EXPECT_TRUE(WasmUtil::getStrippedSource(source.data(), source.data() + source.size(), actual)); + // No `precompiled_` is found in the custom sections. + EXPECT_TRUE(actual.empty()); + + // Append "precompiled_test" custom section + std::vector custom_section = {// custom section id + 0x00, + // section length + 0x13, + // name length + 0x10, + // name = precompiled_test + 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, + 0x64, 0x5f, 0x74, 0x65, 0x73, 0x74, + // content + 0x01, 0x01}; + + source.append(custom_section.data(), custom_section.size()); + std::string_view section = {}; + EXPECT_TRUE(WasmUtil::getCustomSection(source.data(), source.data() + source.size(), + "precompiled_test", section)); + EXPECT_FALSE(section.empty()); + + // Chcek if the custom section is stripped. + actual = {}; + EXPECT_TRUE(WasmUtil::getStrippedSource(source.data(), source.data() + source.size(), actual)); + // No `precompiled_` is found in the custom sections. + EXPECT_FALSE(actual.empty()); + EXPECT_EQ(actual.size(), source.size() - custom_section.size()); +} + +TEST(WasmUtil, parseVarint) { + std::vector source; + const char *begin = source.data(); + uint32_t ret = 0; + EXPECT_FALSE(WasmUtil::parseVarint(begin, source.data(), ret)); + + source = {0x04}; + begin = source.data(); + EXPECT_TRUE(WasmUtil::parseVarint(begin, begin + source.size(), ret)); + EXPECT_EQ(0x04, ret); + ret = 0; + + source = {static_cast(0x80), 0x7f}; + begin = source.data(); + EXPECT_TRUE(WasmUtil::parseVarint(begin, begin + source.size(), ret)); + EXPECT_EQ(16256, ret); + ret = 0; + + source = {static_cast(0x89), static_cast(0x80), static_cast(0x80), + static_cast(0x80), 0x01}; + begin = source.data(); + EXPECT_TRUE(WasmUtil::parseVarint(begin, begin + source.size(), ret)); + EXPECT_EQ(268435465, ret); +} + +} // namespace common +} // namespace proxy_wasm diff --git a/test/null_vm_test.cc b/test/null_vm_test.cc index 26d45473d..0201b8599 100644 --- a/test/null_vm_test.cc +++ b/test/null_vm_test.cc @@ -68,7 +68,6 @@ TEST_F(BaseVmTest, NullVmStartup) { EXPECT_TRUE(wasm_vm->cloneable() == Cloneable::InstantiatedModule); auto wasm_vm_clone = wasm_vm->clone(); EXPECT_TRUE(wasm_vm_clone != nullptr); - EXPECT_TRUE(wasm_vm->getCustomSection("user").empty()); EXPECT_TRUE(wasm_vm->load("test_null_vm_plugin", true)); EXPECT_NE(test_null_vm_plugin, nullptr); } diff --git a/test/runtime_test.cc b/test/runtime_test.cc index 078a1db05..19ea8305c 100644 --- a/test/runtime_test.cc +++ b/test/runtime_test.cc @@ -44,21 +44,6 @@ TEST_P(TestVM, ABIVersion) { ASSERT_EQ(vm_->getAbiVersion(), AbiVersion::ProxyWasm_0_2_0); } -TEST_P(TestVM, CustomSection) { - initialize("abi_export.wasm"); - char custom_section[12] = { - 0x00, // custom section id - 0x0a, // section length - 0x04, 0x68, 0x65, 0x79, 0x21, // section name: "hey!" - 0x68, 0x65, 0x6c, 0x6c, 0x6f, // content: "hello" - }; - - source_ = source_.append(&custom_section[0], 12); - ASSERT_TRUE(vm_->load(source_, false)); - auto name_section = vm_->getCustomSection("hey!"); - ASSERT_EQ(name_section, "hello"); -} - TEST_P(TestVM, Memory) { initialize("abi_export.wasm"); ASSERT_TRUE(vm_->load(source_, false)); diff --git a/test/utility.cc b/test/utility.cc index 7e7ba4177..e55a5773c 100644 --- a/test/utility.cc +++ b/test/utility.cc @@ -32,4 +32,13 @@ std::vector getRuntimes() { runtimes.pop_back(); return runtimes; } + +std::string readTestWasmFile(std::string filename) { + auto path = "test/test_data/" + filename; + std::ifstream file(path, std::ios::binary); + EXPECT_FALSE(file.fail()) << "failed to open: " << path; + std::stringstream file_string_stream; + file_string_stream << file.rdbuf(); + return file_string_stream.str(); +} } // namespace proxy_wasm diff --git a/test/utility.h b/test/utility.h index de844d8da..22a86f1f0 100644 --- a/test/utility.h +++ b/test/utility.h @@ -35,6 +35,9 @@ namespace proxy_wasm { +std::vector getRuntimes(); +std::string readTestWasmFile(std::string filename); + struct DummyIntegration : public WasmVmIntegration { ~DummyIntegration() override{}; WasmVmIntegration *clone() override { return new DummyIntegration{}; } @@ -81,21 +84,10 @@ class TestVM : public testing::TestWithParam { vm_->integration().reset(integration_); } - DummyIntegration *integration_; - - void initialize(std::string filename) { - auto path = "test/test_data/" + filename; - std::ifstream file(path, std::ios::binary); - EXPECT_FALSE(file.fail()) << "failed to open: " << path; - std::stringstream file_string_stream; - file_string_stream << file.rdbuf(); - source_ = file_string_stream.str(); - } + void initialize(std::string filename) { source_ = readTestWasmFile(filename); } + DummyIntegration *integration_; std::string source_; std::string runtime_; }; - -std::vector getRuntimes(); - } // namespace proxy_wasm From 57bb777a7f12734ef0bd58448b3b3e7f7f7c3604 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Mon, 12 Apr 2021 17:41:18 +0900 Subject: [PATCH 02/18] Add license Signed-off-by: Takeshi Yoneda --- test/common/wasm_util_test.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/common/wasm_util_test.cc b/test/common/wasm_util_test.cc index e4610a53f..3ac37225e 100644 --- a/test/common/wasm_util_test.cc +++ b/test/common/wasm_util_test.cc @@ -1,3 +1,17 @@ +// Copyright 2021 Google LLC +// +// 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 "src/common/wasm_util.h" #include From 700d5b872f8c2f846d27479a139618e4f266d87d Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Mon, 12 Apr 2021 22:45:36 +0900 Subject: [PATCH 03/18] review: stop copying source Signed-off-by: Takeshi Yoneda --- src/common/wasm_util.cc | 24 ++++++++------ src/common/wasm_util.h | 15 +++------ src/v8/v8.cc | 35 +++++++++++---------- src/wasmtime/wasmtime.cc | 23 ++++++-------- test/common/wasm_util_test.cc | 59 ++++++++++------------------------- 5 files changed, 63 insertions(+), 93 deletions(-) diff --git a/src/common/wasm_util.cc b/src/common/wasm_util.cc index a620fffca..5916bbbac 100644 --- a/src/common/wasm_util.cc +++ b/src/common/wasm_util.cc @@ -13,16 +13,21 @@ // limitations under the License. #include "src/common/wasm_util.h" -#include -#include +#include namespace proxy_wasm { namespace common { -bool WasmUtil::getCustomSection(const char *begin, const char *end, std::string_view name, +bool WasmUtil::checkWasmHeader(std::string_view bytecode) { + static const uint8_t wasm_magic_number[4] = {0x00, 0x61, 0x73, 0x6d}; + return bytecode.size() < 8 || !::memcmp(bytecode.data(), wasm_magic_number, 4); +} + +bool WasmUtil::getCustomSection(std::string_view bytecode, std::string_view name, std::string_view &ret) { // Skip the Wasm header. - const char *pos = begin + 8; + const char *pos = bytecode.data() + 8; + const char *end = bytecode.data() + bytecode.size(); while (pos < end) { if (pos + 1 > end) { return false; @@ -53,10 +58,10 @@ bool WasmUtil::getCustomSection(const char *begin, const char *end, std::string_ return true; }; -bool WasmUtil::getFunctionNameIndex(const char *begin, const char *end, +bool WasmUtil::getFunctionNameIndex(std::string_view bytecode, std::unordered_map &ret) { std::string_view name_section = {}; - if (!WasmUtil::getCustomSection(begin, end, "name", name_section)) { + if (!WasmUtil::getCustomSection(bytecode, "name", name_section)) { return false; }; if (!name_section.empty()) { @@ -101,9 +106,10 @@ bool WasmUtil::getFunctionNameIndex(const char *begin, const char *end, return true; } -bool WasmUtil::getStrippedSource(const char *begin, const char *end, std::vector &ret) { +bool WasmUtil::getStrippedSource(std::string_view bytecode, std::string &ret) { // Skip the Wasm header. - const char *pos = begin + 8; + const char *pos = bytecode.data() + 8; + const char *end = bytecode.data() + bytecode.size(); while (pos < end) { const auto section_start = pos; if (pos + 1 > end) { @@ -125,7 +131,7 @@ bool WasmUtil::getStrippedSource(const char *begin, const char *end, std::vector // If this is the first "precompiled_" section, then save everything // before it, otherwise skip it. if (ret.empty()) { - const char *start = begin; + const char *start = bytecode.data(); ret.insert(ret.end(), start, section_start); } } diff --git a/src/common/wasm_util.h b/src/common/wasm_util.h index f19e0196a..a00a05c6a 100644 --- a/src/common/wasm_util.h +++ b/src/common/wasm_util.h @@ -23,6 +23,7 @@ namespace common { // Utilitiy functions which directly operate on Wasm bytecodes. class WasmUtil { public: + static bool checkWasmHeader(std::string_view bytecode); /** * getCustomSection extract the view of the custom section for a given name. * @param begin is the beggining of bytecode. @@ -31,7 +32,7 @@ class WasmUtil { * @param ret is the reference to store the resulting view to the custom section. * @return indicates whether parsing succeeded or not. */ - static bool getCustomSection(const char *begin, const char *end, std::string_view name, + static bool getCustomSection(std::string_view bytecode, std::string_view name, std::string_view &ret); /** @@ -43,7 +44,7 @@ class WasmUtil { * @param ret the reference to store map from function indexes to function names. * @return indicates whether parsing succeeded or not. */ - static bool getFunctionNameIndex(const char *begin, const char *end, + static bool getFunctionNameIndex(std::string_view bytecode, std::unordered_map &ret); /** @@ -53,15 +54,9 @@ class WasmUtil { * @param ret the reference to the stripped bytecode. * @return indicates whether parsing succeeded or not. */ - static bool getStrippedSource(const char *begin, const char *end, std::vector &ret); + static bool getStrippedSource(std::string_view bytecode, std::string &ret); - /** - * parseVarint parses the bytecode following LEB128. - * @param begin is the postion where parsing starts. - * @param end is the end of bytecode. - * @param ret is the reference to store the resulting value. - * @return indicates whether parsing succeeded or not. - */ +private: static bool parseVarint(const char *&begin, const char *end, uint32_t &ret); }; diff --git a/src/v8/v8.cc b/src/v8/v8.cc index 150afbf31..752bfc5f4 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -113,7 +113,6 @@ class V8 : public WasmVm { void getModuleFunctionImpl(std::string_view function_name, std::function *function); - wasm::vec source_ = wasm::vec::invalid(); wasm::own store_; wasm::own module_; wasm::own> shared_module_; @@ -255,22 +254,15 @@ bool V8::load(const std::string &code, bool allow_precompiled) { store_ = wasm::Store::make(engine()); // Wasm file header is 8 bytes (magic number + version). - static const uint8_t magic_number[4] = {0x00, 0x61, 0x73, 0x6d}; - if (code.size() < 8 || ::memcmp(code.data(), magic_number, 4) != 0) { + if (!common::WasmUtil::checkWasmHeader(code)) { return false; } - source_ = wasm::vec::make_uninitialized(code.size()); - ::memcpy(source_.get(), code.data(), code.size()); - - const char *source_begin = source_.get(); - const char *source_end = source_begin + source_.size(); if (allow_precompiled) { const auto section_name = getPrecompiledSectionName(); if (!section_name.empty()) { - string_view precompiled = {}; - if (!common::WasmUtil::getCustomSection(source_begin, source_end, section_name, - precompiled)) { + std::string_view precompiled = {}; + if (!common::WasmUtil::getCustomSection(code, section_name, precompiled)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); return false; } @@ -289,11 +281,20 @@ bool V8::load(const std::string &code, bool allow_precompiled) { } if (!module_) { - const std::vector stripped = - common::WasmUtil::getStrippedSource(source_begin, source_end); - module_ = wasm::Module::make( - store_.get(), - stripped.empty() ? source_ : wasm::vec::make(stripped.size(), stripped.data())); + std::string stripped; + if (!common::WasmUtil::getStrippedSource(code, stripped)) { + fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); + return false; + }; + wasm::vec code_vec = wasm::vec::invalid(); + if (stripped.empty()) { + // Use the original bytecode. + code_vec = wasm::vec::make(code.size(), (char *)(code.data())); + } else { + // Othewise use the stripped bytecode. + code_vec = wasm::vec::make(stripped.size(), stripped.data()); + } + module_ = wasm::Module::make(store_.get(), code_vec); } if (module_) { @@ -301,7 +302,7 @@ bool V8::load(const std::string &code, bool allow_precompiled) { assert((shared_module_ != nullptr)); } - if (!common::WasmUtil::getFunctionNameIndex(source_begin, source_end, function_names_index_)) { + if (!common::WasmUtil::getFunctionNameIndex(code, function_names_index_)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); }; return module_ != nullptr; diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index 06d1baf3e..b06f9607d 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -99,7 +99,6 @@ class Wasmtime : public WasmVm { void getModuleFunctionImpl(std::string_view function_name, std::function *function); - WasmByteVec source_; WasmStorePtr store_; WasmModulePtr module_; WasmSharedModulePtr shared_module_; @@ -115,29 +114,25 @@ class Wasmtime : public WasmVm { bool Wasmtime::load(const std::string &code, bool allow_precompiled) { store_ = wasm_store_new(engine()); - // Wasm file header is 8 bytes (magic number + version). - static const uint8_t magic_number[4] = {0x00, 0x61, 0x73, 0x6d}; - if (code.size() < 8 || ::memcmp(code.data(), magic_number, 4) != 0) { + if (!common::WasmUtil::checkWasmHeader(code)) { return false; } - wasm_byte_vec_new_uninitialized(source_.get(), code.size()); - ::memcpy(source_.get()->data, code.data(), code.size()); - - std::vector stripped_vec; - if (!common::WasmUtil::getStrippedSource( - source_.get()->data, source_.get()->data + source_.get()->size, stripped_vec)) { + std::vector stripped_vec; + if (!common::WasmUtil::getStrippedSource(code, stripped_vec)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); + return false; }; if (stripped_vec.empty()) { - // Use the original source. - module_ = wasm_module_new(store_.get(), source_.get()); + // Use the original bytecode. + WasmByteVec source_vec; + wasm_byte_vec_new(source_vec.get(), code.size(), code.data()); + module_ = wasm_module_new(store_.get(), source_vec.get()); } else { // Othewise pass the stripped source code. WasmByteVec stripped; - wasm_byte_vec_new_uninitialized(stripped.get(), stripped_vec.size()); - ::memcpy(stripped.get()->data, stripped_vec.data(), stripped_vec.size()); + wasm_byte_vec_new(stripped.get(), code.size(), code.data()); module_ = wasm_module_new(store_.get(), stripped.get()); } diff --git a/test/common/wasm_util_test.cc b/test/common/wasm_util_test.cc index 3ac37225e..b1e82c75e 100644 --- a/test/common/wasm_util_test.cc +++ b/test/common/wasm_util_test.cc @@ -26,7 +26,7 @@ namespace proxy_wasm { namespace common { TEST(TestWasmCommonUtil, getCustomSection) { - std::vector custom_section = { + std::string custom_section = { 0x00, 0x61, 0x73, 0x6d, // Wasm magic 0x01, 0x00, 0x00, 0x00, // Wasm version 0x00, // custom section id @@ -37,29 +37,28 @@ TEST(TestWasmCommonUtil, getCustomSection) { std::string_view section = {}; // OK. - EXPECT_TRUE(WasmUtil::getCustomSection( - custom_section.data(), custom_section.data() + custom_section.size(), "hey!", section)); + EXPECT_TRUE(WasmUtil::getCustomSection(custom_section, "hey!", section)); EXPECT_EQ(std::string(section), "hello"); section = {}; // Non exist. - EXPECT_TRUE(WasmUtil::getCustomSection( - custom_section.data(), custom_section.data() + custom_section.size(), "non-exist", section)); + EXPECT_TRUE(WasmUtil::getCustomSection(custom_section, "non-exist", section)); EXPECT_EQ(section, ""); // Fail due to the corrupted bytecode. // TODO(@mathetake): here we haven't covered all the parsing failure branches. Add more cases. - EXPECT_FALSE(WasmUtil::getCustomSection( - custom_section.data(), custom_section.data() + custom_section.size() - 3, "hey", section)); - EXPECT_FALSE(WasmUtil::getCustomSection( - custom_section.data() + 1, custom_section.data() + custom_section.size(), "hey", section)); + std::string corrupted = {custom_section.data(), + custom_section.data() + custom_section.size() - 3}; + EXPECT_FALSE(WasmUtil::getCustomSection(corrupted, "hey", section)); + corrupted = {custom_section.data() + 1, custom_section.data() + custom_section.size()}; + EXPECT_FALSE(WasmUtil::getCustomSection(corrupted, "hey", section)); } TEST(TestWasmCommonUtil, getFunctionNameIndex) { const auto source = readTestWasmFile("abi_export.wasm"); std::unordered_map actual; // OK. - EXPECT_TRUE(WasmUtil::getFunctionNameIndex(source.data(), source.data() + source.size(), actual)); + EXPECT_TRUE(WasmUtil::getFunctionNameIndex(source, actual)); EXPECT_FALSE(actual.empty()); EXPECT_EQ(actual.find(0)->second, "proxy_abi_version_0_2_0"); @@ -67,18 +66,18 @@ TEST(TestWasmCommonUtil, getFunctionNameIndex) { // TODO(@mathetake): here we haven't covered all the parsing failure branches. Add more cases. actual = {}; std::string_view name_section = {}; - EXPECT_TRUE(WasmUtil::getCustomSection(source.data(), source.data() + source.size(), "name", - name_section)); + EXPECT_TRUE(WasmUtil::getCustomSection(source, "name", name_section)); // Passing module with malformed custom section. - EXPECT_FALSE(WasmUtil::getFunctionNameIndex(source.data(), name_section.data() + 1, actual)); + std::string corrupted = {source.data(), name_section.data() + 1}; + EXPECT_FALSE(WasmUtil::getFunctionNameIndex(corrupted, actual)); EXPECT_TRUE(actual.empty()); } TEST(TestWasmCommonUtil, getStrippedSource) { // Unmodified case. auto source = readTestWasmFile("abi_export.wasm"); - std::vector actual; - EXPECT_TRUE(WasmUtil::getStrippedSource(source.data(), source.data() + source.size(), actual)); + std::vector actual; + EXPECT_TRUE(WasmUtil::getStrippedSource(source, actual)); // No `precompiled_` is found in the custom sections. EXPECT_TRUE(actual.empty()); @@ -97,42 +96,16 @@ TEST(TestWasmCommonUtil, getStrippedSource) { source.append(custom_section.data(), custom_section.size()); std::string_view section = {}; - EXPECT_TRUE(WasmUtil::getCustomSection(source.data(), source.data() + source.size(), - "precompiled_test", section)); + EXPECT_TRUE(WasmUtil::getCustomSection(source, "precompiled_test", section)); EXPECT_FALSE(section.empty()); // Chcek if the custom section is stripped. actual = {}; - EXPECT_TRUE(WasmUtil::getStrippedSource(source.data(), source.data() + source.size(), actual)); + EXPECT_TRUE(WasmUtil::getStrippedSource(source, actual)); // No `precompiled_` is found in the custom sections. EXPECT_FALSE(actual.empty()); EXPECT_EQ(actual.size(), source.size() - custom_section.size()); } -TEST(WasmUtil, parseVarint) { - std::vector source; - const char *begin = source.data(); - uint32_t ret = 0; - EXPECT_FALSE(WasmUtil::parseVarint(begin, source.data(), ret)); - - source = {0x04}; - begin = source.data(); - EXPECT_TRUE(WasmUtil::parseVarint(begin, begin + source.size(), ret)); - EXPECT_EQ(0x04, ret); - ret = 0; - - source = {static_cast(0x80), 0x7f}; - begin = source.data(); - EXPECT_TRUE(WasmUtil::parseVarint(begin, begin + source.size(), ret)); - EXPECT_EQ(16256, ret); - ret = 0; - - source = {static_cast(0x89), static_cast(0x80), static_cast(0x80), - static_cast(0x80), 0x01}; - begin = source.data(); - EXPECT_TRUE(WasmUtil::parseVarint(begin, begin + source.size(), ret)); - EXPECT_EQ(268435465, ret); -} - } // namespace common } // namespace proxy_wasm From 7172764062c53939f2af668fe50cc87f41b58b37 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Mon, 12 Apr 2021 22:49:25 +0900 Subject: [PATCH 04/18] Fix build Signed-off-by: Takeshi Yoneda --- src/wasmtime/wasmtime.cc | 2 +- test/common/wasm_util_test.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index b06f9607d..96f025286 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -118,7 +118,7 @@ bool Wasmtime::load(const std::string &code, bool allow_precompiled) { return false; } - std::vector stripped_vec; + std::string stripped_vec; if (!common::WasmUtil::getStrippedSource(code, stripped_vec)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); return false; diff --git a/test/common/wasm_util_test.cc b/test/common/wasm_util_test.cc index b1e82c75e..582f0ae4c 100644 --- a/test/common/wasm_util_test.cc +++ b/test/common/wasm_util_test.cc @@ -76,7 +76,7 @@ TEST(TestWasmCommonUtil, getFunctionNameIndex) { TEST(TestWasmCommonUtil, getStrippedSource) { // Unmodified case. auto source = readTestWasmFile("abi_export.wasm"); - std::vector actual; + std::string actual; EXPECT_TRUE(WasmUtil::getStrippedSource(source, actual)); // No `precompiled_` is found in the custom sections. EXPECT_TRUE(actual.empty()); From d9511116f4d68c5c201a3705d92cc79c5a483f05 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Mon, 12 Apr 2021 22:59:28 +0900 Subject: [PATCH 05/18] Fix doc comment Signed-off-by: Takeshi Yoneda --- src/common/wasm_util.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/common/wasm_util.h b/src/common/wasm_util.h index a00a05c6a..fa7760f88 100644 --- a/src/common/wasm_util.h +++ b/src/common/wasm_util.h @@ -23,11 +23,16 @@ namespace common { // Utilitiy functions which directly operate on Wasm bytecodes. class WasmUtil { public: + /** + * checkWasmHeader validates Wasm header. + * @param bytecode is the target bytecode. + * @return indicates whether the bytecode has valid Wasm header. + */ static bool checkWasmHeader(std::string_view bytecode); + /** * getCustomSection extract the view of the custom section for a given name. - * @param begin is the beggining of bytecode. - * @param end is the end of bytecode. + * @param bytecode is the target bytecode. * @param name is the name of the custom section. * @param ret is the reference to store the resulting view to the custom section. * @return indicates whether parsing succeeded or not. @@ -39,8 +44,7 @@ class WasmUtil { * getFunctionNameIndex constructs the map from function indexes to function names stored in * the function name subsection in "name" custom section. * See https://webassembly.github.io/spec/core/appendix/custom.html#binary-funcnamesec for detail. - * @param begin is the beggining of bytecode. - * @param end is the end of bytecode. + * @param bytecode is the target bytecode. * @param ret the reference to store map from function indexes to function names. * @return indicates whether parsing succeeded or not. */ @@ -49,8 +53,7 @@ class WasmUtil { /** * getStrippedSource gets Wasm module without Custom Sections to save some memory in workers. - * @param begin is the beggining of original bytecode. - * @param end is the end of original bytecode. + * @param bytecode is the original bytecode. * @param ret the reference to the stripped bytecode. * @return indicates whether parsing succeeded or not. */ From c5b123cffb538b5e49188e006c65b2b638194f55 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 08:40:21 +0900 Subject: [PATCH 06/18] rename files for better alignment Signed-off-by: Takeshi Yoneda --- src/common/wasm_util.cc | 18 +++++++++--------- src/common/wasm_util.h | 2 +- src/v8/v8.cc | 11 +++++++---- src/wasmtime/wasmtime.cc | 4 ++-- test/common/wasm_util_test.cc | 20 ++++++++++---------- 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/common/wasm_util.cc b/src/common/wasm_util.cc index 5916bbbac..1e974fcae 100644 --- a/src/common/wasm_util.cc +++ b/src/common/wasm_util.cc @@ -18,13 +18,13 @@ namespace proxy_wasm { namespace common { -bool WasmUtil::checkWasmHeader(std::string_view bytecode) { +bool BytecodeUtil::checkWasmHeader(std::string_view bytecode) { static const uint8_t wasm_magic_number[4] = {0x00, 0x61, 0x73, 0x6d}; return bytecode.size() < 8 || !::memcmp(bytecode.data(), wasm_magic_number, 4); } -bool WasmUtil::getCustomSection(std::string_view bytecode, std::string_view name, - std::string_view &ret) { +bool BytecodeUtil::getCustomSection(std::string_view bytecode, std::string_view name, + std::string_view &ret) { // Skip the Wasm header. const char *pos = bytecode.data() + 8; const char *end = bytecode.data() + bytecode.size(); @@ -41,7 +41,7 @@ bool WasmUtil::getCustomSection(std::string_view bytecode, std::string_view name // Custom section. const auto section_data_start = pos; uint32_t section_name_len = 0; - if (!WasmUtil::parseVarint(pos, end, section_name_len) || pos + section_name_len > end) { + if (!BytecodeUtil::parseVarint(pos, end, section_name_len) || pos + section_name_len > end) { return false; } if (section_name_len == name.size() && ::memcmp(pos, name.data(), section_name_len) == 0) { @@ -58,10 +58,10 @@ bool WasmUtil::getCustomSection(std::string_view bytecode, std::string_view name return true; }; -bool WasmUtil::getFunctionNameIndex(std::string_view bytecode, - std::unordered_map &ret) { +bool BytecodeUtil::getFunctionNameIndex(std::string_view bytecode, + std::unordered_map &ret) { std::string_view name_section = {}; - if (!WasmUtil::getCustomSection(bytecode, "name", name_section)) { + if (!BytecodeUtil::getCustomSection(bytecode, "name", name_section)) { return false; }; if (!name_section.empty()) { @@ -106,7 +106,7 @@ bool WasmUtil::getFunctionNameIndex(std::string_view bytecode, return true; } -bool WasmUtil::getStrippedSource(std::string_view bytecode, std::string &ret) { +bool BytecodeUtil::getStrippedSource(std::string_view bytecode, std::string &ret) { // Skip the Wasm header. const char *pos = bytecode.data() + 8; const char *end = bytecode.data() + bytecode.size(); @@ -147,7 +147,7 @@ bool WasmUtil::getStrippedSource(std::string_view bytecode, std::string &ret) { return true; } -bool WasmUtil::parseVarint(const char *&pos, const char *end, uint32_t &ret) { +bool BytecodeUtil::parseVarint(const char *&pos, const char *end, uint32_t &ret) { uint32_t shift = 0; char b; do { diff --git a/src/common/wasm_util.h b/src/common/wasm_util.h index fa7760f88..4473fdf70 100644 --- a/src/common/wasm_util.h +++ b/src/common/wasm_util.h @@ -21,7 +21,7 @@ namespace proxy_wasm { namespace common { // Utilitiy functions which directly operate on Wasm bytecodes. -class WasmUtil { +class BytecodeUtil { public: /** * checkWasmHeader validates Wasm header. diff --git a/src/v8/v8.cc b/src/v8/v8.cc index 752bfc5f4..105b45e0d 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -254,7 +254,8 @@ bool V8::load(const std::string &code, bool allow_precompiled) { store_ = wasm::Store::make(engine()); // Wasm file header is 8 bytes (magic number + version). - if (!common::WasmUtil::checkWasmHeader(code)) { + if (!common::BytecodeUtil::checkWasmHeader(code)) { + fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); return false; } @@ -262,7 +263,7 @@ bool V8::load(const std::string &code, bool allow_precompiled) { const auto section_name = getPrecompiledSectionName(); if (!section_name.empty()) { std::string_view precompiled = {}; - if (!common::WasmUtil::getCustomSection(code, section_name, precompiled)) { + if (!common::BytecodeUtil::getCustomSection(code, section_name, precompiled)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); return false; } @@ -282,7 +283,7 @@ bool V8::load(const std::string &code, bool allow_precompiled) { if (!module_) { std::string stripped; - if (!common::WasmUtil::getStrippedSource(code, stripped)) { + if (!common::BytecodeUtil::getStrippedSource(code, stripped)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); return false; }; @@ -302,9 +303,11 @@ bool V8::load(const std::string &code, bool allow_precompiled) { assert((shared_module_ != nullptr)); } - if (!common::WasmUtil::getFunctionNameIndex(code, function_names_index_)) { + if (!common::BytecodeUtil::getFunctionNameIndex(code, function_names_index_)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); + return false; }; + return module_ != nullptr; } diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index 96f025286..42e8f4cf2 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -114,12 +114,12 @@ class Wasmtime : public WasmVm { bool Wasmtime::load(const std::string &code, bool allow_precompiled) { store_ = wasm_store_new(engine()); - if (!common::WasmUtil::checkWasmHeader(code)) { + if (!common::BytecodeUtil::checkWasmHeader(code)) { return false; } std::string stripped_vec; - if (!common::WasmUtil::getStrippedSource(code, stripped_vec)) { + if (!common::BytecodeUtil::getStrippedSource(code, stripped_vec)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); return false; }; diff --git a/test/common/wasm_util_test.cc b/test/common/wasm_util_test.cc index 582f0ae4c..d8138bcf9 100644 --- a/test/common/wasm_util_test.cc +++ b/test/common/wasm_util_test.cc @@ -37,28 +37,28 @@ TEST(TestWasmCommonUtil, getCustomSection) { std::string_view section = {}; // OK. - EXPECT_TRUE(WasmUtil::getCustomSection(custom_section, "hey!", section)); + EXPECT_TRUE(BytecodeUtil::getCustomSection(custom_section, "hey!", section)); EXPECT_EQ(std::string(section), "hello"); section = {}; // Non exist. - EXPECT_TRUE(WasmUtil::getCustomSection(custom_section, "non-exist", section)); + EXPECT_TRUE(BytecodeUtil::getCustomSection(custom_section, "non-exist", section)); EXPECT_EQ(section, ""); // Fail due to the corrupted bytecode. // TODO(@mathetake): here we haven't covered all the parsing failure branches. Add more cases. std::string corrupted = {custom_section.data(), custom_section.data() + custom_section.size() - 3}; - EXPECT_FALSE(WasmUtil::getCustomSection(corrupted, "hey", section)); + EXPECT_FALSE(BytecodeUtil::getCustomSection(corrupted, "hey", section)); corrupted = {custom_section.data() + 1, custom_section.data() + custom_section.size()}; - EXPECT_FALSE(WasmUtil::getCustomSection(corrupted, "hey", section)); + EXPECT_FALSE(BytecodeUtil::getCustomSection(corrupted, "hey", section)); } TEST(TestWasmCommonUtil, getFunctionNameIndex) { const auto source = readTestWasmFile("abi_export.wasm"); std::unordered_map actual; // OK. - EXPECT_TRUE(WasmUtil::getFunctionNameIndex(source, actual)); + EXPECT_TRUE(BytecodeUtil::getFunctionNameIndex(source, actual)); EXPECT_FALSE(actual.empty()); EXPECT_EQ(actual.find(0)->second, "proxy_abi_version_0_2_0"); @@ -66,10 +66,10 @@ TEST(TestWasmCommonUtil, getFunctionNameIndex) { // TODO(@mathetake): here we haven't covered all the parsing failure branches. Add more cases. actual = {}; std::string_view name_section = {}; - EXPECT_TRUE(WasmUtil::getCustomSection(source, "name", name_section)); + EXPECT_TRUE(BytecodeUtil::getCustomSection(source, "name", name_section)); // Passing module with malformed custom section. std::string corrupted = {source.data(), name_section.data() + 1}; - EXPECT_FALSE(WasmUtil::getFunctionNameIndex(corrupted, actual)); + EXPECT_FALSE(BytecodeUtil::getFunctionNameIndex(corrupted, actual)); EXPECT_TRUE(actual.empty()); } @@ -77,7 +77,7 @@ TEST(TestWasmCommonUtil, getStrippedSource) { // Unmodified case. auto source = readTestWasmFile("abi_export.wasm"); std::string actual; - EXPECT_TRUE(WasmUtil::getStrippedSource(source, actual)); + EXPECT_TRUE(BytecodeUtil::getStrippedSource(source, actual)); // No `precompiled_` is found in the custom sections. EXPECT_TRUE(actual.empty()); @@ -96,12 +96,12 @@ TEST(TestWasmCommonUtil, getStrippedSource) { source.append(custom_section.data(), custom_section.size()); std::string_view section = {}; - EXPECT_TRUE(WasmUtil::getCustomSection(source, "precompiled_test", section)); + EXPECT_TRUE(BytecodeUtil::getCustomSection(source, "precompiled_test", section)); EXPECT_FALSE(section.empty()); // Chcek if the custom section is stripped. actual = {}; - EXPECT_TRUE(WasmUtil::getStrippedSource(source, actual)); + EXPECT_TRUE(BytecodeUtil::getStrippedSource(source, actual)); // No `precompiled_` is found in the custom sections. EXPECT_FALSE(actual.empty()); EXPECT_EQ(actual.size(), source.size() - custom_section.size()); From cefe6565889781aa33bc1bfd00aa825a07579358 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 08:43:37 +0900 Subject: [PATCH 07/18] Check Wasm header Signed-off-by: Takeshi Yoneda --- src/common/wasm_util.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/common/wasm_util.cc b/src/common/wasm_util.cc index 1e974fcae..d5efba778 100644 --- a/src/common/wasm_util.cc +++ b/src/common/wasm_util.cc @@ -25,6 +25,11 @@ bool BytecodeUtil::checkWasmHeader(std::string_view bytecode) { bool BytecodeUtil::getCustomSection(std::string_view bytecode, std::string_view name, std::string_view &ret) { + // Check Wasm header. + if (!checkWasmHeader(bytecode)) { + return false; + } + // Skip the Wasm header. const char *pos = bytecode.data() + 8; const char *end = bytecode.data() + bytecode.size(); @@ -107,6 +112,11 @@ bool BytecodeUtil::getFunctionNameIndex(std::string_view bytecode, } bool BytecodeUtil::getStrippedSource(std::string_view bytecode, std::string &ret) { + // Check Wasm header. + if (!checkWasmHeader(bytecode)) { + return false; + } + // Skip the Wasm header. const char *pos = bytecode.data() + 8; const char *end = bytecode.data() + bytecode.size(); From d749021cf4988a80b35d70836b2109928197484b Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 08:46:11 +0900 Subject: [PATCH 08/18] Simplify Wasmtime Signed-off-by: Takeshi Yoneda --- src/wasmtime/wasmtime.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index 42e8f4cf2..116ae3e25 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -115,6 +115,7 @@ bool Wasmtime::load(const std::string &code, bool allow_precompiled) { store_ = wasm_store_new(engine()); if (!common::BytecodeUtil::checkWasmHeader(code)) { + fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); return false; } @@ -124,17 +125,15 @@ bool Wasmtime::load(const std::string &code, bool allow_precompiled) { return false; }; + WasmByteVec source_vec; if (stripped_vec.empty()) { // Use the original bytecode. - WasmByteVec source_vec; wasm_byte_vec_new(source_vec.get(), code.size(), code.data()); - module_ = wasm_module_new(store_.get(), source_vec.get()); } else { // Othewise pass the stripped source code. - WasmByteVec stripped; - wasm_byte_vec_new(stripped.get(), code.size(), code.data()); - module_ = wasm_module_new(store_.get(), stripped.get()); + wasm_byte_vec_new(source_vec.get(), stripped_vec.size(), stripped_vec.data()); } + module_ = wasm_module_new(store_.get(), source_vec.get()); if (module_) { shared_module_ = wasm_module_share(module_.get()); From 265de5412368f574726c371f3718c9d3ee29c0c5 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 08:50:13 +0900 Subject: [PATCH 09/18] Add precompiled section test on runtime Signed-off-by: Takeshi Yoneda --- test/runtime_test.cc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/runtime_test.cc b/test/runtime_test.cc index 19ea8305c..7128d8c76 100644 --- a/test/runtime_test.cc +++ b/test/runtime_test.cc @@ -173,5 +173,26 @@ TEST_P(TestVM, Trap) { ASSERT_TRUE(integration_->error_message_.find(exp_message) != std::string::npos); } +TEST_P(TestVM, WithPrecompiledSection) { + // Verify that stripping precompile_* custom section works. + initialize("abi_export.wasm"); + // Append precompiled_test section + std::vector custom_section = {// custom section id + 0x00, + // section length + 0x13, + // name length + 0x10, + // name = precompiled_test + 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, + 0x64, 0x5f, 0x74, 0x65, 0x73, 0x74, + // content + 0x01, 0x01}; + + source_.append(custom_section.data(), custom_section.size()); + ASSERT_TRUE(vm_->load(source_, false)); + ASSERT_EQ(vm_->getAbiVersion(), AbiVersion::ProxyWasm_0_2_0); +} + } // namespace } // namespace proxy_wasm From a103f8f3de4b3d56e9a686666e9d2c877c575d7d Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 09:30:52 +0900 Subject: [PATCH 10/18] fix build Signed-off-by: Takeshi Yoneda --- src/common/wasm_util.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/wasm_util.cc b/src/common/wasm_util.cc index d5efba778..8976d9e2e 100644 --- a/src/common/wasm_util.cc +++ b/src/common/wasm_util.cc @@ -142,7 +142,7 @@ bool BytecodeUtil::getStrippedSource(std::string_view bytecode, std::string &ret // before it, otherwise skip it. if (ret.empty()) { const char *start = bytecode.data(); - ret.insert(ret.end(), start, section_start); + ret.append(start, section_start); } } pos = section_data_start + section_len; @@ -150,7 +150,7 @@ bool BytecodeUtil::getStrippedSource(std::string_view bytecode, std::string &ret pos += section_len; // Save this section if we already saw a custom "precompiled_" section. if (!ret.empty()) { - ret.insert(ret.end(), section_start, pos /* section end */); + ret.append(section_start, pos); } } } From d807f06f06afa8ea995b8458de3131331c0e23d6 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 10:00:46 +0900 Subject: [PATCH 11/18] Use BytecodeUtil in WAVM for precompiled section Signed-off-by: Takeshi Yoneda --- src/wavm/wavm.cc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/wavm/wavm.cc b/src/wavm/wavm.cc index 108dafac3..2b3bad9a7 100644 --- a/src/wavm/wavm.cc +++ b/src/wavm/wavm.cc @@ -27,6 +27,8 @@ #include #include +#include "src/common/wasm_util.h" + #include "WAVM/IR/Module.h" #include "WAVM/IR/Operators.h" #include "WAVM/IR/Types.h" @@ -301,19 +303,18 @@ bool Wavm::load(const std::string &code, bool allow_precompiled) { return false; } getAbiVersion(); // Cache ABI version. - const CustomSection *precompiled_object_section = nullptr; + std::string_view precompiled = {}; if (allow_precompiled) { - for (const CustomSection &customSection : ir_module_.customSections) { - if (customSection.name == getPrecompiledSectionName()) { - precompiled_object_section = &customSection; - break; - } + if (!common::BytecodeUtil::getCustomSection(code, getPrecompiledSectionName(), precompiled)) { + fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); + return false; } } - if (!precompiled_object_section) { + if (precompiled.empty()) { module_ = WAVM::Runtime::compileModule(ir_module_); } else { - module_ = WAVM::Runtime::loadPrecompiledModule(ir_module_, precompiled_object_section->data); + module_ = WAVM::Runtime::loadPrecompiledModule( + ir_module_, {precompiled.data(), precompiled.data() + precompiled.size()}); } return true; } From 0f7eac3958fc3105945981b138ac8a2c19eb2594 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 10:28:59 +0900 Subject: [PATCH 12/18] Rename wasm_util -> bytecode_util Signed-off-by: Takeshi Yoneda --- ...77a7f12734ef0bd58448b3b3e7f7f7c3604.tar.gz.1 | Bin 0 -> 98125 bytes src/common/{wasm_util.cc => bytecode_util.cc} | 2 +- src/common/{wasm_util.h => bytecode_util.h} | 4 ++-- src/v8/v8.cc | 4 ++-- src/wasmtime/wasmtime.cc | 2 +- src/wavm/wavm.cc | 2 +- test/common/BUILD | 4 ++-- ...{wasm_util_test.cc => bytecode_util_test.cc} | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) create mode 100644 57bb777a7f12734ef0bd58448b3b3e7f7f7c3604.tar.gz.1 rename src/common/{wasm_util.cc => bytecode_util.cc} (99%) rename src/common/{wasm_util.h => bytecode_util.h} (94%) rename test/common/{wasm_util_test.cc => bytecode_util_test.cc} (99%) diff --git a/57bb777a7f12734ef0bd58448b3b3e7f7f7c3604.tar.gz.1 b/57bb777a7f12734ef0bd58448b3b3e7f7f7c3604.tar.gz.1 new file mode 100644 index 0000000000000000000000000000000000000000..e42673a2d8d3f1942c037d5fe3cb3c70c81905b3 GIT binary patch literal 98125 zcmV)dK&QVSiwFP!000001MFOFbKADE?q~f9jB@To%AsET7N_pbow~M@=w8S6*iJK@ zPR9e0kc65dbO6$_I{oo?cL9)~B-?3|x^qsG!u@?%=qM?VXM7Z^nNCFDqAJa;{-YtyF&B zxQFg9FYe#u+Sz2WnodQQzuws$4tIBV`R-_Ab9ZZ7jQYc5=hgQ1tKrsgOYDx|PrUWA zzuow|d49US+%?nccF~!0GwsB)S!be5-uYBR=zZcGxF2?RckbT*@N<3tZ*FdF_rKZs zOIPl$uYCW1mj1g#{+mc|gf>!Tch6z{|Morlf4Qvxoj&OQQH1!F>wml3@AjWO`d52> z-u{nMo{c*rrKkL!&GFFw-`?C>-v8UX8=Fu2{}HZEr_(qFB^G=v_SnH});LgUG0l$U zROWkZqu+1r$FVTxy-MUr3Vk{n83A`Xn~g)E<&8K~GRuYDPvtm69J$9vJT;=R`u({a zPx8iv()l2Z(;^YZkL`B5jYgf7Gp%y9hM6=~^NR`4cvEC?4spkvX8RX18>iw}X2MfE z7b6&WV4-a}&&7s5Iy*_XMk7Yh7h7aMuKY{x z5WrWi|7Yw#%@!IXGu!NM_SsvdAe6G>~A>u|yN3>b>}5ZFxloGH!tSPQt9D`a@CWe%7lVn&VfIoATH zB+}$s4vV}dEzce-IvfD<;u&l1U$DVNll`!NF}R3;#>c_syVDPs?Bo9V`Toh};OK&# zp0k6~lf%K~;PeDOyfUIB|aXZtZ&4egz&H>~1uIXT+_{JF!Ych;YBO|DVm4z5j#$e`{-NCI0VjZf`vK|3|o<{Qr~x z{{sI1pZ~Pp|Bt$V@YEu^QHzciso+MCuXZ;;T2j?+d}=WGgH#_kGz2BH_Ikf>ibR0{ z=AE&~EB7Bf*ZH;_JCa$#x~zkfu;z>Iq{%v}`WVOc&oiv5G}-SAjCsa7H>}y64ZHZo zEyNB312>jtVjX#ZFj>3GVIfmnFS=um5T|f;or2jI(ghdLqlie4_UPYSsnql;TIJJV z@k;0HZ2$7z>wndy1diy`jwR5Yi7H2FHi>C0A3h&J-5)n$);{X*@}s zBl#ms82C#>F^<;ZK{(NUd=OTUa2kz2-anXK2NV&dN&SN~nE z&&GdpoGC5to#O%g*Y9s^tknOvHlO-`k8#<(*Lm@@VZP4mv-Uql(ue1GsQ&kId!_%s zwXyY-|2@W)DxS2O-|GT0psP6U_2PIh5hK$b{+2c)){Nt;R07o2i)Opw29wQPq0L-@ z&0L|)^sFD*yWv`5(o{ZwaC&xm0gpC(^40pe37H^#X#Ub>?3vFd0dK$$*N~31V0vDp z`PGdyawt=oFW77LbF7U2N`d9PVh+8$#wqHiaOHt;PTbp#IF zyt1gU56`I#IdBvG5;cISXYBIy@U#VhaU$|- zF4}vL@j-U0C}9KilFKQ`;^Y30@1q}IwEAKGXS~b$(St$+srJ@ImDK#T`U%UcFc)+Fqx{fD5m-Sj}=AL1uTCCim*5VYNF{8ZuyGQdFv5 z%pgq)Z-bt%EQY_L9BNpMV4(jI#GTj4tu+=tlYyn!fp*9h+=2mKnalR{*X{q$^8W{? zhexL$Pmazn?w#X7{I|8a+W*~r`Q-l};d;ToKa(og7xG$Z&c3%Ei(iW;K=@T$pSk}} zF3$%)e7GE(yzNetyXJUc|8H)r$^V}EzmIc0WAD@)i`sZ3$`+>^jgR7a!cui3@CJ{m zO21Hr#u^TmTnTH${sF2D!$5*8U{Ak_IPbDc06G9lv}pVaB4(V8#GIKamNLhMOawq3 zAcW0<%$3zg3eR?R0X#jcxKX++VDDoA9*=W18VC2y&89dZpef*7O=moluB5+?YNMpu zr8YwgZqZW3be5`x&}~3r)OEnRcU<;LU``qqO5wW(v0<pQ^{h6Q^h_TSj(FnfU7Q{GL)jYt*DX1W%sP~q`^aGVjM zVdp5chPB#e1|5yVP6Tyh6j3yCj186yl%+B(@S{-1BEwU1uqc(mKVD&`7)~Xs_TYG* z;4QX8m>l79o`do5R0FdMH_moFM56_4W;hBS1;0am2~K5YL9Drzwj(kQ_%wusV!;xX zJm@vI9w^*Zb8SV|c$qf71 z_W7P0b~*!fT!3*vdQuW-R0Jya!L~9(1D%2Oz+{sm&U@{z?9}9c&h=UG-}O-+n&bZX zzxi@wYqkEfwX^dS{~zJ1rQmC?db|I=@xeiWi2X0m3a%Gyv)|vo^Pva&^wj>jJUV}W z!S+uM!#4Pv({uLW;wWP0M`!1!haV2`>xf1j4lW!hJv|`;8(nsYg%e4EwcBvql&2J! znII~e3T}gZ4)MB#IEj6Vd~t!N9khTggH8{=_IW&xEu%R~0K%HB)e!Kw5Vk+YHh{iX z#dyNLwQ(H}1*o_n__4&7(kqNr=tIpRAY;Ua2hrX0BA+NNf1~*vopn#-6Q1Kqgt6us zo?lpM=6eRjn5XQBNUtyf;Q^zNMJ3qy11g>i5Ce>LWNfL6Zb<+_G&MmSl}3mQ{fCs8 zj_8Pm7VeONEvq?7ZlFIJ0(9(zUF^wPbY$bNsiaye-0P_6s5EIQhP7ndKC0$IN6enf zq9YWU{W(IM5p#QF#oN8TMG}D6%ribF6ovDeBAz(LA~uI48kY~+r+GQi4ka^}XiY$+ zC4m!CkD16BQX0t-NE3iujHFvT{r_q+2L+tqJ)t58@0D3xGXd!tPZ3BC0kn-|EJ2ku z>H(jX$^qpy3H#zty4eo34u4T5H!>-Z7C`5~J{$pY3*1Vxe1?SV%x(fw%ZjO4+|i_y z7t5A5(*htNp2wlPgoZdCq60}_vp%-RQoMpIhzFaHP8-qL6$e$_F&$>{3&WEOQMvbs zkRxLUM1KE|!+9rBz!%mgutF09JHvSyK+ko!@Yo(rK%eLq-vLQ#8PsJ5%DN zU+~_|b`(nY=IXmtNJqDl=NMZOn zk?|yO2B0j+YjL|{>f-Vqo`GoGK4AhRthE0GB%GSV-Q>?#2s}~-mO|3!FqukeQ@~?# zEHjv8Rp+bz*!!tbZTm-TS$s}ND#bhZc7h1*?5=Y1ov3Wv* z8{%;vuoG;1w7t^lWwa5#{srtrL5wVgy22DnN2pPy^|0))R^!Wipxm;-e5C;W8D1Al zOFocTO($f-i9;fulCrX)r{Mlw%tyhd$kFSo3=?@T%rY|vdLDO>brI*pp4$pE5&7{I zSmCuy;qKmO5dxK}fS|DV1;QMGDDDO?pBC*|vs{xuP-NqM>6YOkk-`Sl3Y>9-S{U+_ z>EF^yu-5ZKZ-xbaQe=DBABgzyXP61MyC=6L8 z6fz5wi>V1+IKXX|j2jn*qCCwwC4cE) zjAe|7No4ogI5)jUyo zSnGp1yUo=tyo9gIW&0iYAmj-Ji2iZ9G%1?^GeZIP1dvgXCkLj(d8$olu#A)CDNY+J zkhcxj2zZ0-XC2XIm%T+;h0|7Nw>`3A7ljS3&Q{kZGr=|sy|REPS*wwv3jv-9#St#R zVjxF^HxoHX#+x6wzBHLj#2T5(I;436E5?r!0txT0qd1$ z?$0;Egg)DXCt#1w(2iF;UFFX0sQ@e%N;6A27<%~)@N7e^p>G_p2=lfO=9j*h!1BtB zYr;AC7OSAGKtX35o$h~tc3SSRKG-y*9C>g^!PtbTjm-gEYoI-V>p*P6Zv>${&k*I& z3hTYLHl2d|wf}-gQ98GZDgA&0$_^EhoAE279s}vf&r0X^F*IPInxu@r%dr-xT!Osq z*kEzPg(VV7xAdEtz}Mfomb5!ZcuK%$G(!5=7jFEPX+s*UGT|a3xIaK7C90>#mLCXC z%vRAB*ta0B&YYV9Yv*OG>$1TJ^5#y188M#!g%poI(<>M$pPNGFxYSgPZ4dy7dFCrju;dl*b8r+BEaS$d+7+F+QqICJ z%j;uGNEOIfC|0*b51D*2>UN4xG^#!3LY_xeHag%IMeTW8;l=~D1itjfS4!8t+mcvU zu-#?nBCHH`%Xe8y&$jG^zz<4~ZEF7L9+XEaLD&eB72xE^ju6qn|Ei40^|aZB@H;$N zRHZ^Bkjk{CLRc-^PJ)f^-goW!INRcFyHae$VJD2(bEls~EMbY%dkUbhs*d-w)rE%d z{8SqIj>4#)a~RBN3pW*%#ykr1cU#oanmRwAShN$HJ(^&8baACgBTY=*$0Q74>C|VA zgPCo+F!H!LNZ~0v0FIUy7ff7ESQ$jb==BdD9V2Jm5xT`hAa05RFhM4oSKH04&6Xh6 z@U!ev@v4xU^`4#vF_$O;v=C)%S5&zjN3F`*N>)R4U1&)gomQ!Tm-wNonqZnV>aBOnVVd6Xo4|ujrOP58J-) zlHku8^PSKl11g?%C!tT-36Yh)0Y!vsqI?R=8%ZLvq?mfxTC*7MSZx01)w%4`NWi{` z0b*FYnW$QYCpQQO=wjLatYGfyTdWmPl~oXIrDDAW0853hKov;Dts`U^OLFBYg%ahi zLGV>+Z%xa{k_mc6YP5!%sMj%nEn#Qpg~gBHx|n%GAL#RWvn|( zR~6F78J7z=7U~Vd>hm8-%^b`kHUopPBrJ4IeD~2lf1+}HsO;WQd>Ja6l;O4=Q+kJC zgjh2Lp6d~bu#F(x27yZ4L>67x0%~9KJGlP# zcNH3{G_`!2dqnHu26TcUom2{eUrn(+jog5g0e8f(K&Of_>A*_uN`2PvCa*Ua4c3GJ zE2-TsJCue}Cv4h|*hj#hAeTk=lU_XcTVU<$=cU5j-ZvGiE#wu82FodGI2y~BHRZO~ zznN}HeCFHfJ~_4Ts0U@zY6n%Xn@6^&Zbd~2kzRGNAk53b_)}1Op~oscYRi>#)gg7)nwM%-m5Mo zkZA{{7T?Lr@pa{(WRQt*Dgk}Pq8*jp?xXj~qU>Av zDRVr5VA}WmdIs{IweW#O8LzUGURLrI0a7iW@^QU}k5Bs}0oCCE`ZWqwkqw5!h5}$~ zTL}nYY)uy%a*n9?&{%T=zOh`bZOz;Rw|jxG^`z7Lr_+;8OJIiVuAu0A90x$+D0Ruj@++ew1+sd^(R5-*Np49 zCJ#HYFkm?TROoUc&e14~={&iS)FgH1V&QrJmY6@>;K^Q^L`bm zgH7>qg3!IbU6-4M_qN+S3XLa9*(xYiI%~~#s=3mUX!0kKJ7Z11|AZDXvt>}{{T5_* zVu}YdqcS!*v8JAPriQ7jLJ@B1q1!>^Yg;X_9^5Z3zmndAmI=l?HOEZIrjn(=NS*=V zYJGH~B};>DNQt>!TZD?Z?rU_Ul^Z2~3F%Z_l**%5m7>55Tum5rCONYH88^J$?0gJ8`Xm7 zg#=?`pRM#$Estgy+3|@QqQ(${nzbY60X0!@DILQw^2N-CTwW+5>a#WNluzrtGVxXO1@w4 zWxG8_fkLAO8V^h-48=Y__}Db7o(du z|J}bF4{CjoskfjP@B~o&?KsxzU@vX&?afN8+};Dvf7@<^4x)ZF0BH*cz}?CQ)#}yj zI_U<*Hy!ox8+h4p|K%XN2AcV4lZ-c8tA%$hE5i=yW+b=6fh8E+P`DNhK9OAUaOZQ~ z{364IBUrfJuheP4L<~SW{AW%;p5B0y@-Td`> z?)sws|DS&R{)a#P_{5!mtLxeOe;S*sv26p{a|2~|qyWY_L;m@+eef;AOfBf6;j(^(JY?s%=vBN{LaQhZV^5*~Sv3|Sr z0*A`o=Fq_Jk-MaYfR9|G8t`|63Wj&JPBD=)J#S7T+BIxH`FfvoCV| zS43A^*3JIq(duOL+r`i@y_)a-2MtlXl4_f`l^-v`hu1w5@&D5`TmB!u0_aTq=InA= z|GxhjPv`$3>p%Mb7pK1F|F^ilS#|CWF^r$|v-HK?$teYw_s73~&{Ms#Fyj7?!~L79 zo3-zxP}0_iGYCcu_n}{0e>^*S|9+kNKYTdaCfU|*j2tUHTpFwDQ+6$Sj+v=Nrp}R_BIDWl9#4+;%RnoTJo$KWb$J22`fxNcy-Ot6 z{i*3Qb!KLsSvSEbjR34E7R^eRW?N1@HQzF&UQ0>Za{@6dPWN7G;o?g7*^>1gYkzp~ z=gZT&yrJ8R`uCA};+gg{PXZC{I+xywTx?X6#sk+1MeU8PxhYr)Gpk-vj4~0Oy>^*( z>>;r~Xr3#+s^>RP*k{Gk#s+d~=E<2XA)sEfQIk6{pOu8`3$} z8f$93gj}NvwoF;*?(TkM8H3Q7dGIY4n+xj{qiR|^qicgDa(0oNZ_RcaIb#N<7CekW zyJQksog18s(?QFe%ii(bDHVyH;UwzeQ0bFjFRnpKp0F4IsrHYLOg1-KV2a9W*e0<_ z5sy-AKGd3e=k5?xHdHd9+SJ)Jj>uciaxk$ca>3Dr#R{I0e#kN2*)tzzob8e%HqR=Es6HwRa!+~4u?rmb|<$t~ZsCue%sFG0CSQ#JFubJvYc zM-GU-RP8*Ojw}ds0z`Y#)}@q-i`h39T?phI`I=m4AtOE7DRoplBr z!&c5+cL1d&L#`xbX)?`&TEi4A3GpS@5x_R~HZ}BB@QsH*cj_u6uH&rD0Ct~JsS448 zIpKjeirFW_&y z1y1BN*Q{MA5riWrWU|_lH42F!Aa^-Oxdh#fMZh=R3o@N28)Yf-;R$c&u{tK;B{LQr zhiG{H86#Lau(>uzRhybU_+g-8*aUF+))jEP6>AJ7?~8~0>|_+Y*%~ZI3NOI&$98=9 z?0T-JSA0hk|1})S*GB)jUCo`GKt5f5T;)u;_W}a?K{ml7xe4_bUOl}kVxC^|Zx?lW zy?P2Fj&E+3PjKIffxo(?wDLglV!G-*3eWFJwT35awvZ^^WP%2>q1)zjvO%?kI4r(& zdEV1AzWK7He({>D-{#d<#cTFl$W)y?bep2mm9d3g1LQX4ysAY~A6HYzLM2rnko-6_ zl>uyrxyUo@~*9 zlGx!(X4!9sJM-San!-~W!7w@ZoMJV?P@tk1GD>kSDIy(JsJ?EAi5W@1K%lcSB`L_h zm-+Yupm-V)o?V;k;pUaMh<=6KlkmesSy_-w*D5h+xbY@Ivm|dtUu6jX9Fz$#eXL-k zE+SWZ{TVCs`HLWB&(~jqpkgveKo)tqB573{alh3n{;G;64io_*~en3$a@ z2$V$Oa3SjO5*$o22LeK#zPRI?;R{wDy46I=*~>4h-HK0ibIVVr8>HG!BlhzeS|@4k zL+8rLQ3;g05$&ddlTdLC)x%gzZA@~YNDWdV7XVU+cF&-&dLqGW*xtnSR^9cZxrN#1 z#xXV5b*)hH)|S$%_K`)UlIL#0YO^uXD#@Kb1u*wwZ0eP(qcfe+n3o!Pko zAlhs|xD5mTxGPUVL%QYIdU4qy14JR>`PQoyy|03cx1 z?6hUB9;iW}N~yQd6KR5~#6reCWmJG4BE2ogkY;ArR~2^iQF%lVtmhQCi}kHBBrZoV z7fh=4R01GA#M(SC&pB2FaT=|uhbx4Kic0{RCu)N$_B@*GD@cvtmF<9M zO)xoDXIz4??3|KKEt%L#C@rYqYv5)?Wb(n;KK8l+ljYN|=+g>-@8ljMsOB5)3z+ue z?un%kMLL$%b1y_Lkk#2*vN@KRtBrz5F_vP8Y^#Y&V2un82A|m{@O@t@mc+0H7P$$( zJ*V6AanU-P45J{<&Q?0r?sRSl+nJ`65CQD@(nIeFx0A4Fd z`P2k{jTfo*Mk}<7n(|{>?~_c!$%3iir2RSIe4^hn&yBBm9d4vp{Ah zk=Uksm8_=>)?|aJChBKOxf7msMfLpEi_`_gfs+NkK?uTK6lLZFLf=aD!6{cY(q?Tk zi)?g9&}cRgkQuy-`eE7fG?K5k#~;G@E9~7cYuJkjnKN*u0>Mwv@=Pp6XiTHq%uR{{ z%CX6*fmuPCL7@RHjGyo~jDFesEsyKzVRp^Z69PSWX!68OcSKKfzG@v>NltkOP=`QI znE~!9fYnyxxkP8ZcNU52862Oo&fZSyIIiY45oIiSVlW>S6NF=_p=RrpNz^JhZiUnU z>w!kWD&)}Ms9r|}9oLd$S0*-#FW05>=jXb-;nUS=8sqdde}OT<>(hy8fU{k&4HVlXk7Efx;Hg1gGQ{ zs_z<}3P#(ND`Z7nTIi0XoWp-MH&H*@lxIe|W5Qs&?%ao|HqMTV1m&pk&*|tLm}^SK zg%~UYK-jxRzGs5bipWf)G!IpR#}T;MVb7_p>ra^LxWz!7&E3^RwRDV{nySGwoXTed ztF)}L^)ZH~q2g_2WLPKLA*DpprIaRnR*+0nga7o)seHw_>|2e4Wp;O~(bZrOB49Ge zJCME5aRz!94>fdd@GXk2&`4Z(X)^4*#l_Rj`3j3=<5K|ibew#8R8fWq zoI6A;mF}Rh5h5n5=mXW>Oz=v38>~-0fWDEJsv-Q&H7o9y;hUBt7}7+=^9kbc-#;%8 z1W%s3tYn*lx^pm^0c3ZtAjqA;V+EIk2Z~Hr!NCnf>xdU>IVEsbO$8MEaG`wP?{@1+JM|JX}ZGmda!b zi+T>`N_)Q}&F+3Xf5O81fBxEaB$hITuU+|?Swk%&POSjDB8};0V2}53f=GZ;=q(Nf zP~?kcle5RGtI%Iubh54M>QfAC8lEfKLO6qWMF*}4xA(rd zG&CWDb7f>Z6^JKVk+Y7_(7emBRc> z4iQ!_U|U8PBMlnyaNXl27Th#TJe(k=I5&m#QL1V-#}-7|cyE%g4f5FAF8jC^DovWu zoPoj-YkGm)C?eG+Sp0D8Zni6iK1r$VOmD$WuYe47RQ;Hn)eOacD7n_aqrq29z{Iq6 ztg~*0As~=6qiaa1rUZuU>lMNXzafO{M0w{yyZLwf&D-l~ovzMbduH;RS3Qd1x#3$- zsjHMhEjXwiK#o#@Eb66qQ)L-iRnk32Ra@(90o)rZk)d=QG~)y>l94U1N1A;8J*NZ) zycXE7^e)0g6f;rUmkU)A<%VrpHfvdSHTYAutf?g+fr6m>v*^sWElKn^<|mU zzV_f%uRqfQ^oO)FrFa;|LcNm(gjR+8&S0@T>=lBw7mM^CDJ2mj-UM4fg2M#Gc|c`1 ztb9lm_fPb@Y_rH~H!E~j-AZ;(-BwSIzz16Jo}hS<9f+Vu8tm(k9<2qxuR%89z_tDOrkSL8{QjDzF^W zrfLvkrbq4Pv+odAx#y!6r3$J-lQPCt6H|iST6&3! z+IPJdsp3&<)(Gk6w_lKUnIibD*#Qbm(#Dns^as*Mm=EF+q63C?8iqAJH{%>Y9#8aS zr#2FI-6Uh6pIb4QCJ>QxR}4(-*2vaCAVq{(zzL;s#%H!J1Rr#-idsi{2l%H{eLr0D zTjk@^pYJX%pD@+7)9ZiOyRzO!k|XVB{R(aS#RI#Vc^?f7b{@PB3oO=vF>ecl$g`Vc zwIt~1nfAi}eIqi9WRVn0txVP|b}<}aTB2A{!Tc)Y$c&8dWR>R9i_l;$z(z=EHL)TJ z0ohS>DN-)7Al9=0(~SBAzJTF!4mbl1hJ?byi&?UHIU(NZKVaL!Z}^_|bBljj@Me-4 zt0=@?xCJLL#xh{)RVigp#1R9o0M~B0gk+aHDHTMJ9`Xk;r!NO!jUHh-XO~`lhqNhy zg$E~xIfLLfSTL;_CZU2*KoV}Gh8Q%1r_>U__Zb`~grp9#$0*ggsaPt5PWH9gAMyR+ z5uWqMPj^qlJyKz(pD+HM05l(MiMl{bip#x$LBgYbrU}b`a7|8Uh`AxC)?O(O$+5^5 zgB)-j=fBgotn#QRRbT#?50}BH$RJl|1S4S!=EM6GwPuk}Y5*FFC!!@(ffis>ykju%8jtwk8WUJ|1J9cYS~06s zhFn&JmrJhqU0fz7H_LD15yhiZkO!xlP71iD1qufl(l+t0dlKcR$IsiucQYR8I5|D} zmh&J76}o#^hIIR7^Dy~LdGn{u)8QLnR&t@BK79M(d0%SzT5h+yC=BRxN~eh9heE!8 z*{V%YIBZ*U*kEbAQ|FX3yjDdBP=WL;i-+*>d4^1 zRk&+r@!+5-d&~19I&}>#kM8an-9vNeQAWpcg4e`v?488h4{aQ{gvHS?)Z>-`XBM7h zc+90wcz9Jo@S6-o#CW8 z!-N-6Y@L65jocoER{%z` z%@o^;5CdKb>suYCLJ-3Mhp3%3RWq%dKS^ zi_mD|Wu=!$-2B5{J7+dG$ECK7GHSRF1N<8AetsN2-ab#h`tXZUYb8!UFgqYG3O%kD zy?jv^_eKZB6(hLC6s?EHGRc5j-!|neh4dkKTSB z7jHO567GQ+iDfp1N*Y{}@C}SE3;U@Ae7N%m4uLT&33Z%{#6yx1rs&Iu*1qi-J_Gd9 zpn(}qjA8W!VuAVzBIVk`BBebr4MnlN}2V&!`I)a-fz|YVhdg|8{r6-(E|< zF5Lg~>F)DM`|sEKe^VmpY5#92e(V4FE4+3#>nc?O%Ch@Ju=e83OLDzo#|4^Zwxx|2DOraJSvUUX=j%t8vV@0rT!^x7JtRf!uqm2)yy%r;*y9uE!4J z1B6dc&kw~$XLs|M{(1HDORIe-28=3-c+09D+~~=D#H+sS?!5iV)f}(NT~_0o;y>ZL zkAwUkJMKjHSO1!5NG$U8 zORfELdJ3Ol4A6+L>jeA5cONPr#=Cd5ara2Qj?Qm$3qB7CaBpr>*m4Y)5iI1xdkSRi z?p+Cx-Sv*cuKpYZf)$z6LJflq`!J#6kL{&%P0 zFt#w?f3!XorLX$;*Z<*sy7|MQYh6`bKUCtJV@Z`s=iPTz;CELSL*)ipL6EkDwEzNF zuS$7LBNpAQ%jd8F<%ZgCy#t1wkfjj#bhqA?z2nr-YbqO%m=w>iYJc`dM7sO1&mb~U zau}P)wL#zMpZp}Y~LRD|5i~{XA zOvNmO#BOT`Cj?(h^>#3JB36}vpb?L5qJi^x>@*xkiiBoJjwLOHO05gT`N3Nvs`2_& zp*v``QoXbWGk8?>hRVj!4#rf>Vo21pXb1&sF;!autJ0&i)mHWLF3e$3^&4sr)ebPG za+X44+ey97j0W$$lThYHs|W9^xLrrVO5zj8d2zG z#5j*a2*XI?(LDY;5lf9c#7~=CN53JRsO1|4fYxlHo6}=v{EK!&Wg=;ZU?OEH6egwm zHH2z#*Ha-Sh-&rO-3%o&h)i@GNT1_Am9-Q)+gio-$hA?HMtIYFIi~Gc)voTX9;BCA zWd^BZO^31nd^=ueBrcBHSVwya)J9Q#sCCoBd<$w@&XCKYb|~>zLk+j3F9=;Bmg&Q< zn>6Mv_@TNBfH)ERt07tGYc7dpmDq=7H`&cw(5wnCfaihW#SyJ%5H5jamDGn|H<8b` zAXpW>AaVx+7e{P+K;#mbZDsYL)=f+FEvRi(y&!H!A{R%lp5eI!ZdFpR@9U&Y`WDox zq8G&MK;Yttl|NhnFO<`VRyVuTx1d$(vo43#MBHLXjqQb-mt%Jly4GX6xuNFJ85QhZ zkUbK#5F(XL0pUr@I5T7645QP_EmP81y~ z(^)fAX9O;U*sl3)MXF&bcPF7B)Vhw_&4hLyp`C(5rEqIT=19;|h~P>0f<{wFRxV#v z{)E;wzh0iU87xq{VPtn`2Vx>+DHLw*eBIq>!2m8UyBe(sbQ8qQAON}zwRd&<`0r#a zH2OPwE`-3ggjqWYtHOWRS`pIAb9Wwxoq|Ip=xYY!NYGM<6l%V;^TjmLH8l;G?CAYg zwJmWYD&5q5GpOuT9LCPc?YJC^S_+vhtKb^*!xnS3ldvjWgsnEKmve9im92t9B};6_ zEM)y<)J9*?blL*;&KhT~AqQfO@18;jv;svOygSXI); zR=d?p?l^NVWrEJIKNYX;6OnRo^G!ZSZOk}JIS7qyZN-rnnd0Zwc4wX)`8JH7M zOChuIp(ca2VNnIIURCnVRzK29vN?kWC^wAEpzS#9g)D`@-A4pKG#%D}i&vFEw0V!Y zlPGj%{O>*vBe`k&@b6?SH2T=AskyEVFYc;m>n1ZjKl-R!ZynoS#!{nSxN9(!Z7O!I zm#I?!!yMgtUIZvf5heGXBh7&=xEUxb)tO~De>q=BFf9xz4Rl%VW-}b;U z6|@v0drsTx8(JpEUPf^dtuv&X^L7T6y^2Gn>uty7SkzL;+&!fA*u`%=W7z=Bq!nO2 zYT0VNdMSEmu$kys4@-7{b0TXYbZRHj_T}_?ecyU|H}CLyOsaa_3+e}AmO^6Nh6?jN z-4a~wB&-Tuaw{6Ww8%4PY!w_TpL07Nhk_PDq_8H`<1`JO6Ux=)G)-&Agl>-K^GFos zhDuD`jKW07QV86CSy!&r(Q`Cds6Ah6bsWuBs+X>M292GH!^pJVj>)m8rI2~J3+qZ0 zF?M-rI43?~o2boRT2G31({RsVv)6GLDa6~sIgzy#I<;t#u4#iCxi6K9$R^&pj@!!` zK7&T7CoD|o?I`SIEHwIsG^Nf8`}W~4SC{EvTWdvn>CMlNe^G9zob1g2OoS|iK%sPQ zt$V|ZyDHwg`Pa{nKkC+7>$aD%3g>q+lcjhfBNOD&*buOhX9l8J=s^a~a>L-bLoeR?JdJq>t|A=B_{iU^FaJZ6&O5 zTbQ@5P)Uu&Io#@~XdyadMux~W9>&2VQ=IA2KSVI$EY1^&;S-WxT5e!2&7mT?%eh3NiZRA+u%*nMJ8c6#37Rkp^-HEh1zV%&P>K zORAtCZ?CS|cm;)|nU!>0VMK zD~9YShD#)+V*xRVfnXC77bxd~dx*rC^E#zygcNftB2y)+#qSBRPK7Op(B|$I_XC@b z5!B09tmEu}fm|Dz7@3P9YCIpGEY*soM=qJ19wPGo!Hl5{>4jd$2Q?gMUqR@xq=ir^7Uda^q9J0l^41TKRh2S}owiHSuD|hoL+pU1EbGA8=%rPA_nFr~Fg9I`vDV^m3 z!eZxw00%^{9!_%ZGaiA`))Mc*vJo-2&b8IA_oVHioTbosLW%`MKIQe(gWHUU(Hnfr zsi<-)y?M{dWH4izSxH$oNeC7VEi80S$C#PdL3upMsj?&%>rs$&kacyegPii zV44I3UEUzQY=kHpB4!PfCFaDaglQxwOe2cu6e3&7+i~Z;q116FqVBu5Rysle0A628tBDm+2*YD^ zDN-)7Al9=04u<*!0W-r5dWe`cga#B08*YD@xd>pVVcjY3D0DoQv^Xl8&-XVMfM!5B zefU6@BB`;8l8DEtoWSK513|GWeJc}j#6ZxD^>kcD>A90qWeWiS*f$>L)@BaXydX#u zaSI{!e7h;V^ncmJ=7Q8w#sD(9>QS?XDB62STySk!a2qT{Y#F?bf@D+@Zlo5$X2^cD zgqh_tBtuqb$8C&K%~`dHioNBiC!!WY27cX)#}HZlD&op7v2dsV3S?d&Y)?O*Ei4xi3asou& zGuRb9XLW7|^L5$Fq5JvXJv`Q)L|V7RdwUt!O-;9VD(5m76&XvK5nLO!5G#0}qSh=D zN)60Ciu`Pm@F)N@K{?F9Y%CSd#8>$IT5%~ya6`bPqZ3M$R0r0ucm7!Q6Bdbvk+X|Uvv8|^t!qH%e zSJ?qHCQ;Ah1qN`+k&Fh(9*-uzHn%WvkI(+|T|}N@xWkVR&uOXWf8Y4AdnOD!S$%WD zL&%I}030op^Vr)1i}ai#K15|@@?Hsvq>BJ!B-kdGNXTW0#hvSbaj+RGYc~arkC^yi82)A zt;s+#i!2NfITRcj)*evKN%jdG79dFH)=Z~LUJj+bu%!{Y^FLhxA&}DPtD?nDIl)*4 zzKUkgIE2#-H|vCQCP?SJ6@<`;y$hprT;-@eu>?SivwPZ8B`=52Uf9wI!CyhW&Fv+8 z)J|4sv@NtE3HdH$mK-AMtO61@F_LYjNU}%_crR?>;y4w87@mof+G|`FpFJmVs_Nx1 zI~KV#au3h9m&uKWQBogjRuc-4P-d+5jynn_P9&-WvRYWpc#51ym6LNWIdEryt+tjD z9g?2!+J3C)m~ zJs2;`tz{Yy)Y8PuZYz;k#E2}XvlXLNyHWw&ar9;?Wmyz9%Bb~yz+Yi3AJ-pmpKD`= zmI+j~Mv=pP7)Fr;h%9{?+D~+HZ*)*xF@m*L(R!FCNd_#kwkc;Rqz}R4@@(clLA0J# z_7Eyc>h*kPbynljYoTXKy&`#8RG*(VH?_R6p(ton9c7f##%3mYlCT2KNIXYnsHDLq z39uPmN*huM)3K@%0u9Enp@ZXGBp#BCU?}IRfF~-JI>e50pc7HcBJ&GOHzh8FomE&= zVHfY|Zs{5jkuFgh22?^sx&$c^>5>?F2q^&pY3Y`d28m$^C8VXhJBF@dW*_wXzH@PI z&dqzbpFPjs?^^4({{OY#ky$Gpc{wCWz(Qp?OTZX89`sf;H^LER=qdFA-}Sx+MK$qX z5yjgQhgedxpXW*K!t$1T+emqOynpl|BEXlW^>?i?p~CVE%h3!ATjI|NrQ(-5M)8l1 zwHVo>x4dX2x}ZUP_f6Za&i}{~wALkWn0c`P#sPTY{qbjdFK`i}iu6F{?GwD^Ysw2@WW8+*JJO^IqTv!Y1p z1Um2S)tLDJK9`3J6Xc*Vfe&H@UV2WFGVKSIQT-)&*Nmhm$g(mpuyF$hPS(!hsOu%@ zZOR_J2+2gJ-P+ay3zJzrz7aG-2*ICr7{Dv1oKGIg`u+HvuFTJQ%epW|gRYdChJa<3 zX`f1BSMgfif{vgF6xc~=Sd({aiZvS5H5Jn6B!*tOl08b$IO>K}E}<64tum%!p#V{^ z{xr^67f^MHKsm0d)0xBKyo z+BIuCg8>)DqV6NvF3xFo_F7QX}uvskxT@|}`Uv5C?)w4exnDfDTy%X%-U zOUcqTid{vb%HJn`?E-1aEIk&*osnrKv8hjhYH2<~(hc>3kYm%wavCsh7iFxEljz4E zWAAOJf<3Y2|_p-y=?ZZW2J8JOyHC3itH+_2w9PilS5g~`) zU_{Vq;5&8l3_hq&$Lat!qE)QoA)qyG~VgDMpIYi29z6e=Nhd6i;p9sQsSv ze4p@c;CSYZ4976+Ol(1m-b;qr`HS5#xW6{o!I9+;q5ylaRT2@dg+nZa!TacaCN1RA z#>MXy2dT7IEsOB?=t60%n~TkGg()QNgwrR`(gnvQ5YM%Lq~CHrrqcj4HqPy!;IP_S zGX!vszFRIWfN&GpmSbnY{RXS?7B3(adQTxovXNjUMBS8r-mtZ#?i$;mo2Mw?iGK4kjX!a6#hnn1)zdEO5OpZm6-<)ZJ4tGof!^W~vJSQzuXXV9EL#8lVGOeimhXZN9;)oh5y;kovQQ z_rvvN4$1z5rkJfJz%9Ui-KRrxFHCDqV`6tH1AWvgLVP>?>Rhn;TcgmefH{wjq0HJd zx{8BKi1-4b8nD?O^Ie{H*08D>)J;5&TQ@A{+}y!NgzCULx9%v$c+QTwC6hXc&B18B z=j$|_jg5Dm#~%SMZQ;iHR=bvajz6DO=}wfSR4q||!qg*?@!_^8tve9wG5 zD>guJLeW}7*US&Cjp6Xap4Cn*YGp>}Hxee-gXP;=TkjD8e!>m4;dinpCKDKVv-Zqe z7p&`d`LY(Pl4^(}s;aDRX-cAPe>k?r4?~ag{gn|`_tj;dM46Cd+qH5A@P3R!A0xb{ z?EslQbQr+phL*N*p4x)n+!|y9hh5i*_bBl4*;*!cn<`nDx99Cx)Gxa)vtHGuZ$0~Y z>6oq3KvVi%XE=+?qLPXlx*>7_+V2l@rD6f}TC*g8n(jo~CZ@B4Fbm3G!kN zxM6LrHvr0|(6KTa+dbh_cOj%f^Qw09rkf-_LFnRt1x-CPbgz>j{%+z7r>=I zdhgWCAB|ibh7vbj6PoJo$whf&OGkO_(?u+&etr;*$7)q+NiKI@`X*3ZRPmXKk5D-9$GSqXK6VV}zm(k%m z49;e^(Do%Yw35x3C>kSI=EycGLa}Uq*(J1bHU`&|W!4gtH*a4QODNpY_D(2B`Up6V z=AWoaLWeSC_zGBF(w*dj+=r1UC%=_g=XD<{#_3=@vFe~`3P|xQF7Hc2cVoomxj?Ht zkq$0mw*E*qJFJuKjlWC-zqx_orb>bV;&cnweiG7m3Vw=a%5uJW_65@bgsvY)+e@bd zq^F3<6Egu|;$-QP1DJvMEv)4(p1VO%xcA*?9dEJ;LFeyp2ElKEY_-G$(k6_`ae~%& zz>@6r;3B}{Fm(*tL&5JJ>Mt}r?+OGtJ=EBWIX_<_ZCO%Hzfi0MQXlV^*kBSf)5lPa zc2<`E*)jdbwy;9b%ZlQJ|1o(`%9Eh3tE;=Ha6jElqof)OHrVxuRZBiORB$oWr>PI8 zVPmJ$f`~t)M5rDvrdN^S^?M!64k$Y<$K0;C*Wx=6;&7{BHP!N(n5UsDVF{5yn_HDZ zKTv;b)(c$(-DPC41{N;E>tf4q5rHh#=kq@cd8U`WC{XtBHE3X<)?6xFz3+FVUHG25gM; zOP2&H1D8JC;r#2*7H-^yKwgoT43^HjMz|a>c|DFs_l@+Cq51nf6Icx&9do0u&t&^? zZTm6`%c!FxokHzD8%q04=pkC2R1B{~!ST9K#TSJa01t^LhP2g3Fi8 ziQZTwQOVDs;Vs#HKr=D?-;VmX{6Y&!j=|3LZaf>& zzj_cTm;{hLy2&282=E7V{^bgxb-1%AQ2X|i*#ZJE{(RHa>^D-TaZ}8_ylBUQSbiY1 z{Mf9Dtfco9uJSDzYce2X$dY*L4c+KmGUHu`&J1lrXXZ-Q!2crGpYFu0gLWXpHVt*@ zJ8g1FH)CQ;OnnRf@jP=(avyW9Lb)Py;ttAQ3$kPzR@zU8>LUus%V!QfkMtkBeAL893_dDOALBDL zNskxzK(Q_Ud`@14wK)_)6f%Dn@``!yzDLWL);x<^mrc;S@{eUN8tb;i>#HX;3hxpw zdlebTx#RfrpHM=4kt#R)3pm@M6$-j{Oa3qGF2QcOBy|iv6czqzNAyP**Sfr)PG6Nc zcS~Vi1T1KjoP-H_>JXKWulLM;UjUxgb8mssnT3+SXn40%5EcMD{Q~rfXYo6#Cx+g4 zp56Q140R<`0xb0*DNjF_Nht=bM~>b+3*RE8S9tb=xQVhnuGoRM8QU@He3F!MHRSaX z4?$%x{$Nq?h$eI~ zpFUrNZ2J>n9x0-UGTy!7KLQK=(W5K=0ELWYswpl0MJ_*n`rBb1LC)`*%dXy2pX1I6I)%jtttWXe zpgi=)Lu&`aFBPtCZQv~um`wFs`DR)kqcis==(6F|7)*z>){?lTXRZ>4BWD_p=%fo@ z$a;&2<9gZbCS3B#&(58A;$OlKTX6>fJN8x2(1_s3PP@)mrCs3F_RODjD|N)hkuR58 z>}t*8$XaPt?Q#qLF6*?RRAJWQ0!P074ez~LLmF_8+_X&f*apvXk!*1T{xqO=8w*Gl zKm-kBa`uM+0^p}WEa9={CH!|4XqTrJn3wIH2O1%eOM4Ww0;oI(E)@VX0W|(1UaO=e zpD?!Jc*wA+v&)83*WgQubnm!{pS9)QSl#54U|S3!rMm`rkF>>Q|I$t7;m(%cM-fmP z2g~nLj+%E4_J$u7tzKl!yuy4e31?Qpi7|B)&ARvTfhd9?wB^godx~OpZ11oSi%gc6 zx~_4}K7qCMFN-|a=lnn3;`?F#gfqpXd8eVQ?@-`5kK3t#=z(Mh7IIKrABwErr8+Mm z6Q(bM#j+%kAV+*|NB_MRGt?0py3$PtBdE`rtLSND0m^FA2Z71EtY!9}a@&Ij>d(Q~ zt08Y4UhXN}zucAn^F+o}BIo(ggVpE!s~wC@Qx?L|Cu9N5^7T8Aho=#!r6}|0bSHA5 zpxKIx{3KNjD`G7&y zKtDHcIz7sFBIWPJ*3t<;{n$*!|6<7!7_M#$d`f*lIQV2?=l(-BDy)TV!O~|cp{dRG zmlTla^EsK83WXi7TpMqAe7%5_WJYRCpNSRFU0^PJRs>>2*mwVu#2rAh?gM;(fTclU zir?Q4JoDuZ$3`6+qUz`_r5@uP$gJ+=<+7&=?;k5!k5S0VODZrbF>lb(I1tj+gS!)H zjvt?doZ{jRC!*G=*oSG^ikwx&CL-;f@YnC-Y0A6q?o!gckB!{?(-@CiPds)_qg8fU z$-o~MPp1}Iy+5B~ZrKP5b%jVU#VpT1hNXhA+;ah2v|VB^Lb?TtoQ;hGtn5@<(Q~Ht zSXFB1rMbRoz|-^Mjsfq0qy82OS_hc^0PzLmrt&Ad;g%0*Kh&7k_@rPdJy+YaoYteG z#Cb-|^w4w(qKt+U9%5;78_Cbg7aC32uIEyDJT}Bh8)NXv6NuEts!>q{pR9$-F8^Uj zG1$cwkAexRmZQ%45qve|pNRQjmYdNUFQn`^uyy0t_sHf6H+i@5*yHvH7%p!g*~}Pa zDhIdykh_GLV~W;Q;{%=m!wqqr>~X7x%lf|hf`%#GMffPzfe<%5-Nu;B8izKxB#L(X zk)D9(>u*C}c_)yK;A^}gUVb2U9%`0<@1es^`oZMkCvuF!3n)^W;Tj5Uxd6&G03$RY zw+{GGs;{X*&Tdeje_&G0nN|$S^=d^OeAC@tbdFj2#c=_JPZf`o#~NhZBxHR-L5nRT zf$^D2#NDgDd*ARV6yRifn^29cFugIZQxpF}y81bSzjcM*dutd=EeIp+io0AF1>rMl zYmv}$Tgu+5$p3QnN;tRcK5FXKLB!G&$2$Co`6qlq-}jR5Cvj-8VL!qg* z12)O<$J4!Qs!OI;+*jd^M@?HvLXe!dTN%OWlrf8-O?~VapmRm|q9}c?0ySCci1Bg* zo>`89T322G6&r9PbW81tSrT%|mwQu$>GtcF#YV24(X5&R=AMsLUN+fJ3FEl@e?47p z6k6RmZH|aYflu1;AR6vOi|Zf&;dC_v@_L8=!-&&7?Y42u$$A|Q3y}gK{~jhR8PJ@Y zx`GGlk5N>4Bi1`V$}WC=cXgoXRS>gr_$jE5S%`xmfSldTGevWsrm`S!hb3BqcR*}| zwm7@K?#J2PE)WimjItE^+P#k7`iDA)^Tf=0?h9ZE9|BDNF&AV5zK^==h33*7jR{Q&9n`S<|mF62p>vaHQZ-M%y?`zQU zzX-cDb9Wl-3A9BkvIMGrR(kw&B9P{ytM5F|W7NQ6v{~LZ^}r&2Hhzl?qq9?va{lIz zxVa5A!i-V-C778kW=RWL98w~3ma^E(ouKN+UXYDe{02{@A7sOlaJLB}q~#|AWR9X! z4C2A(kA&PcmqJwWFHyK2Qj&t{AHHf?jj{V@cx)cj>-{GEgcW_0Mg4+W(jTj)_0*z(YMq#k;D5PP;*cn2DW4~-Q$yP~lGj|A9n7N3k^#GGglR8SJPoj5 zca5;~TtLI$2k@p|`B4b2eP<2yq?GTUjFk~ey#uJwSEJdU_-tFzo#^66ms2w4TZ>zv zb|3uC?d4Ue@fzB%++L)AXnAeAtj1+tMZc=-1Xkv~z2KCd9ir1E+Ke>ta9DEQwzzi2 z(ryZux|v)&=m8G)53LS?BkRBK{jT%;%dc(US@VYtd$_u?^|j?$1SxcRGsPTaB^9p_t z|1MnWK|{r1ZE-xFX*>bvy&4QLKO47LyOBd*&=yvvrn4D>0vducua*+u*{aRWqs=+( zqlso-eS9CZM2>HISqolvDX@8404q1=9w+ayB(JKKPj*qDh{8#ZmGdUHE2bT{CG9zn zF+r`%JVoR4c(hD7)x(u;frX2J3v{JP547TMUai~!D!GA>R#)ZzVgy+yo! zr$B^Y?t^k{z2U(>w(z@LM5dxKNUv_Po1eiOu?S2a8SVL03Eqh}5svI}_vqd&C{|!Z zxx)PYXLa_;jX;Tr&S z@TmoGdBrz<_p%K40jYYx`LDKyeS4d=2A;IJ;OLkY!|*M2%>J0owQ z_4g=LBHk?Y=iPqvzD2ek#ju;X5H4fnj@MqI*B)eeTd}j{O zXBibZ{z-L_%x!BuUrU6cOIc?R$u|x-LxB=7%+)K6KLeB1(?GnM=Kt-ZD-jfYBsA~! z4*bm?b)xTgbPzRog=*7Mx-tCkBpcfQH zcJQ5ncquK$Zz3FZQ;yD*c?(<)y^z7f#IUg~>;ur+?C340i`%8e5)|-{vF_BGySN*E zi-a$$iCbXph*c|3ukR2p^s6<% z6}$*J9sQK6$LNy#e9PYyEw*)kem^{(35n7Ot6Gae(#5ZAZzy)1Ia8FIQ=~P9Y zD-2`axo1l?#`J1o_~}~c`_vnI6Xt<_23+Z%kAr~$L{Cwvk>OYd#{03AeB2-k#qRVO zeyt?C{(F;oG;}OJ!tQjXbF3cJMzZ zV;BkKi3iX_zyHpX%^n6C;Ys%Z(-QrnEe+epUb5ZnlN;$D3RT-Q>}jAr;y;{@{%nU$ z>(TpyU?D7PoKhs>h_pG>qr+YCO?#6GE$?Wpmpmg_vmaL~6;X+NBN)+66sEtT287tX z|143niS-;?K?Bq_u)lp0`gW-9*FA07P7k!PEFJRR0dSnNBbm&y(6{B{<@{LvhXl#H z(Al(G4e88(t<4=GES)Uz?!#Z?eaR@9TuUbEqJ>AE%8n$S?u;xnE&Q!k+|O z@L$03@1*DdRVu4%4F?Z1Et2xWCe8v$od>UzG#euvl3z$bz;&T~aakuR6hhmD+Wj;lSg_k@BSAC zTW9&QoJgQUeG({MSgb@q|K*0iJpOqRc!S^Qdob1mgN%VRl)@k$oW5TonJnCu*7R^{ zo^P7$QUx#Wem$mH6kA~6#CLMwYjUV5lZlh2EiKufpb&_%Yy4h@tMVgz{351g`tfc$ zfHgQ2vc1OABA$*L0A}`D7)HxKhzM<-eTiZeuvT22T=1|MKw)^sUvr3lKl;_HDh z(AG1zW)K~K18eY3O^z|dSc=yXK?sX~OHc@C(VR`F23^t(Illcez#=TwX4XsLraYILz%|Fzkrr|9*PROT$Y@gL0{{)X0K@D6p$3Z3BbJ=E+4QF2;&R* zc_%vbm{O0T;S0O_i*~p0OjrXa+N=WjPkgo@0f8BScgVem#haF(FfVLUk%Pqbb?j@t zLGsPd=!rstc~<>Bkvr(Qw=CqBSv#`vMJ=G|Dha%3bN_`PQG09d286gl77vVLe)d;fgp_(%MzU<14^QAT^GR)aG`q5(Qn zjQ=_ncg4%fD%bcP)>hQa2kXbOQGGVJd3G$(8^-=#0NwlM^lVheLyF-~&)O3YfP>6v zl!i3~TKu>C{B1Z-QQ$p!7xDp~!-z_8*OQ4|yVhYkK@uXC2QHa3I~Y!%EGLF}L3jFL z`pM`n9rvd4jWpT(i@PRQ+(OpuW^qCrOJN7SH1rc#m|L1D`>+0itO5*%f$`pg5IeyK zv}_4R)iUyxPMp*OETi|RPms93!qVUBoVz`XodtTc#d>1P`Nx^xVj zasc>dE(~15$L=Kde=a+e3kf||iq6;xxbfpRr;&2C^w#(+M{stko)&mQTdjSHCH|w0 zpwerkWlq>GK+B0WhXg!oYgyb9u1^>#V&m-r>j0@hYC{Xui#BeGm0oJP)6@+!qGE zYm%cGy#iNGnFAFhA39!$1~;>oISN&Dd$PcuCC^J|2g-F>#-}k_ECIjlgMLRuk5< zX>PZEs)dR;dhPdKEHfPyaiA{@CI9%>%DG=&zsLk`(uK7gj_KDzkJj{<@$Nj6OwVor z3V}45WCOc@{mquLEwIFkR~&F~(juU+9dW;(`Lr1&c*r~usQ=xk(CnC2q)EWZa?iL9 z!@Ao)mcQNJ<7mp~&bU~|TkHj?8i z8=t3*1lsoohYb9Q-_!sIhsIj;QYK9OzvXfY39gk|RXbmVnmN56Mjb~uVMw+5|3RGC ztqGqrJCQK0KUS|H*m3T+_y~h`ew~=zq-*p_O2!eW!tuCy|2+KW8ZRsHmh0QwdaA#j zyl-3+5CpXc?&N_xTh$0%duULPalha^mJ~y;whuqIJdKw zakFte49?;z$qAsw%ytGrV9t}J#l^d#eyNZNRKfjtF1z=(>-dtDK!V_Wuw<_a3;Gbz-HVjRxsGdYg zLrg9K$5dB8MTV0}>VXoJ*^8LQZJ@e#VP@zCI)3q=X7L=I4auq~43rkaGsqZ(fdH@kvQxbTkO!5?|QTiS}q`hfo`h&$!!InfU{gU6~lrUokdip%$^^&*N( zg-V$qW|~i?v_BDX08~mS`M_`c_49O*9ORlOiK|QVbOwQ8Gh3nGE8d9jn(ZT;hJrN| zyl5P#3Io zq7rGEMlY>jzb`2zy-4tj?lh+DLmPOMV~Ihdn+HvkL-%C_V~?4*wNwLEe}!aaksW0z zZSLKo_VKNzCoMMD>Vqq3w9$CPemV_|sOs|7*A@SIaz&?z}_9_|1|LV7v!KgrF}6`(EoGM+q(YyBt=dQ^da-PuyHAw}NA0*03DRT?wpT zTgLigtfFu;_(s_7pW{y1?b2*Mov(W*-EFDmp2;h7flV*z`2b04zAYqjE2<_Qtp!bA z*WApWss@pC>GCB%{4RX09_N!F+1=iE6hi@fZugPpb77ffb%^S=h#r~k0}xQI{)o-*CLV>EAXM z3b}LBlz=X^>Pd`+XQXi+yLK!iul53YD^rb#&nB{IB6zyRu>8cwlp=4Z7VSX=>+m5o z`a(7q2++uaOAdGSd8}ufsj+GR+@p$kW3B(mELn83DMM5f(Miu``ah| zVW(Oyyt&K!>a83%EW$)Kfiqa&_%U`d=(B>1Ye?JH zGG)S7N_iuURXA=$mAFT49q|U&6t}b81~cUDkcq9gQkl$7jwU81^>20^`J#s!3kYh@ zZ`QB-8;gasxO1i8cpTKV_Yr2I;Na@u*06_*0iX>E>vdB}w&A9&c>E>#wsS|@ zJY+Y?P)}RzFBN$zs{wZge_g{Ak)$#sxi9s6mkKk{#zbbBBY>5fg1*PX95XRP>HJl? zYNNZjG^&{vU8Q45?K4d8?vu$S;I;6hXn)vmp z7Q-ZW;%#~3H56g`=!&q6veaI~f?XkQHKu01G8b=fE37QB~1 zR(ont-DG#{J|Jc45~*c5)IX-4cHWso-gTmse_dL5k&JA3T^$#?hsa^qS&z8&y z05tCgWc!|s-vCAc918_z`lHt6LhbB$4E9?hrjl1UCX8`os;_Ue3@TvKSYWOWt)0 zh{mA4rp%6flqaJ7bT%`i+j@G@6C;f?rn-HSPhgBB!AS$YoN-#Oef zZb8`;aa^@RTE`y=11n-%u8pPt9l_(J+=Z)Dkd038ex!9Hwfx{bjbnPS2uZ7cLe}=k~fb z_YV$9-jFZugBNj|4-QCuV|`2kt(Mwaaj*3Tn7{K6_#8eX=qyU}Yh5dYH^*=cY|yg| zR#7g``&JM$U(-6+7)OC;g$VSXuMR3BkUYHJbT%TBVsyMGyU64o_)waq5jwI%+IR^G z48!lr5~n{~Xxlq*CMRp{i46-hAD%n#XjMm=)2SYi`}(5P;TUk6~k>izXwFUT=owzPD?E)Law8&9W0JjR*o zd}CpsTlNlQd|JmCuwF9C9oEf-tSDG}Rc*;G9x!{!F4Kl&suP+vp$6sn+da2N57Dgh za??ysh$a-73!`((*2SzeKE5w<4yKH6$~g~go@f247C(&n{v@X8soz8cZED&&h0`x9 z>qczqQPAN9$Tu)=p=0f!2iby*WhD=j&qfU$nmSM0UxpoKHP+VFF75pY$z)w_t8FBf zfwn{_B_xZ_!B8g4V=T@XP!i9;TjT+(2U*2vuGJ0=YnfX_FDkS!vT*cKI6B%g;zj;0 zeI*d68dbXZNyp~pr%X< zYbMVSv4M`yd$j$SHtE5DO01OBf5p*Lf}^drp`u)^lNK4W&GXpE(rpWJq2U z$fz#ys(&V{Hfxe?a%y^|gMM-w$N%`_EbVo^!HE};2fF~lMo>DtkpiGo!OB(=- zDV77Kwg9UkV0Z}zmJWq|VzK&YX|4(i{A539rjD08!E(y#@N2BY0_XwF;TMTXPEDwb zMu(Sb=;*=YiX-R2W2^2j9liym5=`=MRKVoCk(V^2wqp^vw2)@$Onp`CLo&hKiG5!~ zu6VjPMP~S89X5#p3}#;WTC~q4PNGw&vP0J>*kkT#bbmMl1YV1&SWxR4b#>T0f#E?SbqG+$r|9Kw0c8Q02?5c@npQPgz~e*MXvDn1V$5 zZ}AD`JQI(~nGyZ^Vo$#%U5$IqmPYG+2O8ighEO~ViCd>8|NB>y?R&B2jtQpJ#0^SL z!%X#>eLp|5`>fc|KJej2)J|o;iuBJBQys2cQ`!=JjuV4}$>uI0t&<(FgwB8BT1>|@ z&2;mUSUT4N13fOs{id*kfl*YU8V)z-Ieb7LM#@V+fNSCnvGN#ph@r?Xy@)MqId^*wg9w<>tzLFD3v}Tcb28(&?$$ltubX! ztc{G#3hOA1#~YGI!lEJ6=q%)*jO+X>7hF6y_);8O+34 zKU24}L88yf$Q>@PUhm#=4c5J!Z9g5!xZ5rGNa=cDNkE1#4LZp7YqA^b6u#utxOWW? zwVpU#A`dCK^qy@VndP1Y_L=MEXn|~)6uQe%#@ILv>l+MC2zc+ek_dL$Z~0TB$M!Tb zt!sA_>3`XmbQU$(*b~Er%7m~eUh+j_DCxyeLcV56x+}f0r!nHdsBN7k2rO4~#;MZJ zmB13V`kD`ab^p?DU&;nT4#yF4&1!eOn-Gev7e_^LlRRA`HJ#ZOT4xwy*>Uz?ejmT} z`5a;id3#&X`sjw~xu?r_c+b%Lzr6}fCI*pl8~{rQ+b zJ<${c>mjXoikllIK~2KW@Q(iM`Dy7t0Z?X8MTKKUWu@fa5OQ>Xp1ca@3+2V|Fa9Sg z(R3>|%WB&#Aw14`A|MvY9OlH<?IejouvE;Ou27O+}=;h@Eijv(*I_tVnI43+V`K z1hzKlV>ZoW#;~5dRhzflr~3A>;rpF^P$qMf{M0~C)H&I*@vy%i~;u?)4RA|KJ*&$|giy*A9>w4YZzxe^KSm*?Of-+KUN z^78fV-QG66S)>7pWDeMikS7a$oLujHq0u1a3wd2SH`1_j*6EVS_B^auwqViYTs^@w zKk}>4Va~Ny>rce^t5ZIhot+PFn%exw4k600ipqtsg9<#|n7la^yt);?lkY7xP!ov^ z@KrX@@vOC;kd(1#;=NA2ljVNEiD~#2V#hjv#vOede1omF`DB7}&``Q2;EQY()T&@( zoVvFLTK}1Y$8Jc-uL{eXK*jFyuW)eTdnysgx?lB_%27haw-vIzO2TY~@u6*DZ5u0Y zN!fxnL-=+~g@4fQTORcD3uqlRIm={lB!ue&ko)9oVu)Z)R!XAX^d!KT?ZOosD70&p zL$SZc^G!k(STcpE0^IxGZlJ0$dK|4ptqOD@te)wro@_2Hv>V2|% zR((bvTO;dD6S@{=<7l6mj^AD4gMs*Q@9NKNY3Q5+ClNza+l1O$%FoBmNvaL(VuYO4 zl3AE9V>QhkaM%e){oA!_3)jRMI#yOR4wut@B%AA2=B7J5&g?+@F?4!PfxMl@*R@n&yY=RQW zV?J%fs0&lDGZO`=tA_JqzZe=lEi%ZW8!@Jil7G(85ejY0NZ^T3WqaTwpCo@@-dw~z zbGadX=ygQrA*Xg3&wSb?HMPjij0Tr{dcKz0l=IVou7{?fUh=Nh-FPDsksSotoa20S zLL)^lo*53l>SW<}c=vO2 z4CP!{tN|UCg%f#iSBJiNToulfDt8A(t~65K7hbZ>Xd&JYeOatDC~lA3B6eYV4o#{OQu}u@2`)bW6yq zKm6K#;qxFS%-?(Uh(^m!^L{0wBk=V|;iIx^C(1FGYgcq~(hMsoqtDVSbKU_X$^`<(>#JvAL+$ zm*9-i^LmOO<+8zuouZlG6)c)zQmySuO;rrF&yS7nz1dd@5N3B~H8vI|lO+rk64TOT zt`!)|_?iu9a($S8b43C3E?3|2+-`VQx!9DURL4=em`e5v49CRIoj7%MVE%OMgh{}1 zzRem3$M4aMOLW0x^EOK6%6y5}KA(4F#IHf+$U?oRk~ePkB!JwW^cQL1_Xi64^L%|4 z_e8_p-YxUIRQgtLZ!u_J%AJlsvYNQ@b7k7{%0~DpRmWqC<{ukT$H#0gB-59|Ug~*~ zo;Pw|_5?^w1NT#J?%To0h7UldY~3GtgPyNlZ*}nHayfHfJYFY{RG_ij8aFtwNyK5X_@#SQN7 z5K*DxN3nFA4p)0g;NVQ7-Ui`a9{$_t-m)Vu9JSm?oSNORE~$kSL{H->ISuRSEd;<5Tms2mATDqKA| zjNAL`uF0dUEw2}&IY1U>SN&vy>^I#g*BkyevKzm!n4gJtRDo&vKm2k5 z`cE^eWc?z+ki))zF5C06Ar-y9I+^*^8VeWR#a$M`?CZLp<;!5jN3-9>x7By=H38sv z6f4gyzrfmyssH4hf8;@o65iv>^&qX^F9ee^tq~fmk4fuuzc--tDjzb@o!sy}Uk^kU zzJh%a~bLH$I3;ev5AgnagD> zazpbU98Z!4{u#Lz5i34$Mvq+c;pehEZgy7BhJf2{N2otOg@}4(he~N!OHuMJ$uTd> zc?@e=g7H|-ZWd1A5OAyC1!LEwlLUEgM(Vo>1{tyTy~(p0V%T!5jy0-eOkd3HWFxlp zUC!Mxv!|o8ORZW1`afwiN`vPNh3T)lS`+Z^E5kqbfB8V^)yAzE$n_mmV%ztnSEQl4 z%)9Nqp(G;Uqh;2P5?TwfpVAEXc30xg2YDZK;}v-NRSmCXr83u7NAcA5Tyc($gJ z$Ci)lKdH4jd;NR+^Doo3X&FwFM!`CqYux2~4CYPVy=-Rusp(3{Z=nOhvS;tt>A!rQLDCA+^$pcD&>Wgcf#{%M%7g< zmH8s89(K8p9oxoK>Zdr`g5&gb{UDs@uc-Wy%I0^iHT=$3pJmDv!=I!jTa zER@-IZU@DJ_SkqQ%P0EwM}`qE8G&^Zx_g#nFY&Snl_wM+x!y)PH^$&pZ+o6oP(V7L z_3`R~(a(xjG0_I~UQuU?0Fr?%4+4H|9&vXfU2Fduv%xj0g2fzU{#$(oa)h-eUp4k5 zF8s{Z^q{retaK!BBALij4N5(%kr|0Qj!*HTb!(g1JWHyApvcavykR&)%n^^@zvleW zuA$&zDvR!SD_W-yW|=0kRqjNTDH(%xrC(cHLTOne;Fi{zF%2L1S65F03`qiAE$k{3 zbY@Ny>7{rM#`ux*v0C_PHs`eh3CZA%`LD?J1@dy^VP75(l`C5@o_(S@Y3os8Wx6L< zLLqASZqnk*9ow*%XU^s7qV&Eiy1pGU?R9AlZ>lJ;r>SPo1WE+l7k?y-;24X5Uti$3mcvEjY=_;UTBtblad>qNt`Et9}Zf&E%^?4Y0iFsAfy&R`3R?&tE z#K%#bSV{VNGER3_zQm~;8oViwkah4E64d?JE*2P;|bT`9gYnUsmuCZZ8*C0NH}{HMraSZh&YNZe?bzn zxwO_HVD9O2L-8MUFX)o^5Bt0O2kH2qJDu%z9sl7ro;vLoYlbcBUH%;4{Es&>)D=cZK#PpI#oM-P|ygPJelL5Mhoxb=x3Hy@S zwAOHD#3AoJ&KFBxAh9W-3J;Daqmg&+Vy2eu4RL(JivalD#^3MBx9zFZ+0Y%gljFis zCX9#l%}g7M2q#DM%gFj@^5&}+r$`K=&Usm@b~uNSC!OJpsmJYzFT&Xf&OWmqcQD-@ zU}j!GOwQf_-4jehqY=%~lO6XEH?pq{uXWxcVC2S#R|!oc@Py5?UAgI`KBoQLWjUMI zI{K)r>3##aOJKGD*l?n7OkEOg)ykOwr;8(a=q`)!@dsSgKL}3)5sZT!!G(YA5EkWB z!oyZ5;s!Kn))9{4qLTOpTUU&vk2@axtpSPcP=t%S0)sA;6iP%nP`ZNwv43V~=u11I zKhT9$d=eXG;9c>>^LpZp=`fRYdT81v=2V23iG|C?#HU>mx|l+W@T*^}Z&-U}9djCf z%WDZFH)S`4KFHNoPaL);xMq`0+%t7c%y*we-M2p-;xNK!z=3w8k4R%U!&J{rXMcCI z=T9j*j9j8`XQL51wBmT6V_X8(3Dl#Brvuy!F~n_9)E!2UMD3PF=(iFiK|Z;`5@=~< z)>gv>sV#1%*BFfc2RwuSkSsH%@C~87lzu>h6AqjRWDu`4?_v|0(B;>g6%gH4APoK^ z6hh~v5Pd|Q0bNy5(4QrVtzgpicog<&&I!Xn)24+9Ks6@r&k66%1PefNL^C$WyQHwz ziAwo`r01^~~oqUpJh+STxps8xjBNXdsNH9Az{GQ|fBQUUDwjm`99| zfAI9Mc%P|o#(v-oQ+a*^QUMhM7z>j_%27H|&QS*$Qbv(|c$jb7k1m?jLnxOeh1IwQ zWY@19%@l)xrk{F7PO21sU@!+#pHtv~D2rfp#HWvR2;@^r?7aIs-;%c+Dj-~V@x0gb zNXVc?HX$wQ=vter;(1agxoU<|6O>r#8nYuR%{eL6y(_9tg--EP;d5~#B(H2}Z;<5E zP9yW8cOj>fxrp9nvL}ZjBzq!B^xp8sF7EZCYlp+*VJUHukd#{#|NkkBU@%6XaJOPv zD7LN}x)mXxa_TecRABp{@1jc}x%((MaStXQP;$DLIhdZu7stM{6znSMKm$~*?IIMV z!+EB^qF8)!9QJ(@|7Zz>0WfCtBBuZFjSLH1q9Ng%jf+AByVHUkQZy63h7tM?*vw>v z!;`5bd>Q#Ko|4BhlBo!sC{Je@$U?})1}G>X`6ipYVuBSTFi6Q}S#6^v4H7#xYivUW zezC`4QF1vj+_xd$JODhqw;^HK5(GvBhmk(df>2HTFq@~CE*SX5Ty#Kp4J6xHZ!;m>XRIhkh$F}H8^oTE%eAp`6ouZzh1Rs9}Z2kzL%*-M`=^Kk(0dLB|xKHS{V&gTq1 z=ZMK+hxnWKc|zet9oB1!$Vjtkh#^O5w9s8Q8e z9amfZ1Y2DUuwpQ9i1}{9dKc`URFBH~e}19ZX3dz7u zOzKC97Q=!;6W4PNJ_PIYW5MDtW*n(-5MHHEy%e8zma=uw3j2nK~@6RG+$4Ug? z;BZ+MVu~f)h}vo?Y|Q*yZ90TXT3R*Yt<4)SkuXoH?N~%rW)e!G@^Sn;b*{p_h_5bn zHahS$4XHe7{nvl}mpVkj-)sssOb%Qv2jgFmY)T6GxC&sNmic1jICKNECe}pa-pZ1n zA>^9K)a_@KL~9hOAkmuqgYR4UT*IoSAsJj9F_Xh5rx*3QFTRs%;SLRD<-x{b-oZ6 z!{l#f)*~Vj#p!RM)Y1d-B&980V|04cl1hlzqA|&_?cj9ZGENX-NODqv$KQuC9-UNo zP$mf01ge**dm-U?=2BEU{u>of0mzJ4vB}pwg_k-7E_w#eEf+h8&q_x7_^=I17Qx!- zN<&v=u-V%t#)G*Y(8W%W3_99@;DCl>(*CH=!C7>|%f=`-JoM6QO`T5Udc&g(NJwb$ zWT?<|*u^q+8l)f-T$@8bV4u?shoopt{4QzIE>DXV|A~>BMT|sjSkr<^*|!q(Tv0b2 zFnA$pH((&vG$NS>tP)_lRIU)1#6rU#Bv&hucS(7dVU`NLc@nRR{g^ASKF{O$9D`e8 zQDZkqSv^EP{YU7iwbM?l6o!`bVYOg!1v<5|Zl^aUzTzLKAa3G78EPjtKj?>JvLQq} z34(Hk0QzX_2@sI5kfK<#s16~-cl#Wnn{x4Z(WMuqO*qWUjd<4MOMP5Gu($iD!x*yC znfoV}s`TmRrs(J!ITJjNY80Wx_sqrc!ol@cJ_oZ&?hF9SJP*woNYE@uulhvvM?N4p zr6$zI%LYc{aK_g!yh;Pj=EJOM;DuNbs*GS84nn@%Apq*iK-eDKF)~;%9%4BW6iSTR zvP&@#^9quFar^+m>f>-0^_7(s-?iteOv)oPI!Oyl4@%MT4GyU^c%*$mwUjZ3lp(_k zp2}NjDGV@w!Xw6p+}g=-D3Kpd&0zoLRcPvCMrugHc;NEwdogX`)Fx|bnPrd_bz=H^ zcu3Z~`T#430LfAbCt1^O>}@dfV}4l4PTugl%0QKz4%LLPzVN%Ybd1T% z4P9Yb!|xLdWs9}2c2h1GGIM&oT@rS4WEv6bU8v-5-rDh8PFx5s7hLHp=A{FWu7I46$##S zU$~>;ro3(uJ{xG{I%3Nb^go|^>04Pn8jLiBgs$1I3JL-QYFPQgHuHt?8Kh=6W%pw& z&D6(Sf&SS5C>FiVH`!$zofJs(AddCU*qvA?MNCIt8T4Kk2*E!aTrMT2aD$>4{}2U5 z)QZAGdX=~o*j39Ry(~6M;bB??)X0$V&mJBmco=MJdn-s3j`pM&nS{jIS!d9pb=?I9`Q>dxBz$5LS~6wNjeGQ6N_N} z)HJ3SxnBufLtRylz35zc=6Roe&Z9*3#q%RXjhuCP(^O%2TcS6siV`D42(@Tch>|~l zhC9*fT7GHe6v-J|#Q-GvtHU}#_Ou{ND-TFR@{gq{yI_1K_Z9Oj&V-e5Q7y*F3RuNl zEcgR4JdvV!Htu5_dRJMjrc+Z}R~I6%{iyvDqM-*A0-U7&z+oG8>v1o7feH zqSS@5y^?;lAuHfJduhW2z;-8}B&F*joI951}M z0X{icjJ?QnOYH#$*|~`;mokb??3=WNeeyt%7=vf6JhFCR(#48YyvD_nG+Yy@`Os7k zTQ{tP$$s3AMK(zE4WCU%m^BdZVGQHx_rjDh@~4_Rq_jnWlNCCQ0*iVHM+lJHFTErs z5)K;%g}4q0Fd7=+Xc9em{&LI@oy}C7+M`lbS;oJz$)q#_%>k{hgG*pz#B3WWZlwHz z_0V}~4w6awXL69t=MoN*80XtA`$Pz5OrUP^3w65+C%=B=_oQ}T)?nrV!<$8zYP9b~ z(>TQ~jQG#Q_qEjYe3!^2%xZe%XH}A45(F#1kbM);P3?R#6Ed1_b4-^gD__z02rLMF zX1^+9Kw2Q322Q3*-dV8E%@b06-et5kN5t=Z5UIG|B@ik_1uqN0UZt0dhi8{hVF>c9 zE?B6>G@qH4 zuTF|?zr}6m9x(dTob(O)3|M%hj=u7vpe1*dLgTVY8!VhNEjHa1mYJn<>GDAJ8i{1m zR9}Qgl*le?Ui4aA5?!4~AlM+hN?i)`;`j~4_1A8UVz@lZ(YqKg)ru9jDzihznK3U( zn08@nF+0SYv5df)bJ1ht?`dz11t6wbp$<~Jh7)-rw(zPtPHy2^DhiaAjEr(x;r*g! z#HP&Z$vpyiLgeHziC z>}4Q4#@#^LKw<^%5h*`pd?!blx;=8bLgp78(;M2CxO`4#S|Lm6AWamfHv;A;b8!EFA;S6Qhw+X+n4AmV%J)+BmcIm_+F@{q`B&^wj$XX(3NBqJabuwYQTfT)S`YlB6vN=;MDojj<^3@Pyxsp@lNsfxn&+ZKN z6^vr1W|2R@+L?yu5eunRaJN+67wbilZn(-tDGtL|L}k%(Pf#qlRfWa8Y}%TPSk8ta zc`|wGYwmvWo78VA*Ui|w^db?ziwv&g7F$m6u?(*e(Ebg@%?tRC2yey_czF9jQ&Bfy z_%A6IC19_~#t0PrMze~ey`vww@rBhutWqA*JU>*7G>QIvNl*xil;&4h%83_P)Z(}FM1ikKL|fkZJ7Zqk$+TP zA%T3NHJg(}G=uDy6yq*duH3k`$bDP|SrM0?!qJ;9%w!Y|>HCecg}ec!+O4$rD8sbG zu)vRoV=92V0(lt8*bJCJnhG?U9lL|r=$Fq zunVIFL}xtZw92mPSq-C>I@5ZErIks#qTT3ZKyVA_Z@(cdsO5|a^H3Ee4g;)-L#g-% zL&!8j$Bkf<0mA!0PMbT`A(NXB9l4=JfhxQ}rO-G!YW$&wNrYN_ESWbmX$8s1Dau}| ztt-R&Nv$xpAG?4@6)-U>2Vp;GzACR%*4Crq|6Z=vbPn_4TB)I@~H5YKv{U zOe?OD8w+aHPQ>KoK2z6+AKzdYHNd<}Bnn(M2vgis15Ew_xEQ2XXM%S{LRQbt`}~=4 za|I4f(3pr^YCzhj;@~23zR`A(b#36C?)L{Gi-E}D@ZgUoHvu~hY>Xi)=~Vb9b9YHG zAD2VxxkflW9#X7pyId|xIwaNU)Rjka*R6{#bWfKRT}&YP!b^U(IqXm>7gC|YOdjfQ z3L!!mHpF6LVyI?Cz7>lMUiddM)^jwt#WPmCp;hBku+T~?g-xrBGv(v0AitMQrkR24 zIZlqynMK&5OlLxA%F!R)I1`TzMWYv)dn~kH_RoW^6qQgQb;UVZ3edh6B|c^V1(7f6 zDG`fez|cjrK$J)T&g)z4D#F7kT{{uD!qgF-TmUGdsWem9qMPOoQ5wMt6|6L_5`&Pt zV5SqgQ&PrG`xTddB?>3Pm<5BHJ&5XmR+Gbdta-QXIV7`wndd%(HR!w^HVp@Ry>idQ%JD6dEG z?~AvmG>0;-w+LatiDo#~r_0`ju(yo-{?v43vklTTN6!|>J+dJC7V0+4O_Z3J*#e6p zz6??lrkQRE1lkNuM1*1@Fa|>)HS0?W1rz)c6k)7ns_fMPJFzxT041(z{R@oFI>?fG z(YaHdbm`T=`GJ7`plsL8yMZ5|qdzcwj8y|;+Ju6e@s&Ffy^+zl0^_d1%uUGD=nlyY zMoKvx6}<4G0bVYWYtb5VT~{I$CR@xg()_w)Vn==pyxeVlkh#F z4p|5SN|a^NtXvN&SM`!MFNoYxR{kte2n)LeYQ0zqXvr*F7>~}9Xf_8m0*M-G*kN>0 z#85`G61>QjCtcKfg3O9>U`dFZM+|va%&AE1H=1;9)%m}?&!|L?TNhdz#reN>+6V1+ zD*smpns3+nzi#2F^MBR(zwTE4FPVHx%b8{2Ggo0WFcWLp3SpM5%Q26)<(JPcoA;^t^5{cfc40uJ1AHhFu!g*eUe<595;HnFAL8q z9t$Ps#WCW~aHte#^r3K0Dzs$cn?#iS#wtQIW}*b-m$EUyV(m|^8@&zHRf;Xw+(>m@ zZ^$;N_1=#^%4}RFRMFi8tkHiHu4QOC;4er~QTCURlmH3lV;(tc8KZvL&TLGqGKX{A(>DbaphrF~#VTJ!kJ z*7`=e9odEq?$H&l6WMkwB}I(B@}g`!T0j#jnuDrJp=ai=hYq!rBVN> zLZXFHogj@swLXxZNaq>!TN_=flLg(ec0Z?&Lc3C}k3zS=6@^|!>$1AH(;E<~i^UsA z1J_Ak#O|Pj5OXqiqjIRjV`@Ui4K%(!defwRc&0uk$aw5Kr0)U zLSoUtGN=XqCHd9ZopfoTRq4i3YudK3byTmgL)AK961QDe5D_A7sdL#5<_Z`b#$$#3 z%9#q<&#FK*v1yaJ7KEB3hHB7AbguwR$ff2I*CN=n*~CwUi*iv8Q_gCXB%wzvFXj+S zcP76_sMzYF@kegsv&h#b9Dixdpj4vDmZ~D#i7Dj(17*<7VtRdR(1E=D6HRuyY?+>m z3t_mf(OOE_C>Aqvs8bnERBRsap`_s?`(`BE0$mj50HX{r*#Ju;)9NtvQ3-fD$)j9c zNMO>rQsV*QjW(CM2WCDg7^Sq@nggcRjQ-X-XJU3t_e>2y=9AW>jFOStS6N^|f)(eD z;)C8wFncq&T@Jf;bg)Nxu~ceSAlJ(3y{^wE>iZDg%nI8qDl4-~7#Ft+*14`3DDv|V8? zbY*zRzSY@x70-NbbUvdz7XrqWdSR|<#7S)al2R2a4?kemurWpiz4W6nU~jV=Wuiy7 zXen(X{OxyV0c`lak=Gp#x@5ncKYYo4{qQo@{=~r1#XOcIyJE8|4!W;pca=sU3iruT1r#Mr9qG{#dJNTLM59 zx|}l`W)2`GY@ohkkWiqnL4==|-HKq#`&$7xRW*TQz~rv?*`HRJFql|iS;UL7D4!W5 zVh0ep!5|!$%-2NR(ZNRRj!d!`c|*nM@WNWG-_zNI-2Cub!yEU!0cSVC%VxEBVa5K& zD;94Hf@|pjGrEQ{UVld3T;xYcw(0`4t+m6$1S@+eiZ=cikZlgPF7O{d#&p&{hbcc;mc;3W+lN$^AsjJ%6cjJXc z!JO^XKLpE?4J7JE)k^xERY54eWVLoptr5|XO>su`Z3-_nw)A;CJ(ho@m@ibbDPu%O z?Yal?(R%)G+8WVNmp+3l{8>L(&e>`}wnnsu48>V9^_EVxs%i6OA-YlxsY5C^AWsy@ zFBxS+eZ`HVY))(=N~A~)IFPOyM6Rq=u@Mb*c_LYp$x=Iy&N~vVq4e2O5S4aJRFjr! zt7;>nA*)o#L%|3uIThz=L^Na-5SwL8u>0(%lkVyJm(NdLojhNZBMK&%x$>o9rmq6i zFD28%x9N+aW~vc6RP!QG)J<;q)YPfFS_>Y2dvFr1Vm0!Q zL{Jl4R!LqtJV7g@L>Hwn4JjF>DT3OMCL&QBdmc?WGsCP$ zZvAK*1plJrryn>R8kwB?V6t&3p|qey$mzQim&3iZ)FgGEe|Y)q>}B`;hj;(=-#Aro zx~FHq{sglWEIUm&G>cixt7Av_7eE_-``alD#%A`jR3oic%XtP9l5Oe*B5z3&cAPJZ1E|`_m!q{j0o~38nmOfDds$xP zzoB8}FptHoioxObQpnn9|5+7NOR!n9wz)=vPtDrq9!W84OVR$JQ_Rk6jR@9uuz!S3 zon2lnFW0?=X zx6JI{>PyDyOVG~heZf}k|AiL)hV$27%KX2!+q>Jl8UL@&&Q9(Bbqi1J|5f{c-BJIq zVvnugXeT;aBkx&uGslaoC;a|cWX66A>|L^P^>}{v` z|IYS)r}qE7ji=`SHUGb({6BH+JtrzdHZu)-v*DJEC0pkIOU&qUtoTs{cj3}PD!@U$ zPjT{E3hu#Y_B! zhQiT}D^(TJdKgj0Ni;>#L*Z@cT<`D@<66CP`%~NwcyfpI%lG2BVF|UE0w;T@LDXVb zlJ<h!9meiM}BUg^cl=dYiAc-ejT z@#TjPCof($y3;0;-MKeaF-kLmlTxO_81`V;l;Q9_q!~>$_on;tP50%0y?^)N?6i?- zG11MXzaZ);_mA8So*SV7l)FWm8zqhy`Ml;x!VZH|cW_;$ZE1|}6a}R%fnf_*o6j>6|nIS#i1;2ojNWZ#?)IQKUNz4ualKS7x+qgo{X4NTNO9M22Ubbfr2Lc zxdbe8;KDzU6I{n7aAa29ib&Ob4@&^+K7sR1oM_`rB;_q>N9OL$f$~PU+>}5OiLqh} zGTGYghOo)NZy252$kO;^Fbg46ka{}Pby-)~4XFUTRbpsZhnDmSQ^$Sq`ksGTu{$DA zm1Tz-;W3XQ|rx(qx?d`81y}y6`>(3`|yB}Wud~$mB;lC>#iF2NR z&_Rg8{n=0_`=n5~kQK~72uY+elOejz^XLLbCe}u@L!G^$M!}&tbtb;v$Ze$T$vegC zhj=Uac^b*%U2r0P@SxmmM>gUQoyK1?)4Yh;PeCKff+lGJ^&-&eEYZzPVX~1MHEu~+ z0wv?vJkF?6e%Gd^A$OENV8AH?%Z#+35mWt>+k#GDg%-!RU*Vf{ zaLwxR`G!gO9&%w_jyyek_Th}>NERU*q$ys7#{xEGzg%4baC;-hB6!kIr-ISAEA ziBz9V+sn5v^hsNFKW>-^Z?lmEXM``l-Du!BtUHANxhwI_A=gke#0P*k<`lq3CNk59 zvt$w^l+7=?fBRc^*jSo#GZVVeZJ~gju5MenRf)i|Ep&%4A26KmaCv&*MugAI_6^b3 ztvR%mkT9doPTbYHr!U4uY+P@|{u5I!Xl<0(|L^VY?q~DA>>kwipSSST_Mf%==iRjb zOy10<FrPY@m^I34-HCrq~qgw)3{Q@%`pOs!)kKA#e9!g?6aMl>Y@3z>l#?FBBc3c2uraY09M8dBSLwi4yx* zkgcb5uz-)h3E#lPAP9aX#z0UZF$5B3CKSF;*aGRV*c^yb%P`b6n-YK{@ih_)9}wAu z;P3#a{=pF?FnK--1CQ2ZU;bsSqsn3E0oWA)Iwqxg6Aor0@5s^bPO{!6Shr!?8j<NW}B zzM)lj%ISIZLIf?GaE^p0Y1qd}-Q;qL$jgiLYh1EG%yc)dT6e=?6tbT#M+UP&Bmev? zERIQOuXSEr%hH&*=N1+7P^M1+Wtmsgd&l#CqO5)|*N}9#)ica~k2`zkn&%JfbWNC4Y6 z#`6S@E15nqcON9APaZSb3*ei0(XaTo79xYy881I{pF=NydiMP9tC>hgn@f3qKns$d z+s|@r8s)O@XMsuBC6VsbnW1E35w$C#@g7sgrmE7_es>7E@Q9+E+pA|bwrPEXy* z8!>emoF(&?`Lt#(IAdqAacteZ_E?s_g+!Zo^tqw)pWy;na{k-d-p}~|wc-Ej^WQBz z_4%(p|J|wc-x3G2XLKH$Xi3Hc7o)3;u9Fj(*u#x;n)1wuwX@kzCoRoM!|ITse;}VT z*rD9nXi6q}A~W>=<`-gV16@TDiG!sE*wS5^Avn?B*>`bOoR7o) zCtM$~)9t=KdHb^4b$k&qZA1=y44=2YfRX@?-A_1KJ~^X=FkMKfK$-|IM~>p<_2%94 zzjxof1R8tM(!DfZVY{oBQdzVS7%UZ6m4Nyu{8w`~Di#kdo!5On;G^-4+&;v)cU>AT z>b^}VKnM>VZN}woxbV`E;_s6}sie_724E?JF&k7ofERqv3id2@+dzri+UEBw34Nc> zs^!1SN9pK472^Nw?4|Yp`}>_vE&tuZQ_Fv~{CB71zpDA)D~N=}p@BX=ssjVv0RN|4 zsH_l^J3$Hm2Zqzm#{b#htNH&eJT*(NS^AB$bb0J?NBSM^7>57(xcKH*cPc6k3HNb) zGWdl!k8w;-US|(P#IEo{lKGZipuyjotgHTC4NA)8O4mL!7(PVtdrmEb+fM?4Zq3TO zC2}xH^?p*pRP?JuB?ZLIfpv^`E#LWGS3lWj)%!ok&@$U7-v43C?_}-2I=l7$e;ZGI z{;P$ByCp2}-qpI$Pk>L{X*l-#x@bU2-3;jgC4@PI3EPL*o0c6sh57S5aRRFzWDCog z2djcpuQkdbte0^}7H~pV(p;~Pw1~Rt-z;zNTcO^@*Qvlf&Qr1yFr|?sl}kfHb{^U+ z5wb#zv)&L!He@(-jQa4T@sH!GT6J;YZzT0ma(Wk>QPRky_m(c$L@VxyRLq~c7C{c`*ZS7kT#+S^U@#%jMffo|;Cij4a8pNNYqku@y05SlOX`@~*RB3b1QTs25zu zM(vzQbNO|*uf3h$dBWO5vxLv4UxnjQ;{0;3vXnG&UaHhY`&@`fS7)nY&Dr$5r)pla3d4< zap=?|VyFr8&X~v0LW5AfBQ%sor4HCk`-l`9O<|v?Y)QpAkggze2+vvx-iunPyT)v3 zc?sFV47p8V>Z*^7mjDGGu{9)`c%(STST|XS(4eA z!?%J&EOpXsPu5rC$Sm$`3z;IakF@mBEl-5*)Q!RoJEzQ%5 z*>n(IS*%or?H(+d6k}3V6qjW=gwxU&^DKe_q~^yLIv8d?@5xAB$-x*mCZMAX8`QU` zRN8bQZJin8Vk1t*@3rjlnDPdN{MnTA$8!?ud{c;6d5HnMpS@`c6nhb*fmlVLzU5^@ zu146KrG<N)Ho9>jF8_*=rG{fKr|OeN>~G3&O5 zBllc6atwT2fie5f;a9;3ocJP~jc_4`6A&al7O8MUccTI6{=y+Q!40FEh(E$5$zdyb z6DOfzQyjmAz!0|_ATIdrA{IBCE6)K!19D?68L8k2xvM0sYA8vIEBS0FpZ*0Qe&9>__8Md z`-RWL6yJbXt=g17z41`eLr z1}6bXAjozI=a{3e`-B2H#hv^|Tou^NYw3`yzaU&^+ zYnIwnB8}+E&+hEpyVZ_Ri|KCs0_TtLJaWgk+7;ER>W*qP049^3CPQAv+$Q|Jt2)wk zetc@7kE1MT6YXih=lFFIuvs*wL0`xcmB6oIo+A$vo}!v`82NC@a4cGTN4%8hRMr)0 z0eE39dLaH@ybNGd4+DfR&YrL34Nh{FP0GNcv0F9J^8GaiaSwWU>7!dDeQ9NjvmOhI zQvv5k^o74br8257RQY_RFS+g|j@xvsmwfb3%~AU;oQ34CFDgX2ni@@{$8D``c$-4+ zwsG48aome8g^#BYbLB0M8d-9>(Sz3NdbA^!pILI41(7!*DIU0z8)!-cQd)*6B4A8% z{X|;&0Q`p6I&V=&&qra;9WkH8`-m`#n;K$^MW>u>A!dBvn1_VtO{HX8z6B7{2Pm0R zwiza=vKBy)&s^=~0Od?HM`^TG8G|I84fDWz>}cq)%m@~CeZ2M@jjA`1drCbv52iE& z=+Pv?>)Do$x&Dtq=HTDrvM?`1bFM%wXi`Yg(7whSoJ%+Iaj}7j1iT078wP>9FDzWY zB}#VT@FdSwD3yH#cJyTX*y$#B5M4@!P6?f19U%ESjhExNANdoIk)6wSYv*yReemOk z^8u6R1ZZ+Fx^80X91C1dNhNh*0xsTp;*mKEcN@T-`N8$iApz7NqT}+D&N0Y}1GQ z_oyVA;_$gd)yWp+E}ln|K9r(#4Ou$T%H&XzUV@i|;8A)n%UfQk(p03EC_)IMj_y&q zsGPsfgPcixl()2bhBEX6fVqWK_m8tvddI9 zq^-(?UIH6<}hCAYNinR<|;k-FB_jJIdn~)AO})SsS4pB*nS9l z7HncXE&4H~D@md2#3mX*T|9bq^zkw$P`)J39!s+VnEg_`D@|UK;8GbKsrqgz`nht- z9zfb(!O3z61T|5TUHa!In4F+g{&LxsdNBlp^W`hV)92E0GBy>*{C1ghW4J~1^#aeqEtMh z>OHBJXu^|so5vQb4^2l+%CJvx#%`#jQ&i6k6_LZy#4R?~($#til&r?C0xk>>A?8kF z_mlT={CCe1wSmnYvsZ_vfn&~oW2r^C)HH)y#(JSqZ9bpRbvQc8v_P6V)y$ge-JDJ3 zZ#jtHrm%OF*U-`+Fl37>5D%S(--2yY=_2@6PZ+!shxSLPODkz@jYUb`lQP=Rjm&;j z#mdo`#O&0lbQ(E0r6`n1(v6(xlH_E8)lqja_K;0~Ueh)UI2gOr{sq4OfoAiE zlxZazqT-cf@B`+m^Gb1rx9M67X`Go(Z-RF*cIM_@>1sLrD_yJ-Z3+HeoP@iADXFM` zr~?%ok$*HdH0!o*ga6(Q6hafiYGkAA4JQS;~!8$#`TP^p=j?K+u%|@ zMfoLrA8G!QU4hwk0Bi7F#3_xnzKO_GtH%qkl4_jFHn)Nd68m;?KO1>&#Oc{dpzf1v znG9RZhlS1Lu;9e-sTY10<>Unqif(Lth~-=CX4^;5toVSk@vAU8^Jpf?{?iXesPnLx z+{(3bc$jB=OEL?}F_|M#Q@>lyd`%Xx_2^=lavR^isQ$8HTGGY2Ow?4r|0=ZJX)8X{ zh??T%y09ii>4t8A&go%EG-G3m)(jde21uq3?8gOA<;@@klodl@C~4SSr5LsxBmib0 z8b)c-_`t#VJ8ncCnXADzDn97(h>siGV(Zc!&43TLC|7I~Z7!0TQ0Pr2qu3%(VLwir zfh5T>(3zXZrCp`#QHk-cD*m9bp562CiE}+4fgBt(nv|-{N3RrAI0z>Ujt{cb# z#5nOUuD}I;mp{>pa$Ccz>QjOh5>ZTytj0EwP?g4p?2l0#ks>;*48YeXdT2K>4OsTr z*_N|_MRc_BDpJTw+!X#gNlq=w_Fw1@q(P0q>cqgRBhiul@h; zg8zSxH+xRDLoLtUX`}nODfX~J4#*{wJ2>)w#AHKg~ zXALz7;k5cKIisl5Z2nbj*rga8h9p?!QE7}=cf?)Cu z%k31%jBFJptm<@wyF~uf-p+^7LhzREBlFQ4E61n=g0_L(zzxDo=hq{uGY5uqVOkL` zz$X~z8&8*fyHGYL>OTAhsDUG_PSX>2dePOFCB2|iR5jjZtZzDcchzx7u5^BFo(d~r zC+V^c8?x`bI#kD-^Ke~$0GQErUVo`>7ZXUFhhfy9>e#^FdNw64rJAqUc>yfxVnwXR zrC1gHWu(f^E{RhHrgb)AT4GZ6-Sz>mmY2Ld}`I%HfDi#Ma2ahX6qvg z+jB~P;yt^tSnqNspZPi@09v;l9c)Se$b@fYoztN$+Osve1cO1B)XoX+6BlJ^1;w|3 z`r0!-bqC%QuO7?RqF8|Ty4m$jwwpQ|pciF)R)^pY20n-HOdF7P(dD;lhfBdEdT7EM z8DX*PRhh+Pr$O|~I>81Cn{uDC&xqnf>3Rn08HhwVGarTT1jL6%6`XSQN@&x2r{k?e zf~Grvou7Z}B2n~s{|2i=5mSLqd=^M8Pz{a~njHyjE( zb%mbOm_QV3QFHQ~uPcIEg+j{QGrW|X;#fo#?WUmm^k%w#%hP+Bn%+}wdXx3_f6y2e zf4&W;-l5WP%NQ#$>f_m9l~nUraQ>ile5jLReNQ-&!D@tBf?bqRN90{195GvrUQ4cjp!fcg%uF3vx8WJd?4YIeJDO(Quk;IW;PbUrz zq;yeSCYRb&Ms*#eL30Tz4ARqH&&OltU@8MxmtpmlU`)>7vL3} z;c$~hX{Ql{&Nz%jcp3K+H}h%8#v2mRni@}O`pA)HP7SD&C_$GrOtUd&N!=>?rQ@mQ!^9-xh#_Iu<7=hKTh@U${@ zwb5xin(#y`j=1PRwHQ|*l`#&oK=)k%xk9^c#jeBvw=*x{B`h1m{lw)OK--0e*~>z7 zerP29Fyyo4ym2S_N@_S` z%QN-Zopjlbi%b{kCDhes!FF_6h#ju%oTCGsTQ6%Jdy&>8A@`g^PZb4h5o5S3GqLPc ztj|3c*3qwaEbd16xYG9Rtx^>`uN&Bc?*ZZ{7x3(C)F z@Fk;2OCV=w?~Q{nAEIVx6X$cFWsG46XX9U{(+LJy_#m|Uxnow|@`mzc7WsyH1Ap_9 zViV?hZfH_eV7Zl9{zgeY+&d8}K@4fB|;X>*k?z%I9DmR=zF z>mX^NU^UD|w|(>x7$tU+^IYEO01DL2ReFK8M$2@9>Mz#^G>%DiVI#Fd$jCRfI{4k( zTLD_)FdfcCx!A`t&A!&pd9{g&DYM2QwXP;&ybPhE2{>*N6Is@4{{-mE95`4*dzYi@Ibylq^I#yR!Z0KN1 zd&;0o&)!vfxjs)fHK3(^lu8xd_~kmDdgDUnoi`j}482QFd82DNQB=;V>USPlc-D?< zu#3@3S*i308~KY5OIi%=oFWrH3{#a34r$17MivvrQ;fF@8N(PRq%tLqg0J2z2AlQF z?3IuJl`rN|0NN2$Bs`gEUud$k*kW>3qts;^bLh(M6gzJGFfOeBhCXydsILC{kdy1x zo%odKRZA45lKEx*=|x~^XhbjjJe`|QqvovVv*w%kO*ln=N6(G;e_xs@;LGyAciNpy z{`Z5OgWCW57M|MwyY~OS3;y3pHg>s{x})NB?%^a`N@g%9Nx2TP!2BuHy2Je%nS2wu6qL_Z(h*q2%$eiJ- zBAxum6UEZ9Gj%_~7|)TJBziGmum>+-5K;u%P~HRbluIHA{=!DEvjm9V zkjoQ`-Xo4`jJCCuVI@i6g#}x@sI?Sp&i~VU`(%eN$yBP3b@s|V{(llEMO^)V6!g_B zBL2$_;GfO^r$xRIV(8lqk(!592WLDsooe(~?{R?iLKA}d6Ly$_ojuh+H8dE_V;Szo zLI;0hkeZcsj$gD|E$3Nu9v8Ix1X|Ex0E<9$zZ+0Bc=i!(5O};NIwtuYJsRG{PDj1Qiqd>*&N}ZkOcv3Ph z4Q%uH@DTgQ;e?Wzy5afRUgi84$S$jLluT#YG_I0%kF`*=ier_KMim^X>08UDf)Q+* zSW!Es^DZ&w(Up6R{8`K1Di2 zNm(1r7IWIjWQ#z&bU(i7zWlHE?>?NZB3XpY7Ln}Lhle_no@^gC3%|EZzITqBMz)CD zf;%OE_Kr)&n#vYo10*te;Wd!FWs=1@{ z5aj!d@gdg1(?kr%2@rt;e+Gx^&!0De+qKT2#H`oy!!7Y<3*TN$$D_YVNSnQxKLY6x z!Mwzbv6yI&PC36}zoBRN<^RIpjE8^1UrA=M5&RPB%?)QPKH;ymEGoLc{WcOHoyK~z zp^sjv$eTwwHGli9w5~2Q<-r-}Lz$IyVO-FInb8G1gaH!5Ae`ZOO^3j*ng!hJ=rjf%xBxyP(|*gfE2JwRVKqOb8_7j0x4kr zs?4t5P(iMnLLhq;8rnZDNvKn$p@RwyJvz4JADXwJ$7TCs*+{B3)V7k;oQ+g!sAvbS z+DJ)5$b(nYNQH)e`_0zWyp5DMG_IC-Y6T6M16s6^vW5l&5TH1*He$<&FBylXe3X_ zln_o<u_A0ZKVjAHlz&lu~vG)H1yBwem6t6`kI+QEMrU{zR?v=W9e#ce~r}!eLZ@ z(aFAm6S_!tL`mft;@jCsgsx{9?F8h@bHD;-)|Glngz#~!rO|2WhvJW8Sw}_%zVxH% z%pGwm8sl?ABwdgtvh~*qD^N~^n3g4V!cfuh&b_JpJ6nTuH>24|_OebGuh{EMBe!n} zn4PX8Qxy;j0X?YtC8GwF2PM&_wYdC$vJTF;vg9)_|^q8Sq&_X|qBD_1| zh+OHmF33eaMIJ4wJEP+kc99SUv~r0tYFuvM!5h42fD*8ZWJvA@GND?sBq-uI6k#g2 zMfm3Bk+OcEYC0uWQ2oJ4!$w{k8k2I?EeU??j|f0-odB_jQ`|L4KzB%eL0@Y;hU6a4=O1@(Hvf;j$mm zASveE@X8yFy0lXfHN~w9k)!Rw<)a5p2DPR2ENhIxFy*G8_wu(3k1p*n5mPvoxvJ9q zbv7ZZ7MVGwMe+t+B*j=fCTl6c0>7PcR_R;|(@os#uQU?qk+3yex8oW5c5V3c!{y5+o6v9zwF42LpQ;9YSW*bz;lOZUo7 zjl>EP!BTC$B(w2rQnP0XFsam+f7xj7jr$3@Df+M_vh1iCq^os6w8E}T?n$@4Bf?oS z@r~FsTH_YnUU=y>DR(JSw>D8SUk_d+;%*R#>vV}c#9bO~1Sf$ZDDXl~IT{8~ERjS2 zM&Xz5S!t2c0K)*tj037jjK<+C>dQ3m+C;blGEBw~NUT4Ib&u2MIs+erB;XciU@(s% zaHu7ffa&A-*fE4leP&*V?jX^}(kNIir*+s;yiG*oiDwkA7cGwy_>PO%=oCVs@zVi(K*)l5wY8UnKX1>A@WgS7WjO=s1G^MKYj7VzD!uNI@5yTqIr$V&xZpr#tBJZVAXBnISZ^ns&KEt#wAenzN4DO8Z@a5l;=5fad_ zq_AN%a&hsAHz)6*W%WQ`Q>#Z{g6!ZXEPxCWy9~JuE{I%FMDaty7>-(!wjfS!A~~^( z^(7-UndGifAknbohp!o~28NQ^lFbaSAhog@DMB51z1cY*)rgeTXy_GkCL|k}r%}jz z8oMfp<6>N4x)6KSrVH0+M%YO@Xqg&3qH1}OCE-i`g3&jLPA!MB*$GYk04IXvmyM%h z!+3opTND<+C~=JF6oy(3&PnD6Vw<(}M}kO-QjDBz-;^!7%4&A%|J%yzL868c;>o=S z9r}R0$>I*2-rsmf5Ftmwc$Ol2nH2#8sz6I#=<*n?g(3*#e!A0vGMi#H}Ok1_&b@ zikod5g?Pc2(9I@q=&IA1`4k&P(WL70Nt@N?PKShx3m5vb)7k9#Q`s|ATCm|E72My& zg4{*}@q6uQ@^zDiY67#rOJGF(7^7TxI?uWrxDK)i`et7xw$?4h458da`ub-Yh|2qwL70*A?cX09?C+~kP*Ksr( zZ`swd9I?ZV3Rlz0kX0NJwz)5yqdMAlXC8XwB$@@l9wVCAYRRaLdhut@4T^Y=h8-W^L^Vozfn=~7gy_GLG z>+TxefN6K#`rWpZqdwHGsgIq9zIm%HXGweA<(Z)g?T;twrrLUyE%UnB;83P+?V|h1 zQ!Y;a$^dN&{LLF2R_nOYK_py*TzGy>`jT)f&O`S|UPYaede-4I@-*ipf(&M)WD*Gs zga|C`V4XM={GSYEfrDew#9nrdOemz7<4%=Bm$)V!U6Xh$ynbH!Bj6z*>3hNf4*SE2 zZRipPdk1j2pRe&X!tW_fAYOG)w^6N&J2$JcXX?s=dx>WR67o?fkb3o=d7*(46LK`v zfRFwgatfDv5y7IEj9l1OIKWv5yvCt`eymxb5onIr ztSaY`z^p)V8U*y@$|Yw&(OhiDm-4^P1RcOI|3@O`F?su-pp3^joYe^M5Jr-61SJ#w z!OTfy`T>k^tjr3e;y&_VP9irDv`iM>Z+|*uvbu05u+_u{Zm#(DkYMZQBRCF(=oIEc ztza-xo?u96By@Jiq*B8MvKlpEsdEZL`oN=+C`EP&GQi01`?l{5lg9XmWU`2%fwD$_ zn(^;H(n?uT4s~*-0xPD$VGH~xf6oKC&5kjlh2;4>g$((BEn}7AvNUWAwYd3$@ycxP z22wMi6`2-7`c`tLe@o9z`2XXLydD6c*#CdKy|bIi|GwRBw`>3ZTX<@h{@SJgrd|52 zKKL?DNP!!Et~CUie*7jl4O({98_S~4>iK^v_{(3)`Ty?DK_>o7XSe46xAD~RU+T@` zPHh${(#y^7AD82L?^rqir`S4X8zuZ7Aldl;Zq5I1;i>t5&HwKf|Mx=<#(X?yd@dk~ zaTw5sKw4zVTa5STF1c%LYM0oXu{747jVVgAu%P+)CT0uH3!rePhk?7$N?ZiB__r5@ zEfMI8KyH0}<2-wR;$U~NC|=W3otWZ!A+B7!j+9P^c)5-0I=UopI)~0|f4AG%7QTh% z)%lhBeudxj@BZ*UXe^YWeY*am#YNW>2(l$Xlg|oAhK&?(ye9B5$ay?{BHKQ0L``b5 z3TUPIo9%R9Ol)AGZiCX`vE*?BTW<0t6W?E1u6Gn+j( z)-44PIIHnXQ1mL@@4U-p3O8l}@L@yUPpjZm6+u4vKw&uw0#2oGzB5SuATGQK(3<_a zJX4AK$n_{{RVo;jPCg>+vOB};I}Mxw)i`se+U@8R30WtJlIlzo4JPeo*}9sx)XLJQ zUki>W{dB`$EtkNz*;{rP|C`R8L-AsH+%|GT^Gdj4H{p1_-aM88`A^4g zG<`pfoI{7Bz+~)-69}TJ5imvpAmv zV)WK#6v#yIJ>SaR-m|LxpH%R(sXuD<`{_1{_y2bLV6UCt|M%N!Ik{yD=Sd^eVb8-5d`4nI zFBn*y%*g$&)a@=)?O`NSi6YKF`4e`+#Li!kGjeOqOp7=PW9O+u-Ew|(9-+$e>H?QV z1HU}MEV|0kZOAWwblT3b{=rEc?MAVeIH$>$NVzL~RJ-EZ1RMVGM=qP#?u#-bFOc4W z-0WW`ZWMbTG2+=2`>^3K){^o~=YRgk;oj*`D)tlGFgpm%C)JQe8J@N+@xd}aP8ChQ z*H5uSN1|wEkd&v<7^xU*LQ2J>mH;e6SFls#w_!lyz{En*yQf5pt(cvhA3k&r4?&vl zk0;zE`iO&WG;Lio5$SM0pJoak=^X@&{7JC&OD1-?K5kg>Y)<(mw$c1@lpZn$5lD}i zslN=QpcKwbrO^bfFZS3HrQ_C`b(jed;ml(62?fwB6Oo#DbkscoR`p#LA$$(((K$UA<=LH^T}=uZfHwAcO}S2B2o@x=E2~0$nfO zf@8__x}j=i8Jkg>sq`pQ6uM(C3S?lsdBX;4pES@S;jVO8OWJzjQj}DYr>Je*x*2b3hPOB1f@DyOeQ^6 zMnsOEEV*GQkWrdd@><`}4uD ziIy|et_UVTU4Rk?BuYyTEy_RIrnR$8m=aAQL|RWaBfrgdlW?{oo%!nZzu7zBlKbDi zo&Eic{&#Q(vP$Gp&VoLLM3>QoCVPWV=_kuZl)OgOx&S}MHH)eVHA@riN7V{x>cR*5F`g6no;FhFR5Ui zeh#S1!_3rM-4w4*iDOQZcAnwC1s=sfV2NR_3he6Zmp`>Tj|y-P=MExr7-QrmBg7+E zy!d*n%_LP{w& zAoXtUM;IvVpctb-IVJw`^7-Gpub!Q}Zcr%V4X4ZQdUQ_#zj&YR!r3)Qe)UITjM+O1 zpMQv3`y?ti8s)C|`A4EhrJQNq&0`9yjQ#Ddsy!J3UC10dPL5X6K+=fRzpo6etr3p) zeM@^r1PiF|ZDE zur{zM{I|0-E2|mU0*%xRY_3MWVFuPldr{*}X9;@##u?ZzXJ_w~1h%-$m2D|2;GuSo zmkv5o9Uh8|2PN%V`fFjh%k|vsZx;MYdj9t1*~$@J5z{ZitALqRS(kHTkG()88Rav^ zY%kAPnR@=22iZ|LPaPfsUdv3QMs@&;cfWe)H7lBQ$2s`Z8D>HeDLqY{U1Drz6v8Ol}%A~Iqv$lD>OR1iiEvdtQeTepGRTO9i7q{mtZ%VExoCR0I5Ns zj_S#q-;?ykL_Kytd9TCs_Yv@o&kdd0^coZTY}%%$?U%R=TI=y2KROTK|Ab|^#3UO( zg(2mss0u;1W0iHA21FY4Lh!g|Gd0t4ynr|@9S6l4l0V3EdEy$mKpLn(BWL3LY9{+Y zAjFUw^lKvzV#2q?m$>^o^!pDC%myWjdz#@`G=5f-pnr5i562=Mdz0{&>Ke4y;KfGC zWJC)mcvi^i_l6^3MkF|SWTm9nmwD{PI=58_Kj{D|y2 zw7rP*P{OYqiO8Rd^j0D@6NfGyXeqZx*RAR}R(v3Z7{BPMa>1)4^-IB&Jj&Z z`jwg&8;WtQQOk0L72}-1xan*;nL62S{UIWX@mBnC?5rDjzoM7f_>}^(2w2_V@O*Uj zWmLDN&STjfZGi=lq!2;TnV|tJORaV$Uy-xk5NlkRGZrvLR?R=B%wH6!RHeb>t55iz z#eEo@;x68(KsM zb)-{wwk|bH>uy8XlVW;Apt)2*O8J!d)l0zii;(VVFsGU9 zuFJQ{S_PE=EWQY5qXFlb8+d4d0&7fO%W!>=is%OV!jny?dk0ZKq*MzAu``>foOwQ7 zV{;}uWQ}g*kFK3h0SKKc8){+|(Gv0&&yC`Jma*zswOiz3CCoj^h#vaqGnrmdxU4ms z26LsLdSvvQB4h4OViBF9(dPoVSD8*Tx-(tMloTMdN@fTO@rlX8dFSyydwsfsB5StM zh)n}vam!3)vAmv3jQhjDlM6nF5Fb9wr)SyUimPp|l_3X>Tkpvb$i_1K#L6gEd0lZM zzCh~T{P@N>eerkx7EdrsBHsD|av1Q~4cv1|7a3e9SA<-Tax)?YmaNV-Q>Vi{WD@8W zO=d-eo9mn%KFDXSo$`|MXs?G~P8qgOW0XYjld4aRe3t727%FONlK#B(XK7&hH z`jNSg2yH9B$sD+0K+Sw0Hz+7b>DfI7kHC=W|KlXDc2*-GdQ(2 z)~84{tcEn4z39E#u_~*j0>nUVc@@<|4B3nxD5fLob7qRJRQ-vUX|Vm;IcPd54)4y_Xi%d5MFEB zzIX$BlQ}6b;%{TWYSky<0{BB$N(V&U>MMJuQaAuZu|gflR9#{)8CbeBWbI?pH8pU~l8(9DXK@+< zZ@noRvcL7N;6ot%M!3VtB@{X|dsoP8MG0tJ2gWA1s z4f8#+^EXaF39-NyX2&sXWy=u7uanh~#B6dW2*T{fjgiAWCI;K4l5mEEr#{E)@&^5v zV#?C>IU53%Z;9Hv)VLsnSYmT20$V=U+6apGSh*%vgbYQKt3*XU&;=2Jp`uV)76EDE zt!ad#iDKsheaSFI8eMB!(*(UgmYzR~g)kVp8Rwgb_s+wKb^|g&UC8FK2!D5oA(|Ac z`h~k-=UBorMU-iz8jQ>M6;?i!>S-ab1{Ur}=O@Hn?-1k1O%y3`mh! zE7>M-BP=AmpTfcQLOUhdp=lWC0U$+ENweAAQvYU<&)bmgg;q;ONptx$M19xi%)mpX zsmNgdOfZ~6?8`#h5mdY>LbWWT&~3JryM*n9Z*U2lP37ZX4M?8@g^3Jm-*{7ZP)69Y zP=Z=-7szdzl^2E~0hcPL`j^X^ar3FTXqjbGlW{YoE+ zK8XfeZf3*crsv(UM2EkjEh{~u)$Caeb>2-&^yS{}TIv3mZCkeU?Jv{mM6^xNGV1*7 z#$|F7JhWBhemO*Mxo1g6iT>JT=AVq$uHUbS_d>`9G4k-W?OF~t>3%L&lWWNoJ}amQ z_!f#nJ1(OX(7|NJRjl*)Ihyo8czw^m^iDWMPQ!%PUr_cmtyB31Y56E77)z;f2qVyPF`3S3A=X4t4LBnr{K z8?9Lq5p2fhVRXBt6+qFfDS=Nzr)X3XKH4@XATZFiG)PCw1Rx}*2MhC4j0GiVH;!lH ziCAnsjJAho2@OnZB?uSwbxd1e9g9h+q7JBbV7@IPE>{UyNw>6GDgF`&HslqZ;Hw{b zZwraVhk7dl3#*hO&#Y}jV9_DH`Z+fjf!QvZHC308O_dzfZRp7>Y_+<{Eljuk!fv%c zi_p$byVdE@ZXb1oArSoV;)5RN!8-o1|ep@-Wb zdgsvI-;y%NAlGlM1rz}786rU)Q}Nq+mX81EeMT4ac=7m;2M3*O{@11(mN*`5MbH9eh?OB_&@!$IgFSosUl>(pzMwJ14~CR! zh>iDM^b!O~I7VN3(rH7NI<)QCSwC(x@U-9T_BZ54ug>)7?Uox_h6DuN?Zw>B6X)4k zEc`J0Fc8zi>L2!JCvc$@A)YYqPEp|XS=L%O37fN0uUIZWLLKj5{-x;cPGdVwZaqtTBOr=!&&5WtpA%n(9I3yX=dY zIr~t8&>4lnIjuTa&oL?!>3A!=(@|?BJFS^>swTeZ*axh?cl`*%x6{8_ubUp9l&I%i zRQgGpDX%b(5tr3cb0QYROJQ^OgzWjkVdCqMLJH>|RWl;e5Uxia1-$__GvzhHZ6_+8 z<3^9Y#<{WKDVdBR2KfBm^{+0AU7psCI=(~_}%}b z#h%WVtZE{P$3{g|2)$e`HuN@Gy><(YevwF_seL$c4voW?<4p3$-`kL1v|-HB0h5L4T?E z7v{oG_*XWH)Po1MFj8{7M#JdYjXkA$>S*p5{Uz4GOo5hAFc&nwk z`z;vjO!Wfr{9d9Nz_$oAs{J`dh4`tQpJ}E*e2u*kX0#HPz;BI&K_XfhA@s&(PUU5TEBrb2foB|xf!%F{-5@m!lGYF*9KL+Qh5 zTqFGTY3ep6)x|`Tv9EbMw-ny+=2WHUWYsbF6ovJTm@s){mg?NE)Y#ea zUBo5dPUj*Km8Ti}-2hIx8!4m;Ep-7lfob7I1Bx7tq^k^!<)H;JS9S74Q!FUm_9Oxu z#!Im^Rwc1geCvZZ8C`FEfD^2@CZ>?TNYm@=T+cse>CHp7A;MQ(i~Nrg=8OlH-xLEGQ6jThEQU5$@f< znEDqh*%dYJ2hd3{cuugZ^axMi869kav?z77^LH}|)a4JHyj1O418Sl5OBB?7QJ6)# z`8JRoO*;0m0`kzx@+RaOIY@$^6jW4%cJ}FzFS&E3V!}}LD9gKYuLIr)1nT0A)Ng$U z;L~Po{#r&Aqhj)vaMRQ%vja>>M1EU_-$mzfH=JayPSU;7aAu+_>5T-nL~n*U3nU%V zNDkcKZj6#S!f>%(n=asm55Nx;}?;P zfj@PHj&@tuqQLJVnS~Li0pGtr1-a0z6h)&>K3(0 zCXsN-2B>A|b(2gxCXLC6;2x0cv#|sx?(1#tKQX2NSD_e;SwT%YBdrQ z&Uai9oh{8v3l;owG5XPO>?&2(H}h;#(uc6(|TY!SORYm_WX+5m*g{eJ2)Kkw?xEx3nIz zYa++0^IKaBcbO>*61YXiT*RE&dv}HO_-zu@a?CYL0*LgLP(c1ZOZEU&=F!|L@A@Xm zeh)Obg7cNWFG)wG%IJN_CLGIeMaq#w;hrGhMhW~^9bV~4$TD<)tG3paopIHrZji-_gihO~YMJxTD(ss% z+Dt+fe6!u{T~EDA%bqgMioa#hS!0LDq1Q$C4esx)u?po}rc)00Awx1r*HQ+qV!m}R z*GiTiXmx(!^*@oF0XnY_N8yzWfV2IjzKX(eBgF)>T78;b6$Cn$kYE}y56SAeM_(%v6=F5gM=w>m!zCZTD z*|e+2>Rj%Y5suVG6i!8ffR?i9S9p{tT%ljXJU$FrM+Li60s%H~TLw8hUzWK^NFH%! zI6D}lplq{x?InzDv;Gaaz6|=P^$JE;j2ia)Sdq4T8eL=j6AX*QA&0mSY7M=}A97&4 zG49|EAO)^lxn3>Q%3p}s`AFM|hTVu5pS+ex-N;#& z+O6|^13OyFoR|{p6pWsP!M!8DpUdI+b649jQ&v#L_D?ztwklZgj<|}!LDDmek--X# z3e-5Ph6QN?VEn#e^xC~cG~~*|aLU?1HF?t(2gV$2BtyL!NzD)X5k=ImNPd|9R~p%e z!y$Bhd8ZWB2QfujQ=$o7L*Ivg=IE?)3D7Prmgy{aAlp-UVW*$Us`pY?LWv$Pv_j3% zmYChpdQFex=58K!BF_v}BJgIS6_Af!k@y&U(WT$lxv6}kNow*{uI*U1lvW#Xd=U=P zrmOl}EAJMoG?f`60g(A*_)KxewA{YR0$)cQ6__g9OpLkFrzHcak}+In7PB*!0M@3b z3~pwA(^H#3%}yr^uIY`-){LDLtW?m{);`U1*${MkF=!*%yycvs;A>zVU+CDv-#O#N zPXhYNjSJIFYQnL-H(9yb!YDD32(k|`V$C^NLqYOZ!^1px)9DVXIhY4XZvKacZDoIB zc9g{EOF~YphSlE;vtN$g*Zlb&^5<1?)%(LqWfYYg<)t=m`pt2=J_g>-7izUscFXXB z^a+S}Luy$f)a(_d-1-`wqK2(~!k8bG4C==)1@5`YwE0cGbdJ$|^vtYFGhWeTIY-m_ zs&_MCEaL5Ij5}!YA|eIC1n^|7YKV}x@F(L5XYAv&LE(_KjF+1u{}W!Q#@8_(%$(_k zi_T92AI{g)7^N5xRkq+CFN#nRNrCVwoOyU2w|Hh561I>ZqC%dn{qQo@{=_u0;^%sR zaHfm7^RUtrQ%I_jV32^8eiX+nWFzm=8zElfD}UO*a2i7q=cJF(Y}?M(x)`#vzI8}b zrD{P3I+U;Eb$I?7UmPC#!7!vkl>F#Og6Rk_h%y_P-4qxo7e*$Wfj4xKEOcslMAf=o zK*LG*%Q#Dd@k^=Jz;%1+xD=BsDFzCNQ89N?gz3fK%C@i2T$g~-mbNx4o$gm0}^1nl?r zA2@%#*$`0$6PR={!BQ!90M53A128t69N0$!bPiI=(IOE8RM2uK6J!fH1Kn^kAB3^R zkwP$&6BCYDju=OxmE5mWawh&FyGbjL((T9unNHwcjW83zFbcU z{#`b*=>Te;K6QThNAN>3{8(h$(MlQNE)a&A3236Bme~eI`N$P1ir17xg=6w0$|
?;FbMXJey#K3g9wQeP#T+9%kQw)F;MW~!`pY=mv7&l{&y)F zV$b{3=%(->e`AtRZv+PWU_8{`oC6vT@M5tGdvPu?a0!@I{I{7i zRt-)m)5MbRW>ZD+zhM$4kU%Mgog{q9+C(zS5L1?fffO{|U?7A=!Ec5GWL0epi^P9+ zQj8?KX&uR}TjX3Bfdu4Sk&!Gqm|31&00>_jhN1H%a*i%PDpq4C5~4&x*S} z*y$f&lVW5aPJaI7?6mvpMfbN4Cuc8H;5wp_MTySf<3^FI+fM1g7qdP<;*w#;?6NR6 zbgINg4jBjSX6%BnIKJm{Nn#bxImCV{g<9EGY#FOQ%y|wP^p7n-h{J|)AR~CurPuJ% z30u5OzLic>t0&}hQO)w@!P5uU@*;9m_S2u+pSQp0=c+>b*6<-r{J5Xu2dV5E&ACv8 z|JA_4+t4M z5~4%D^7jH&J1diO-mvmxZ*d@8ZEYBU7h51@lWw*Mr_VWNy8>*p z`-?QP@YI3$-2c?Y+h#&}lEO{5#+pQ4-^VHEP;C23Z3jxuLg(95#@7Ely>r5Y0AuR-<_TQ`d;#^g$%o_W?auXujCo@;jJ5l z^2R@h5Oa*NQUjLpYj1;OFq3FFR^;*s7dHtDVx6{T(#Y|12 zu;2AQ`|6mBe^W99AWhgsVK7wOoT8-GEuG?3gAcTuz=_DR>iuixj*Kk}WPqWf6+9K9 zzD{5UKcR-0-XA%-i__ExJ}~hjKO7iVHTn6=vSoSXxN@U2VRf(F#LEl2JWL3lMsz|j z-ct*Wd@CSZ7qqK!BUzTnR!fW_(D+KpGFyoO>&@}Gau&CmD|);a$itMlD_~(mh7o7F zGJM$h>MqZTExF2j<9@zr_qB?b(rPp}co9uEE{ws{9dwF<)wN6+$x@-N5LFf?ToQBS zZL3bVa-!y>)O4>l82HM`)l8=;lS-#wC;740R-O31e&|Wku5b1ylg*1To^I|P^m+#e z2kybJ-8tCV^@iKM!QP|Y-ABEh-i~)Lg#YXB>~HUG#Zi9?kE~n8ZEVAHaIi=J!jt}& z{%-GX@9b@F@9gjG!~4!|d%OLYz1u**4Bg70NwkY8Dp&SBJ-B=FtY-f4KdpX0rwzo% z{{C*>{I~ZGGV{L&fBfZEkocX?KP6+FT$7~fbhg|3oA95-*o!*h^*U%!41AMyKZzwZUHH*jXbz@vm7&a(+7aFSm(oR40FhhwMH+IAXP z;DPvrf-``)4rk8Ty`~f*v)JS7B)p=8U83(z;8c(M@^~`x(IU{f@~0Qnj)2la82>F` zguST?#a#!zzwstkE9kgW(P?_nXY+7t>+0&Nyzg%-=4nQgkFnU zzXl`B_ksrVegq@#T|4dsdex`nz{tIF!pL#YBhN#7KkPMLms8q@I2=x|+{i;P10OZ- zz1h@2n(QMCT`vG=a|7qWvs35f^nvpeoSaVSe)qSNvtQo*dIs{s2RH(roxD7C-hFUD zaCmWYcJl5m{Ced)d;8zc-%sAY*l;{R8MFhNF3L^VO&`(e4G4Fqo@aDHBxZ5qiP!gs zejkPwoX=1$JI7Eb0p1!+P-hwAw8nVLM^GI6JP^+S=dzpg)=oVEV-$TL~{> zhH~+syioUYT(w+xGMb(H0Ty4gi5RGDp+n3p@c+dz2`Mnb$MLb#hg00tdkcV2_)Jb} zoT<(IHtTNmkfA->Yyxzlj$_w`akHXYYram)$*%`AXZyN5yY z$L_@VF!e|N)F{g;+T-~~w~|c`|5LcNkvammr}xzG;UOl~liBn#(Wldi76AylBYp%R zPqvSp^q9dOp2#AX1AtT(rHowQ>FBwMllM{zxp6vhv!R;Vc?CtsrS`~ z@q)ThK9c2ET>E~mxXzL*PGXkN63fiDyxMW;u4Kh@@SM8W&|AwkG(VAtR{?Lf2qy5j zoG^P`9uuAyQ6!z!tOV89=c=ph=w~2BwK+F3W|RAZieD!;iU>|Ygg2zuD;T=w=egvt zDfth&*j*bVO`Lgef-QFLCtKWEk}W0w>+{=Ja z5P5yizg#sEl9-6ALcs^_rws{a0LFz;&`tZ%uNWsH4&SOVa>Biq8Nh4^k}WTX9_e~` zQ}~eq30IAvGtuuN45_x~M$wQH#CK(p6(A)IGWn8<{ktTN(z)&Rj#&F(#`Cy|&1mO- zZbo}cZbmBVFD$lr5(X>ZlvE5*lRMiiMOVKTe-U9xKZvmvu&50^=y1uRT%OwY?j5z^ zd&ZtPeUN>9^ihayHSG7mFNGgRiB9v5)Nqbg06RmRNq%Xm&64F|_&?)W?inKUhpF zttbU>ZBbA!v^T(up?^N(Ia^kuu#?d#cGY0@mPY4aE)vKpcF0@6!gJZ(6=Q;IAKj_f zH9*}5oXDO(*Be?royee`QixcEK&6DD8`@PqaGym|=h&2!WaEpYVuj~6k3(JEI4Z1X zHr4nds9+KFo{Q$>#f1@TPbSVes@rZ(}3)xrfU9hZo3q8tt>?{Uiqq({?6ViJ!bx{VnST}|B2 zRk$BLKr1zg5wcPZ{GRH|A1(C17pO2s{Q(N9kz*~4nyR4wNAmaPu^VIIM$tVhmA4G~%c-=nRT80sRy}jhRDuO(rn~EL9V6 zDQSv*V)N%DOO4uR8%1h#Cx+GyCsRTFstru{9$`AT>2>4J2mH1x%0Kv$IKpZmQtNRR zknuJ&1F&RMGEh|(iCF{^6z9&|1mHsrRSpH|m+_#b zqWS8ubuVZg4Q45gpCkj2DA9W9m<&kcJ;qGy8^+3xu){Glb z9wLu(lF4awQ!Q0N{<92@=f_sUPE6eAY-B8wq>kd+w-Vkl*Q$GJTXmEUqv6}R9)7f~ z!}P8X9GrF{iO-~cZR4MYf-o&tKz2@);RJGntRxjAh`b#n=HM`ks+-2rq8k?=top8X zBS;g}mBAQ^DL08Ox#s7^RaRLh1(g)0GR&IMl@`2I?-RsjYua|pvO&_&dSN&+)PD9G zlRQ~jlcM`McR8Zn6eXo)?t-hDG*o-P;z}CG+=g~jI4&%k9^^(& z%c&VE#grUs&N%-1R0LMG;OM!!A*_HWAzaRjD_P#Ff~=%)7F+r4&yTTW;6+evdT`;v zQ+!&?!v%%1s(=P6m+811W`*%lA9F__{2hvq!8xuL1=CFB*wsTDWNFb#eiw`^i2>|H zt}BRn)-MLGd4FU@+3Yc`0ER$$zo;hSS|QKGw`sAHyK5>3ds`GLO;$=dKRw5wilvq?9p zn}C#dRM|}wcQmo%SiYmGN!>i7sH5h6)JoUhjV?a3-%G4M?JDU;mfvlyKW!X0xByeu zQMa-JQ*BmVf+^djTUmptHdBkxvSnxdHA*nb9vq9UNRyJ;?;~ffQb(@TI5VBD=2&9K zfbMWuY49?7x9Rp+++)2Fizj1#&#DMe=}F0WrIzHLS&b`FJd*mmgW z=s5F_gX$H|fhe-vG>HCDP4o66N|okY8xyT5@xt{FEt0ogYFT>b7w1S_NK-ej9% z6DiC~EW`WD?j-TtspA&ODwzeWFW>|6SW(RvoNS0ieN60LV365yNWP~cr>Cd!tB=CM znQ1J>yi~YN(=WP`DOBijbo88;AtnRN)=NvgQ;oLnK`7Mk@>ya0*UNEE2=J2l-}}3J z`iDm9{MWl0|COVj8bMugt4l?7y|sX?b43u>dhkTsrZ*fGBUl)C z#U_r&ETJR~Bu189-N1Y814)lwWPx#bSnx3`D3Epf;)a5jHXOs6lgw;$2gUlyf-$R} z1<+UOeB`0+U^nuHfL2)cPX=CpM2Tziao0RPJj5a>lob{GT{kNt`}#i;`%{v>^1{M1 z9u5!tBRu5j8GP`?psP!gIf3HWk-a50Oo8TKz-Tf-rCbmwKkwA6ws|bN!-s)X^-<_b zZwc}x=!zgLm{f2U%#d}jZ|QQZ2|#8gfAAXMJfI~l4i7!aZIK_ioQ)e7Jy~=Oqi{@x z1y);$0S@AiIt9XHJT(mOAF>k#6@~6$Fq5k;W>*C6k9qD@^1~|RCWb?Uwb(fq5(xI= z4`n_sDcuTIM=dU1_*Z+a*)=z{*L;G&#x++^0U2FL2HX`;!gQ!->z2Wn)cKuPd)*WWU|Bwm_e<&{GZGBHNOZ|%bow=$^#WjF-`lfz`Lkl{-jkoU<}aLOhpZ-HZpeHhru2cfnI zfu#oLhqwVnBvJ<ab>Aq=I#nR{h7>EVL1ES}g3}7Ya|K0t)y-fbE zgYEkKe;ZGIq_2*- z1c=0;zRNwu$fP~D|0#XvlvBV_^*@eJ2EWiSpNkTW-*FNCk(K)i5bnzOee;-ar+&Id z2o3%Q`*LFCO`@ef1fxPO^flpPO?mBs^r8Vv@jTHEzHZRpU22N1N5x&1ep+X6EFvda zW{v*f<%+!IxjB*;xGzsW1ysZ9emN!~mS4p&WXR4h3U@qX?M8QdC z^XE1$m|N?tX5W%$cHwL%cVccl|BROD1IuU$hzaWGw9%y*t4tnU_KUMn2-6vf^xfaH zK>o=1fQSkVRG(c7F;%7_qf7V=(2VD9{O7Ma8Kq)HSc&Gj8^7`6u{-TwBxg=X17fJ+ zC_sfVa3lsej0fK5DS#3xv@{N&&#%rt40z0iJ zIHP(!nz8;+lPOjvBUY9SQysWLLBiz!~o_hbU_y3#K|1oFyHWYy5Adz9$^tOr$kP2pX zfChA_17x80PYEanaU)tl!Yb#C1Q{p>+ybEFcey%5tNYhXWkV5xE2Lqz=NxKnOMOD3 zjiAEhHUs_Qg7iyvOVw3D8L>xP;jif$Mqluu&#_d2QZdzqBePTjBq^)Pe9;7|^!TZG z^2UthK{Apt#V7~TpJ&)Ya_frXSmQs(F7Sq_`^jq_LbY%<8aP*;h=NCKqmL2LuINS< ze^R>+a-ZQSyoxs*zvZ>)OE4SvfYkt}N9!bRgNI1Fhc}3+*x3C{WvH+J;hYRn8KuD^ z>!T1&h>*LD!f*mB^OAU`Kc%pIR~NV=HRymKP_ITVCl&|Y)zEB6xT26@CV?jMet=dp zQtSn8?~g{_xjSO0EiokujGSvC8{xe5^l3r@CT+;Ob}XmcS>(=}WCzS)DxW%d(A5nG zEv^I`4l3f`k~j=pxe5QYilu{f~&h&F-UyGz)B-QNII^kxeV=b zam69d7R+(GsVhoTYEO8P4%nJrh(~M5x$H6tN@@&+DTQkN-Mc>Zrp|h@@{f}GO5beb zw3iByscSA`td7aRADU%`BQ`SUgt*i=KGBuq=3(QNNOG_-XqSFXfQ~B^;j#_lT zQ)%kizgkRcS+vS_{?$rIUW@wY55z}<+|AIK#wP*>T;n|&c}ABY-3Hgltzwio=_sk$ zu88$tuFvY>!+6UZ!ba#e*nV&)Wa>t zooX8u$c1#88R8XH%X&qnBq6HNFbU5Xux`RNH-;0um|KR1lf2EN!WAJyP**T4%zNX> z^tuqtODrK_tg~gIlYujgU}>-+Z06e}oOHGC`PU_Rc=v)*ylaXx4f$eDctM*gB4Z_2 z*vp6$Gm_?+*9tRRI=7{>D;XxAY1XH11jicY#mHf`Sr-i|wx<`}JWlZBI0oM{iL@Ur0&5*2rNHn$ zdwrNIJpH?9T1dxWgxiu;-vFm`FkD{3HE@cB<>4p{&Y{kQH^MX%k*7t3rqkwAR7W#e zy$+%0IDz{1!c&h$Q-=>R8UR50JhCZo6u6agRl0KJ*ZP4&yvhj+z-5xd#Fvsq`aPLc z-m7P|`d|A6aGCvQd%Kgh|J<$ZKX2oy^}n_L_a5H=ve1&f04~>>CO5#kWVgId#H#Pe zS7lUDgybqYj?Atvd9X`eMOQzsq$9hFWmS-41G$rY9OvY;q`OY2CKu!%uy+n7&T*$<)M)Cim~@|wm9Y3j{M8gD5vg+qmBxml^fAD|qO4hII{!cYYe#)G zju&4PvSySLOV>?3P2au8-tY%1*t=vpg>&#dwNP#!)w*vpgu>F>1szq`Nvm%ZCSz;`bHuXO$~snPy!#tNv!{s)L7WB+ro zz1OMFf4A_|=fC>=x3cpe6nO`f||Ni~;o44=Y|DO-1XTN^@?Z5u}|GK^Y zz#E=l`2YMg8VBLzUm(QJF0Vdc|9iXL+1cIOKX~-`$E^oPmZm1|;5q#3_Q?g``Qhmg zM}`l(!ySD|JrZ&@%4d&20AHunNYdh1z4d}Y_I84YG&rSSWU|UaJOyfaim|($O^4v& zN27F0Tqiaf9M)mW*=agIiWm?7A7{ro#z^1Jy0dGZy6_~SZk_tGC=MeIk;rY3#f<2M zKltomrX~90i6fh#-#`A?)Q%<;d4+-DhbK>*_CDRgJr4t*L_9<~Js-zA0N#*P`!Q4R z(NW%4{$Sz&mNj0Nv^PxRXi)Ws&i3c+?N`r{kvE;=W2gP-k42$u@4Qk_I*UW0?husy zWq?3$ntv!Cq!<`&|00=ro)|LBX&){#MRy+8oeg89ilRL@*ON;kp`f!A3W}-p&Le15 z#8`x7J(sY_&SV4>W|l8Jjad>Cg!g`5WHO|1CCAP~KbXv>;vCIU-JS>*dhD!+vnhN{ zEGDUNi&Gsmnn3%z_GnImpTQ^woHTd)$O=LCU!*U;r&`!_+JE3(t$`1rKoQV&OR^jo zooXWwM)zCI95fQ)gelTNUfyIR==Y zciZUNDqlUpS9{Nz>be=^M;D~u(Z~r%#Jqx)f^_E(l_r@Q`Jbl>#wI~MN~xEH%#8uG zSephSraJ<(1*i&iN0SS;=S>ArmFV8+>VCGX2hWGic07xlA}=O*-jX)BOo{oi(bzq6b1|2ybx z*ZRL(cxwG$t^d2f`oCO@lRj)@aNs!31P`~y{$5@`cT{{{mGO+LoKcT%b!%NI|DX8% zFurg*sU4u0|91}d4-PW-KRf$%{FmE!w$|6qU=6=HIaAD`0Y93U9!72pjpt2F4RPRv zp9b-TAFQptSG)na85%JIr#z3~Wb9$qEZ~pGm{F2H$1Hy#d9DCMiJ^iXBpg}z8nJKy zBRME?8^?{~u}IPiE4fX-ryqCC0YaK_=lAL73r4U25g;)@N9o5Rv3e#g5ajAIKJ zZ47K{4Iuc?Z?Rp;-ccFsIx*X+Kv9fut}aBxbTtw`UK@f04o&jzGYA1?)FLJ6K<`t- z#Sv|5NJkMLuF)jBJz(xM7M@qwjiIaD1)P9{BuUJglGq zGxa%>FyhT2HB8tV&VG66oW6T?2D{ly*yx=1AKraDdGYdv-1s)q``v$=``gR^djH|& zDQU|)UaynpuL?Bw~cub+Kz-v9dH{kzkb(EJMk`}XARs}Io1 z%Qr9Ip0%J=c;~$Q2tS;w8NN=_T~+ z*-x)ua#Jv<=dYigyxDMGJbUx(XWrP~0hAAGSd4q;{PxRBe1+{jga3byn?4Q$B!III z@N)x3`Qc1e{q5xR<%aX@!^tTkBS?xVefeP?UyX?we~ zyN>@klqY^#W~QM|EL zZ z+(x_eXlJjtO?5iEJMBk%J&$1RZTAlb{T=E@r|0br4hYtx?Sa>852?)K-k`s|?;haa z{r2PDunlEI8{Y2Y-u~l0!S#kcZ};HQKK{Kugpz~)KDW2scia6w{XOs=cl!G@zFqfV z_tCEFQa}2=Z5Jv~KlTAJj|Q%6%Z?C=Ap)o$%Y4`W{2ZSpSusR2Q8eea?_xNDg z=RWRx+uOY%jcKsw9z1UE();cGzPrD(M}2MYb{=;g?;prEItRUjZTAu3y5qHbu(Ap6 z?f`l_7*fCXc6I`a=?%R{ zZkxx^c0q`wI{nUW?-4Xle;@4k_u4M^y$ygKwI9>p`;Q-Q?{}!Z;qJD#v&VgH!^F7T zP*=3ke(dh{+ik*o+uH$X+cb_2p!(oom&UQP+uQE-dxEao{q25_+S~O8k6d?`=cD(y z-*i_)_EhgxjyZzYP-zONo z-u{8>FHv6FB_qIuCFZ zP9qJnZbB`x?DA&Oz#F5Tj;=h_xFfW5e2f+T2OE9z#A)nwoK1Kkq8XcQ_JG}Q+c+w9 z271xKKFc5N9sO6QV;coRY!^Y?Hz2kRh+FA)pZj$6t^0kLw8|G(1u2!aR zFVoS>4D4lg^fI2k%&uN$XfLy;mpQkW+1JZl*vlNScTy3Nr>BPDA#-R$p$h=Q9M(g$ z!{!E?KkSU>_{)%T{XckGMAQ=vP6yyH-*>SV?q?toz&6?!*L~RebN&;@I^;hQHR4Lr zGl^vYP^g3Qx)6ht2yc9BOPJ@tpRR~PVAkisF^rBP;Po{2M0G2<;MZQx*A9K{=X~9v zuY;VgyY$t|`MO76hdE#O>FasU*8}=`QO5Hg8Ps5b1K$i}T8kthw^IH#d`h!!J|_Y0 z6UXdI$2#Qhh4;C^@8xbHe&LoN_U4d}q0YllM70m&R_slOJVHN=4-Wy1C`><5yFK*1 z(LlGbVdnPNr`kS6psxJE^rF!bqy{f&ANgVX2lWPdsSyB4o@r5W-&kkYF)sY$kMv8D zT(+kJub-GZNuX2Ae3rh^N@P0=X$WT2IG9#XNQLD=BXJ856F!9~~`Z>s9$s4eYv9){=cw3wHY?y~Eq6ez>M>-MhkAHx?q`~E@ zcHh%UObB!OSPcRc#*F<>U5-cQMGb*!qoT2=BnFDOy^yT`meMe*9rwS{{5m09*O#a7>26ylH*lBcd79PRj&~GYUVgy$*!W$5l zEIdn$I!K*J`ffz|jRjA!FznyA|3E$xXiO&$6RCmQfcXTBTGg$fbBZ1V|JvKz*`Jw) ztlZ_iI%qYiS#sJ-J!HsxGlfrceQ16NX>1D|+gE{LU+ctDQn*f)72WyWU~;?{&b61? z!OAe7XnHKXP_Se>in^oT(4HER-2en*}s84@pRU zfd`em?xj1D^O!}8Jn}mE1<0Cyr@Ywzq$n=GWQHu{SQ}cGaZ$GSVNvchQN65J_@axabw{0NOP2p9(Wtz5PyCK4k}(XHO))+_eXzl1PY;}HQ9eg#J0%15Ahx5K`uVb zbh+~H#!V;@AJ=cC_8k0kgTBG~Gb-s)xlM-8ubDa~i6QI#US#BjhYTA)iLjDWMxuB? zD?+@L&J(sZowwY_O`SIa$d|#B9i6^)%pJaimO4}0Efftoa)UuQ?z(-H^OaLjcj}%q zUMzUy@#Cn`5|L+L9E%cikS7OS#@9Yec{ZPbORq^D6JkfAf1(R|; z6G7%-m24C(*v#h-4GpZq%3O#q(j{TPh3SIU&QX@r(vI|3vlMPl8&Z9gFkh5NxUr{Z zV}u26%uhrNi=-gWMXZruSL!MGJw-}fIDHP$4owPoUzQ`Zl->|2r$8xFMtMbAuwrsE zsVhZ$fU%0UJUlPThUgH-lbknbT^MI=10fq_^lm%~6TAu({YNfra!-U3OZ$Lfq0htU zx==@#MRHneR}Isec4;7~Rn{~R0ACX-!yoMOSV7fQN(&ZER~+?IgpfX>=^cgAN#F2? zIE9;hcFvCG;j^H(MaazSQJ%bG0X4RWNJ3_);d`L9)=sid_ohO?9+JF6a^ z2V;dYkOj~@%3)nHwScl%_!EugPoV`!9>tZb)pJO{L_7U;dRR8S_KtFws z(WF*9vHPLC4I9qG(5NccgsnyiP3*1S7|OH;`9&<;FCA%5?0v#gmGVI(2DVGv|1a(T zarr1O?3;SfA7akkGMr$S z+);_!Mt*w9sXy|k*H%ALGyf&f=r{~0u6Y-0nIn3@L)3q7Uh>K?-xF_kC%y=fUJxNY zdHv_w8ooO`d>Ndh0K4wdzh;g~7W-idb%!JOoNNJ(lCNApyb7M^kd7UOBqC1ZeFg`` z?t2Xcu;Kjvhq~##d~|sD@ex+V74e(bdj@kj?v1X`B6q@xD5Hi-$L$EvB7KQ$k@H5e z666ctd8n9C_#IUu4HiK~1Z<4gE%Jjq>W3az+~IsyhxBi^k;J^_^a_Kde;hmOmtzrgnPc+EzP+DDNrY?vUo)>enMP0K zR}5UuRv#Z9L7&;mLxR+;K0ZEb$i5>-paSMNIG}no3-I0t3ghyPd>}Gq2MtvCKp2RS zL-Qzf2exAlIyi4|5f}XpyTD11Cj*xrBye%;&w9RO_%Kt+uZCGH(@QA)K7o1ak>}=H z*XZ|=>ZTuj%0`YKc)i)VNM4pyfjZAeVc-#$?#sWd*ihvT51)&UU_2BY{84geqRkm2 z{g}ZvQmvw=_x^5|vdzCCMs-R?3t2o!9`z(Wq~oM+LxG!wc)Jp9Bn{BXK8vNeYF+8# z&ZNw_$uiKOC%*xYw7|mG&i}u?FMn?$NfLcO`>!a}-{&bA+4#aRGHBP(rpK=_u(oi| zd^E2{mP)o3OY-V4u#D$#e;E;ZL>_fWKA>k*vrAi5nURs1k&%&+ajd{SPZ){3YJM$w z=O~+VhRnFpWoG* zS2-kfa$S!g`@_!kLgkC_zIJ7v0r|aIa~dg7Tgp&`DqBHQyoUj64&URDJZm=UbtoKl zt>N<;QQi29I0`6W5Q`zUuy>H{R>N_z!ozh9^9st|z1Odk-}a6Vlas^b;PBnsqvmm( zF;&&2pQh+Fn(>{@^)LI)O@Cut_3x!vGJ$boyce994>c@1!18PO~k*n`}>NWwY9Zq zZ*(?pxGT{k;Tx^Uq6-9SJ6=(>sxk4;8X_lU_b`64RPL}zrq;MK~8$<2a7a8FcXXc z{*##VNKOtHCT}+)&~zngj47Q;QT?FsuSbc)3Ij8FSgce*7Ws^mp5U-w<}*R+>E=dptI4kjm%S4r7GB8K8kw9NCH%21N{YVA|cghQol>@-DNGV(D`>@yiE zojcVPOM_*sCaXmbV`sZO3=jhYFkY3#qbp7+K>%fu=nSVoOA>+=8d9B$rh`udG4mC= zqQ5Sfgt0dZ*x2~P#~KgRZsHNstvE{@uiC9>%URwMUd~wo*NsIU**)}3U|NhP%xsob zbmmGes#uoZ`U|5biFfa#@mN%&xyy!ux{JXmR#fd@fxPqxz^@1>&Zb23CWitmy{*kk z0fkk1JKJsT7$2nwCh0=!jM-K)~+ghW8wn2-XtdFH1#{WFUA_be)S#QW0f=fqA3Uev zQ}VYnOFG`{b@tFQXx_-eH#R)FH9ll+VmB7!_Szmy6$=*jsiqRG`mM8Gdo6e&+-#^U zb@H%^2UIwdLX)Hv!z1eRs7Z;~-@ZP0(~KeAUh5R~uB+k*HJJ3ey>zrHU_x|p*eOk8 zSxr2HKN@~RY7?8Sy^P)&eh*4Z@!z-^O<0%#{atD`QB7eX??XVfNFET&hf;6JleMYX zSF4#Z3k0@EsBj6O(?`RA2@$k8RO_i~4{dP`8s^wTSFm){$jk_hi5Ry8(a0MfKyc}v z55?PssKpT%-YW?&IG*EYPH0Afi>p+BD;)FP#~0`UxvMp@P-c?9itH@13|KP=Ch()SNK zkT}D`P=W4v3$7rBMpx0q8s*evGa-3W^XLSIy5nk zV%*Q8!L)yxLP`dCM_Hv*wM_U|@o=$xLghbf%cxW97^`asBY8cccwik=KY~yKol)Y? zGtuxr{t*dG(|)^uN#EcG0!*bi=o-X)c;L&iOhN(-^OPhwWz&IlI2P@9I4USP5+0Xd zV+n|E8{vM0p=DQEimcO+tcX@>aLdQx?1sxi@-AJHDn8T|jiW0JUB=`qu*e3-sZlRL z#E|TZwOuVIKH!zs#G0IZ<&q)SezC@3uCJAyJc6M+@Om96?EM71B1Q8rr-C^9vgMff zvlf{ls9A{5v>?U9hlCsVcU!%S7}U|n6Hryx-{akMb9kVM;3Y1t3X~zkjmy?(3}I78 zqv<8sVBl&YrH?w2gy;{RYd#hXC4WR^S~WqRrD>JJVaoWZem!Vm<9{#tF|7sYjCaI@GcE;#&PdU0_%89A+lS&LHC13x=} z%{Yg>1of^aJJcO8ifd+O?srgXCc+j4APgw00zgm>SN3S(Dkd=)s_EP=l8->b`je*( zxd%as)do6gj!*`PtEldo#MZmjhD3qaDlKTp@>%3drh2gjRdE%&oAj3B5S&T~i4|6@ zGhy%ovjSaXP~wO#kUMdb2!1jBk_Z}JUS@B*tL2^&V`u-z|D{Ko$ zKBwu^f(E2w@42?3`)hOm=ndY|J8?@m$-z+g zF!60wEyAqNj_d*05iLHCDrBG7I_)L$+>op%8_9Zw3j=aC%#hdX@1Pp6J}R!oDU&`e zw}s8wTG*VYg^k%-*sw)HElva~zNgy&lLZqGf`t}tvr(xya^_GeeU(&d$u&&3z5fOB z2}Uao32e+_CVDi@+Y8ZjhA~6T>mkv}_nIoR3s`g+rg*QiP4QWuEy(V0g6ptbj~1sC ztaUy=Q;O@}Nuo4YN^AkwHN{b*kg?6V#|Ee24kr{z3=Zd&-^k#VuiPHGM7uy!`(mK9 zbQECUvSlVVft1f>rKmH-G>WYVP0AttC61Kf-c@%;aKV=EY=&1i4lMK>rg0+VkQCBr zsCA(Yea-n@4cr6!9?6$dfbRDFMg~aRyqa(+Msmxpj_1 zC}vSYdE7GRy@1pu*Jg<#0g{d;ChKIdqhDUXeX;l2FeJDEeEaj;_+4)}86EdN4M(kN z9l}&ai`B0Gg2I z#_K;BX%%#z%>lFUV&f3HP_o8mLYDkO$|iNXk%z0r`ol0JZ;(}2IF9oVF+mHDuv)8H z7W@u%;W5TAv#ne7ss?%;7DO3s#Yo6gV3JS;?Z7 z3UkiW)!m(q+);|2`}LHh=$7wI(!MSaMY#mxj}1QuG6;G(IHG8vW_eN6YMff39nwC3 zNFL=HORiB+)MPkHWXK4Q_tv5Sa3PFAB)zhH>2~(3IoZF3zGC2^(J9_8439UYz&8aN zl(~5I4Tr>HSCacY=#6Q!mL7WA=|`$rEH@}^>>&HN+Q49QYKbc4XpVD~1+~~gil3O} zusU-BTvyhXF`A-A5Iu+MB5D9gAnO{SIatRQIE)3Q@s$x;xE|m}K3sR#VaqN}-#z7Y z4c^pD)GODZO!v2(m)SS9rx@c88E49K3%jjODv0Q@207JOznAG+B_x%S%c4lq5wHe!2={bX<2QHH^@?1`k)M1FelgmsQ4H}#pkltMtOjjO&`2JQak>*3k!^eVlG)gNMfMy+au-1-F-$zEF{<23;@Te6mMBG5 zXpoC0(=sbeh}0+pu0g8XPO`mfwELh6^Z#`r@X_RGO#<|fgk?7VFb*Eh_~;)I@7y<5A1Q~qTR1=UA3>U6>Jd} z5t}-C^PK~Ri0TDyu=UO*mMLVqP`dh=_f!pt7WnM26p+BxdH6=OX5q|k%5!V8>v0Fu zSq(i6IaOY?I)=5v(rJmwz&LsSJ)=GQE<4J(y0&|3ZiAg-Zm$9@z%4YGKFcf8TfB>& z=^nZyE%Ra@;BPP15OB+n_F9#@pNjq9~xNfINI|RfDF$l7rCImPPJsZsCM!tU@kMu79aEtUxHlm6i;xx1mSW z5Y27X!L#!F0Noi@(bn?vVhTRVy}|0qVFa2AtW?L&Wrh2J6585|WsD>})ree^v6N%m zL^dCxsWaBV%;A(7JS;R?oeqRg zmu!Q6=$6jYFYq_^O#8eIyWO$r8E-mT{{n4GD5m{rRU=@Oxj4tbo(Q;kXBm#6EElE@ zl;=z}w(NVDel3HhY$pJQz7ffk;gOYUm3LHzy3%ADA@F)&=`;L@t8)`0pQHsr+nH0c zeJR^w`X=eg(~~~8I?8a5j6A?B==#m`uYB+4=J`MRNw1TfV>I`SG$8r;Ki0Q5);HYz z9|HQ;BLBxdJd2bbiLXtQ=egR+#9D?8aLPv(R#}5# zvI<@d+n*A#I!2vmW|A8bypFRd#VC_LrC%dk&?or1z%ng~F@@%_hReioAXiU%PvV<^ z%k^##%x6nZ!`k%4)}0~xO!A{LUhqeH&5vKYnNe$;YBbDwLN{gvDw+pA2fChw_Cfsq zsJqA}RK0+xcUCxb1I*61P>#|e3Bt`MICE`spE|ndH0A2`e=_R34K(n~MaP4vo{f~& z4H5+=Ri&MB$xcqKF7>Z10snhHH?SI{=dax z;Rie{AXh2O04TP}-f-=lXWo0(x;Pt(VLrFA`L)}q;AU^guXo1Wfih!5_Ibm}04OMT zB*f3wX!7;Zsn}9?w(Zn@ZW)#9*Dh7&ER}VtnVdr`>qN*9t&7OMU2+TwckQy;nz{I!8%XiIgZ#L;4Ad$EN zooO_v0qpg7_a=bfp=vt-nsnad-P~@%9NWFD$zbCx<>Q3W2~d!Q3Obx4t`ouJTI2R` zjh{sUB=swihszs|)QW+~?<|X;0-RUFQQA8jsGAQkA)q(ruAhTk^5fPXym@`_WP+JJOC>oMCCnH6rIL(?d^%?THhZN$p};luhz1xsJ&I5${-9gh6ow*nUb zrgwPoyJgz-=|%VGx0IiSsGe*jI#ShyBZ zfYED}Y!nteunb7`G@W#YpCwncQjY%9{)X2nz*>^kMpy8*@wxg=7b#KXly|i>s!?)n zsLGh6Nld>Wx2cz7E~~Q4pmZeF1rG13*E2qNd18aCPpJ>k(8ptf`k)=+j!M%tO5t)p z8Kqspa3NTDCvBs-OYC#is=T3BD=Adu10V}3lrBypZZT#K-Q1LBi8ieyn|cy?l^}Z4$c!}YHEy%tnXWD?w9sBiEr^(!cE;A0+SJ9Ah9I+B*$*tBCRKB~v&Eo?fJ4TS6N% z^Cls_mIe0s&EC7?zr1aR!Hx&5%klXTsSQNfjcoWW9Ym-O<~>{>|$=ZSXQAFZS8#qm>hyBaHBj*<6bUcov7Hoan*rxEc?&nP`n4e%inEdoK>uIzR2*0vY_ElP_?Yl?3j6@(IT~ zAc5Z%?^JTh;oG0zzuxDPi6)4f2_-gN32rN;jD%9Tjfu>X^$oQ-1}c!e5w029$P{YJnX@L-*f;q+o;u^_P{r&(>A4YnfR4INF{JrZWN*MiVJqN0Y6wgWV%U=v&vzF3a|pINnLV5 zQ7EBdqZpwu%c&>1iq0=Yv6nR%A@h&(s>63yT<*JxW{15rw|cO=hUV7uA+aRxyuV

uyi9Kki1|1f+vEqsPuU)} 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 namespace proxy_wasm { diff --git a/src/common/wasm_util.h b/src/common/bytecode_util.h similarity index 94% rename from src/common/wasm_util.h rename to src/common/bytecode_util.h index 4473fdf70..fdd3fbf06 100644 --- a/src/common/wasm_util.h +++ b/src/common/bytecode_util.h @@ -45,7 +45,7 @@ class BytecodeUtil { * the function name subsection in "name" custom section. * See https://webassembly.github.io/spec/core/appendix/custom.html#binary-funcnamesec for detail. * @param bytecode is the target bytecode. - * @param ret the reference to store map from function indexes to function names. + * @param ret is the reference to store map from function indexes to function names. * @return indicates whether parsing succeeded or not. */ static bool getFunctionNameIndex(std::string_view bytecode, @@ -54,7 +54,7 @@ class BytecodeUtil { /** * getStrippedSource gets Wasm module without Custom Sections to save some memory in workers. * @param bytecode is the original bytecode. - * @param ret the reference to the stripped bytecode. + * @param ret is the reference to the stripped bytecode. * @return indicates whether parsing succeeded or not. */ static bool getStrippedSource(std::string_view bytecode, std::string &ret); diff --git a/src/v8/v8.cc b/src/v8/v8.cc index 105b45e0d..943800d23 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -25,7 +25,7 @@ #include #include -#include "src/common/wasm_util.h" +#include "src/common/bytecode_util.h" #include "v8.h" #include "v8-version.h" @@ -290,7 +290,7 @@ bool V8::load(const std::string &code, bool allow_precompiled) { wasm::vec code_vec = wasm::vec::invalid(); if (stripped.empty()) { // Use the original bytecode. - code_vec = wasm::vec::make(code.size(), (char *)(code.data())); + code_vec = wasm::vec::make(code.size(), code.data()); } else { // Othewise use the stripped bytecode. code_vec = wasm::vec::make(stripped.size(), stripped.data()); diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index 116ae3e25..34ba1bad3 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -25,7 +25,7 @@ #include #include "include/proxy-wasm/wasm_vm.h" -#include "src/common/wasm_util.h" +#include "src/common/bytecode_util.h" #include "src/wasmtime/types.h" #include "wasmtime/include/wasm.h" diff --git a/src/wavm/wavm.cc b/src/wavm/wavm.cc index 2b3bad9a7..f37b27b10 100644 --- a/src/wavm/wavm.cc +++ b/src/wavm/wavm.cc @@ -27,7 +27,7 @@ #include #include -#include "src/common/wasm_util.h" +#include "src/common/bytecode_util.h" #include "WAVM/IR/Module.h" #include "WAVM/IR/Operators.h" diff --git a/test/common/BUILD b/test/common/BUILD index c06b9723a..c76fc5e48 100644 --- a/test/common/BUILD +++ b/test/common/BUILD @@ -2,8 +2,8 @@ load("@rules_cc//cc:defs.bzl", "cc_test") load("@proxy_wasm_cpp_host//bazel:variables.bzl", "COPTS") cc_test( - name = "wasm_util_test", - srcs = ["wasm_util_test.cc"], + name = "bytecode_util_test", + srcs = ["bytecode_util_test.cc"], copts = COPTS, data = [ "//test/test_data:abi_export.wasm", diff --git a/test/common/wasm_util_test.cc b/test/common/bytecode_util_test.cc similarity index 99% rename from test/common/wasm_util_test.cc rename to test/common/bytecode_util_test.cc index d8138bcf9..9560119bf 100644 --- a/test/common/wasm_util_test.cc +++ b/test/common/bytecode_util_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "src/common/wasm_util.h" +#include "src/common/bytecode_util.h" #include #include From 305d48d1afdd5bf8c6f4dad015404cd48828ef79 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 11:14:22 +0900 Subject: [PATCH 13/18] Add ABI parse in BytecodeUtil Signed-off-by: Takeshi Yoneda --- src/common/bytecode_util.cc | 62 +++++++++++++++++++++++++++++++ src/common/bytecode_util.h | 10 +++++ test/common/bytecode_util_test.cc | 7 ++++ 3 files changed, 79 insertions(+) diff --git a/src/common/bytecode_util.cc b/src/common/bytecode_util.cc index c81966836..3d1ee84ff 100644 --- a/src/common/bytecode_util.cc +++ b/src/common/bytecode_util.cc @@ -23,6 +23,68 @@ bool BytecodeUtil::checkWasmHeader(std::string_view bytecode) { return bytecode.size() < 8 || !::memcmp(bytecode.data(), wasm_magic_number, 4); } +bool BytecodeUtil::getAbiVersion(std::string_view bytecode, proxy_wasm::AbiVersion &ret) { + ret = proxy_wasm::AbiVersion::Unknown; + // Check Wasm header. + if (!checkWasmHeader(bytecode)) { + return false; + } + // Skip the Wasm header. + const char *pos = bytecode.data() + 8; + const char *end = bytecode.data() + bytecode.size(); + while (pos < end) { + if (pos + 1 > end) { + return false; + } + const auto section_type = *pos++; + uint32_t section_len = 0; + if (!parseVarint(pos, end, section_len) || pos + section_len > end) { + return false; + } + if (section_type == 7 /* export section */) { + uint32_t export_vector_size = 0; + if (!parseVarint(pos, end, export_vector_size) || pos + export_vector_size > end) { + return false; + } + // Search thourgh exports. + for (uint32_t i = 0; i < export_vector_size; i++) { + // Parse name of the export. + uint32_t export_name_size = 0; + if (!parseVarint(pos, end, export_name_size) || pos + export_name_size > end) { + return false; + } + const std::string export_name = {pos, export_name_size}; + pos += export_name_size; + if (pos + 1 > end) { + return false; + } + // Check if it is a function type export + if (*pos++ == 0x00) { + // Check the name of the function. + if (export_name == "proxy_abi_version_0_1_0") { + ret = AbiVersion::ProxyWasm_0_1_0; + return true; + } else if (export_name == "proxy_abi_version_0_2_0") { + ret = AbiVersion::ProxyWasm_0_2_0; + return true; + } else if (export_name == "proxy_abi_version_0_2_1") { + ret = AbiVersion::ProxyWasm_0_2_1; + return true; + } + } + // Skip export's index. + if (!parseVarint(pos, end, export_name_size)) { + return false; + } + } + return false; + } else { + pos += section_len; + } + } + return true; +} + bool BytecodeUtil::getCustomSection(std::string_view bytecode, std::string_view name, std::string_view &ret) { // Check Wasm header. diff --git a/src/common/bytecode_util.h b/src/common/bytecode_util.h index fdd3fbf06..2937d88b4 100644 --- a/src/common/bytecode_util.h +++ b/src/common/bytecode_util.h @@ -17,6 +17,8 @@ #include #include +#include "include/proxy-wasm/wasm_vm.h" + namespace proxy_wasm { namespace common { @@ -30,6 +32,14 @@ class BytecodeUtil { */ static bool checkWasmHeader(std::string_view bytecode); + /** + * checkWasmHeader extracts ABI version from the bytecode. + * @param bytecode is the target bytecode. + * @param ret is the reference to store the extracted ABI version or UnKnonw if it doesn't exist. + * @return indicates whether parsing succeeded or not. + */ + static bool getAbiVersion(std::string_view bytecode, proxy_wasm::AbiVersion &ret); + /** * getCustomSection extract the view of the custom section for a given name. * @param bytecode is the target bytecode. diff --git a/test/common/bytecode_util_test.cc b/test/common/bytecode_util_test.cc index 9560119bf..65329cc80 100644 --- a/test/common/bytecode_util_test.cc +++ b/test/common/bytecode_util_test.cc @@ -107,5 +107,12 @@ TEST(TestWasmCommonUtil, getStrippedSource) { EXPECT_EQ(actual.size(), source.size() - custom_section.size()); } +TEST(TestWasmCommonUtil, getAbiVersion) { + const auto source = readTestWasmFile("abi_export.wasm"); + proxy_wasm::AbiVersion actual; + EXPECT_TRUE(BytecodeUtil::getAbiVersion(source, actual)); + EXPECT_EQ(actual, proxy_wasm::AbiVersion::ProxyWasm_0_2_0); +} + } // namespace common } // namespace proxy_wasm From 41a9ac6a9f5e86990812181ec3447747c3781480 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 11:40:46 +0900 Subject: [PATCH 14/18] Use BytecodeUtil in getAbiVersion on WasmVm except NullVm Signed-off-by: Takeshi Yoneda --- ...a7f12734ef0bd58448b3b3e7f7f7c3604.tar.gz.1 | Bin 98125 -> 0 bytes src/common/bytecode_util.cc | 2 +- src/v8/v8.cc | 30 ++++++---------- src/wasmtime/wasmtime.cc | 33 ++++++------------ src/wavm/wavm.cc | 30 +++++----------- 5 files changed, 31 insertions(+), 64 deletions(-) delete mode 100644 57bb777a7f12734ef0bd58448b3b3e7f7f7c3604.tar.gz.1 diff --git a/57bb777a7f12734ef0bd58448b3b3e7f7f7c3604.tar.gz.1 b/57bb777a7f12734ef0bd58448b3b3e7f7f7c3604.tar.gz.1 deleted file mode 100644 index e42673a2d8d3f1942c037d5fe3cb3c70c81905b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98125 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

uyi9Kki1|1f+vEqsPuU)} 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 host_functions_; std::unordered_map> module_functions_; + AbiVersion abi_version_; std::unordered_map function_names_index_; }; @@ -259,6 +260,12 @@ bool V8::load(const std::string &code, bool allow_precompiled) { return false; } + // Get ABI version from bytecode. + if (!common::BytecodeUtil::getAbiVersion(code, abi_version_)) { + fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); + return false; + } + if (allow_precompiled) { const auto section_name = getPrecompiledSectionName(); if (!section_name.empty()) { @@ -290,7 +297,7 @@ bool V8::load(const std::string &code, bool allow_precompiled) { wasm::vec code_vec = wasm::vec::invalid(); if (stripped.empty()) { // Use the original bytecode. - code_vec = wasm::vec::make(code.size(), code.data()); + code_vec = wasm::vec::make(code.size(), (char *)(code.data())); } else { // Othewise use the stripped bytecode. code_vec = wasm::vec::make(stripped.size(), stripped.data()); @@ -320,6 +327,7 @@ std::unique_ptr V8::clone() { clone->module_ = wasm::Module::obtain(clone->store_.get(), shared_module_.get()); clone->function_names_index_ = function_names_index_; + clone->abi_version_ = abi_version_; return clone; } @@ -340,25 +348,7 @@ std::string_view V8::getPrecompiledSectionName() { return name; } -AbiVersion V8::getAbiVersion() { - assert(module_ != nullptr); - - const auto export_types = module_.get()->exports(); - for (size_t i = 0; i < export_types.size(); i++) { - if (export_types[i]->type()->kind() == wasm::EXTERN_FUNC) { - std::string_view name(export_types[i]->name().get(), export_types[i]->name().size()); - if (name == "proxy_abi_version_0_1_0") { - return AbiVersion::ProxyWasm_0_1_0; - } else if (name == "proxy_abi_version_0_2_0") { - return AbiVersion::ProxyWasm_0_2_0; - } else if (name == "proxy_abi_version_0_2_1") { - return AbiVersion::ProxyWasm_0_2_1; - } - } - } - - return AbiVersion::Unknown; -} +AbiVersion V8::getAbiVersion() { return abi_version_; } bool V8::link(std::string_view debug_name) { assert(module_ != nullptr); diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index 34ba1bad3..d3b14a8b6 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -103,12 +103,13 @@ class Wasmtime : public WasmVm { WasmModulePtr module_; WasmSharedModulePtr shared_module_; WasmInstancePtr instance_; - WasmMemoryPtr memory_; WasmTablePtr table_; std::unordered_map host_functions_; std::unordered_map module_functions_; + + AbiVersion abi_version_; }; bool Wasmtime::load(const std::string &code, bool allow_precompiled) { @@ -119,6 +120,12 @@ bool Wasmtime::load(const std::string &code, bool allow_precompiled) { return false; } + // Get ABI version from bytecode. + if (!common::BytecodeUtil::getAbiVersion(code, abi_version_)) { + fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); + return false; + } + std::string stripped_vec; if (!common::BytecodeUtil::getStrippedSource(code, stripped_vec)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); @@ -150,6 +157,8 @@ std::unique_ptr Wasmtime::clone() { clone->integration().reset(integration()->clone()); clone->store_ = wasm_store_new(engine()); clone->module_ = wasm_module_obtain(clone->store_.get(), shared_module_.get()); + clone->abi_version_ = abi_version_; + return clone; } @@ -645,27 +654,7 @@ void Wasmtime::getModuleFunctionImpl(std::string_view function_name, }; }; -AbiVersion Wasmtime::getAbiVersion() { - assert(module_ != nullptr); - WasmExportTypeVec export_types; - wasm_module_exports(module_.get(), export_types.get()); - - for (size_t i = 0; i < export_types.get()->size; i++) { - const wasm_externtype_t *exp_extern_type = wasm_exporttype_type(export_types.get()->data[i]); - if (wasm_externtype_kind(exp_extern_type) == WASM_EXTERN_FUNC) { - const wasm_name_t *name_ptr = wasm_exporttype_name(export_types.get()->data[i]); - std::string_view name(name_ptr->data, name_ptr->size); - if (name == "proxy_abi_version_0_1_0") { - return AbiVersion::ProxyWasm_0_1_0; - } else if (name == "proxy_abi_version_0_2_0") { - return AbiVersion::ProxyWasm_0_2_0; - } else if (name == "proxy_abi_version_0_2_1") { - return AbiVersion::ProxyWasm_0_2_1; - } - } - } - return AbiVersion::Unknown; -} +AbiVersion Wasmtime::getAbiVersion() { return abi_version_; } } // namespace wasmtime diff --git a/src/wavm/wavm.cc b/src/wavm/wavm.cc index f37b27b10..d3a4d7627 100644 --- a/src/wavm/wavm.cc +++ b/src/wavm/wavm.cc @@ -279,6 +279,7 @@ Wavm::~Wavm() { std::unique_ptr Wavm::clone() { auto wavm = std::make_unique(); wavm->integration().reset(integration()->clone()); + wavm->abi_version_ = abi_version_; wavm->compartment_ = WAVM::Runtime::cloneCompartment(compartment_); wavm->memory_ = WAVM::Runtime::remapToClonedCompartment(memory_, wavm->compartment_); @@ -302,7 +303,13 @@ bool Wavm::load(const std::string &code, bool allow_precompiled) { if (!loadModule(code, ir_module_)) { return false; } - getAbiVersion(); // Cache ABI version. + + // Get ABI version from bytecode. + if (!common::BytecodeUtil::getAbiVersion(code, abi_version_)) { + fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); + return false; + } + std::string_view precompiled = {}; if (allow_precompiled) { if (!common::BytecodeUtil::getCustomSection(code, getPrecompiledSectionName(), precompiled)) { @@ -319,26 +326,7 @@ bool Wavm::load(const std::string &code, bool allow_precompiled) { return true; } -AbiVersion Wavm::getAbiVersion() { - if (abi_version_ != AbiVersion::Unknown) { - return abi_version_; - } - for (auto &e : ir_module_.exports) { - if (e.name == "proxy_abi_version_0_1_0") { - abi_version_ = AbiVersion::ProxyWasm_0_1_0; - return abi_version_; - } - if (e.name == "proxy_abi_version_0_2_0") { - abi_version_ = AbiVersion::ProxyWasm_0_2_0; - return abi_version_; - } - if (e.name == "proxy_abi_version_0_2_1") { - abi_version_ = AbiVersion::ProxyWasm_0_2_1; - return abi_version_; - } - } - return AbiVersion::Unknown; -} +AbiVersion Wavm::getAbiVersion() { return abi_version_; } bool Wavm::link(std::string_view debug_name) { RootResolver rootResolver(compartment_, this); From 808a8691a450864c51bf22a0e2b28160107f4d9c Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 11:46:08 +0900 Subject: [PATCH 15/18] Construct string only when it is function export. Signed-off-by: Takeshi Yoneda --- src/common/bytecode_util.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/bytecode_util.cc b/src/common/bytecode_util.cc index 9826d1677..a79bb9295 100644 --- a/src/common/bytecode_util.cc +++ b/src/common/bytecode_util.cc @@ -53,13 +53,14 @@ bool BytecodeUtil::getAbiVersion(std::string_view bytecode, proxy_wasm::AbiVersi if (!parseVarint(pos, end, export_name_size) || pos + export_name_size > end) { return false; } - const std::string export_name = {pos, export_name_size}; + const auto name_begin = pos; pos += export_name_size; if (pos + 1 > end) { return false; } // Check if it is a function type export if (*pos++ == 0x00) { + const std::string export_name = {name_begin, export_name_size}; // Check the name of the function. if (export_name == "proxy_abi_version_0_1_0") { ret = AbiVersion::ProxyWasm_0_1_0; From 1dd2bc1e4cef10eaf691f11e7d3800f831943f83 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 15:04:33 +0900 Subject: [PATCH 16/18] review: fix style and remove redundant WasmHeader check Signed-off-by: Takeshi Yoneda --- src/common/bytecode_util.cc | 2 ++ src/common/bytecode_util.h | 4 ++-- src/v8/v8.cc | 6 ------ src/wasmtime/wasmtime.cc | 5 ----- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/common/bytecode_util.cc b/src/common/bytecode_util.cc index a79bb9295..b9f911855 100644 --- a/src/common/bytecode_util.cc +++ b/src/common/bytecode_util.cc @@ -19,6 +19,7 @@ namespace proxy_wasm { namespace common { bool BytecodeUtil::checkWasmHeader(std::string_view bytecode) { + // Wasm file header is 8 bytes (magic number + version). static const uint8_t wasm_magic_number[4] = {0x00, 0x61, 0x73, 0x6d}; return bytecode.size() < 8 || !::memcmp(bytecode.data(), wasm_magic_number, 4); } @@ -29,6 +30,7 @@ bool BytecodeUtil::getAbiVersion(std::string_view bytecode, proxy_wasm::AbiVersi if (!checkWasmHeader(bytecode)) { return false; } + // Skip the Wasm header. const char *pos = bytecode.data() + 8; const char *end = bytecode.data() + bytecode.size(); diff --git a/src/common/bytecode_util.h b/src/common/bytecode_util.h index 2937d88b4..dee0a0ffb 100644 --- a/src/common/bytecode_util.h +++ b/src/common/bytecode_util.h @@ -33,9 +33,9 @@ class BytecodeUtil { static bool checkWasmHeader(std::string_view bytecode); /** - * checkWasmHeader extracts ABI version from the bytecode. + * getAbiVersion extracts ABI version from the bytecode. * @param bytecode is the target bytecode. - * @param ret is the reference to store the extracted ABI version or UnKnonw if it doesn't exist. + * @param ret is the reference to store the extracted ABI version or UnKnown if it doesn't exist. * @return indicates whether parsing succeeded or not. */ static bool getAbiVersion(std::string_view bytecode, proxy_wasm::AbiVersion &ret); diff --git a/src/v8/v8.cc b/src/v8/v8.cc index b47be6e36..99b41d156 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -254,12 +254,6 @@ template constexpr T convertValTypesToArgsTuple(const U bool V8::load(const std::string &code, bool allow_precompiled) { store_ = wasm::Store::make(engine()); - // Wasm file header is 8 bytes (magic number + version). - if (!common::BytecodeUtil::checkWasmHeader(code)) { - fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); - return false; - } - // Get ABI version from bytecode. if (!common::BytecodeUtil::getAbiVersion(code, abi_version_)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index d3b14a8b6..704031779 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -115,11 +115,6 @@ class Wasmtime : public WasmVm { bool Wasmtime::load(const std::string &code, bool allow_precompiled) { store_ = wasm_store_new(engine()); - if (!common::BytecodeUtil::checkWasmHeader(code)) { - fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); - return false; - } - // Get ABI version from bytecode. if (!common::BytecodeUtil::getAbiVersion(code, abi_version_)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); From ed0f3a5b02d48e5412f7b55033e4f6bed142a16d Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 15:30:43 +0900 Subject: [PATCH 17/18] review: copy original bytecode. Signed-off-by: Takeshi Yoneda --- src/common/bytecode_util.cc | 4 ++++ src/common/bytecode_util.h | 2 +- src/v8/v8.cc | 9 +-------- src/wasmtime/wasmtime.cc | 8 +------- test/common/bytecode_util_test.cc | 7 +++++-- 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/common/bytecode_util.cc b/src/common/bytecode_util.cc index b9f911855..4b6a8a804 100644 --- a/src/common/bytecode_util.cc +++ b/src/common/bytecode_util.cc @@ -219,6 +219,10 @@ bool BytecodeUtil::getStrippedSource(std::string_view bytecode, std::string &ret } } } + if (ret.empty()) { + // Copy the original source code if it is empty. + ret = std::string(bytecode); + } return true; } diff --git a/src/common/bytecode_util.h b/src/common/bytecode_util.h index dee0a0ffb..438969fb5 100644 --- a/src/common/bytecode_util.h +++ b/src/common/bytecode_util.h @@ -64,7 +64,7 @@ class BytecodeUtil { /** * getStrippedSource gets Wasm module without Custom Sections to save some memory in workers. * @param bytecode is the original bytecode. - * @param ret is the reference to the stripped bytecode. + * @param ret is the reference to the stripped bytecode or a copy of the original bytecode. * @return indicates whether parsing succeeded or not. */ static bool getStrippedSource(std::string_view bytecode, std::string &ret); diff --git a/src/v8/v8.cc b/src/v8/v8.cc index 99b41d156..77ef796fe 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -288,14 +288,7 @@ bool V8::load(const std::string &code, bool allow_precompiled) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); return false; }; - wasm::vec code_vec = wasm::vec::invalid(); - if (stripped.empty()) { - // Use the original bytecode. - code_vec = wasm::vec::make(code.size(), (char *)(code.data())); - } else { - // Othewise use the stripped bytecode. - code_vec = wasm::vec::make(stripped.size(), stripped.data()); - } + wasm::vec code_vec = wasm::vec::make(stripped.size(), stripped.data()); module_ = wasm::Module::make(store_.get(), code_vec); } diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index 704031779..673eb0262 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -128,13 +128,7 @@ bool Wasmtime::load(const std::string &code, bool allow_precompiled) { }; WasmByteVec source_vec; - if (stripped_vec.empty()) { - // Use the original bytecode. - wasm_byte_vec_new(source_vec.get(), code.size(), code.data()); - } else { - // Othewise pass the stripped source code. - wasm_byte_vec_new(source_vec.get(), stripped_vec.size(), stripped_vec.data()); - } + wasm_byte_vec_new(source_vec.get(), stripped_vec.size(), stripped_vec.data()); module_ = wasm_module_new(store_.get(), source_vec.get()); if (module_) { diff --git a/test/common/bytecode_util_test.cc b/test/common/bytecode_util_test.cc index 65329cc80..50900c0ce 100644 --- a/test/common/bytecode_util_test.cc +++ b/test/common/bytecode_util_test.cc @@ -78,8 +78,11 @@ TEST(TestWasmCommonUtil, getStrippedSource) { auto source = readTestWasmFile("abi_export.wasm"); std::string actual; EXPECT_TRUE(BytecodeUtil::getStrippedSource(source, actual)); - // No `precompiled_` is found in the custom sections. - EXPECT_TRUE(actual.empty()); + // If no `precompiled_` is found in the custom sections, + // then the copy of the original should be returned. + EXPECT_FALSE(actual.empty()); + EXPECT_TRUE(actual.data() != source.data()); + EXPECT_EQ(actual, source); // Append "precompiled_test" custom section std::vector custom_section = {// custom section id From c639e2ccc47e489663c19d24ebd3d0bc7f380ff8 Mon Sep 17 00:00:00 2001 From: Takeshi Yoneda Date: Tue, 13 Apr 2021 15:43:43 +0900 Subject: [PATCH 18/18] style: align var names across v8 and wasmtime Signed-off-by: Takeshi Yoneda --- src/v8/v8.cc | 4 ++-- src/wasmtime/wasmtime.cc | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/v8/v8.cc b/src/v8/v8.cc index 77ef796fe..14ba46f65 100644 --- a/src/v8/v8.cc +++ b/src/v8/v8.cc @@ -288,8 +288,8 @@ bool V8::load(const std::string &code, bool allow_precompiled) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); return false; }; - wasm::vec code_vec = wasm::vec::make(stripped.size(), stripped.data()); - module_ = wasm::Module::make(store_.get(), code_vec); + wasm::vec stripped_vec = wasm::vec::make(stripped.size(), stripped.data()); + module_ = wasm::Module::make(store_.get(), stripped_vec); } if (module_) { diff --git a/src/wasmtime/wasmtime.cc b/src/wasmtime/wasmtime.cc index 673eb0262..3ff503645 100644 --- a/src/wasmtime/wasmtime.cc +++ b/src/wasmtime/wasmtime.cc @@ -121,15 +121,15 @@ bool Wasmtime::load(const std::string &code, bool allow_precompiled) { return false; } - std::string stripped_vec; - if (!common::BytecodeUtil::getStrippedSource(code, stripped_vec)) { + std::string stripped; + if (!common::BytecodeUtil::getStrippedSource(code, stripped)) { fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module"); return false; }; - WasmByteVec source_vec; - wasm_byte_vec_new(source_vec.get(), stripped_vec.size(), stripped_vec.data()); - module_ = wasm_module_new(store_.get(), source_vec.get()); + WasmByteVec stripped_vec; + wasm_byte_vec_new(stripped_vec.get(), stripped.size(), stripped.data()); + module_ = wasm_module_new(store_.get(), stripped_vec.get()); if (module_) { shared_module_ = wasm_module_share(module_.get());