diff --git a/Changelog.md b/Changelog.md index 2f3067771..992de9c11 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,6 +15,7 @@ Bugfixes: * ABIEncoderV2: Fix internal error related to mappings as library parameters. * ABIEncoderV2: Fix invalid signature for events containing structs emitted in libraries. * Inline Assembly: Proper error message for missing variables. + * Optimizer: Fix internal error related to unused tag removal across assemblies. This never generated any invalid code. * SMTChecker: Fixed crash when used with fixed-sized arrays. * Yul: Properly detect name clashes with functions before their declaration. diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 7cf7137d2..6b9ece01e 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -390,7 +390,7 @@ Assembly& Assembly::optimise(OptimiserSettings const& _settings) map Assembly::optimiseInternal( OptimiserSettings const& _settings, - std::set const& _tagsReferencedFromOutside + std::set _tagsReferencedFromOutside ) { // Run optimisation for sub-assemblies. @@ -436,7 +436,22 @@ map Assembly::optimiseInternal( BlockDeduplicator dedup{m_items}; if (dedup.deduplicate()) { - tagReplacements.insert(dedup.replacedTags().begin(), dedup.replacedTags().end()); + for (auto const& replacement: dedup.replacedTags()) + { + assertThrow( + replacement.first <= size_t(-1) && replacement.second <= size_t(-1), + OptimizerException, + "Invalid tag replacement." + ); + assertThrow( + !tagReplacements.count(replacement.first), + OptimizerException, + "Replacement already known." + ); + tagReplacements[replacement.first] = replacement.second; + if (_tagsReferencedFromOutside.erase(size_t(replacement.first))) + _tagsReferencedFromOutside.insert(size_t(replacement.second)); + } count++; } } diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 1718fbaef..bb5a54b8c 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -154,7 +154,7 @@ protected: /// Does the same operations as @a optimise, but should only be applied to a sub and /// returns the replaced tags. Also takes an argument containing the tags of this assembly /// that are referenced in a super-assembly. - std::map optimiseInternal(OptimiserSettings const& _settings, std::set const& _tagsReferencedFromOutside); + std::map optimiseInternal(OptimiserSettings const& _settings, std::set _tagsReferencedFromOutside); unsigned bytesRequired(unsigned subTagSize) const;