diff --git a/wumsloader/src/module/ModuleDataFactory.cpp b/wumsloader/src/module/ModuleDataFactory.cpp index c653fd5..3dda318 100644 --- a/wumsloader/src/module/ModuleDataFactory.cpp +++ b/wumsloader/src/module/ModuleDataFactory.cpp @@ -18,6 +18,7 @@ #include "ModuleDataFactory.h" #include "fs/FileUtils.h" #include "utils/ElfUtils.h" +#include "utils/OnLeavingScope.h" #include "utils/logger.h" #include #include @@ -42,10 +43,11 @@ std::optional> ModuleDataFactory::load(const std::st return {}; } + auto cleanupBuffer = onLeavingScope([buffer]() { MEMFreeToDefaultHeap(buffer); }); + // Load ELF data if (!reader.load(reinterpret_cast(buffer), fsize)) { DEBUG_FUNCTION_LINE_ERR("Can't find or process %s", path.c_str()); - MEMFreeToDefaultHeap(buffer); return {}; } uint32_t sec_num = reader.sections.size(); @@ -53,7 +55,6 @@ std::optional> ModuleDataFactory::load(const std::st auto destinations = std::make_unique(sec_num); if (!destinations) { DEBUG_FUNCTION_LINE_ERR("Failed alloc memory for destinations array"); - MEMFreeToDefaultHeap(buffer); return {}; } @@ -85,7 +86,6 @@ std::optional> ModuleDataFactory::load(const std::st auto data = std::make_unique(text_size + data_size); if (!data) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory for the .text section (%d bytes)", text_size); - MEMFreeToDefaultHeap(buffer); return {}; } @@ -125,7 +125,6 @@ std::optional> ModuleDataFactory::load(const std::st destinations[psec->get_index()] -= 0xC0000000; } else { DEBUG_FUNCTION_LINE_ERR("Unhandled case"); - MEMFreeToDefaultHeap(buffer); return std::nullopt; } @@ -162,7 +161,6 @@ std::optional> ModuleDataFactory::load(const std::st DEBUG_FUNCTION_LINE("Linking (%d)... %s", i, psec->get_name().c_str()); if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], (uint32_t) text_data, (uint32_t) data_data, nullptr, 0)) { DEBUG_FUNCTION_LINE_ERR("elfLink failed"); - MEMFreeToDefaultHeap(buffer); return std::nullopt; } } @@ -240,7 +238,6 @@ std::optional> ModuleDataFactory::load(const std::st } else if (key == "wums") { if (value != "0.3") { DEBUG_FUNCTION_LINE_ERR("Warning: Ignoring module - Unsupported WUMS version: %s.", value.c_str()); - MEMFreeToDefaultHeap(buffer); return std::nullopt; } } @@ -307,8 +304,6 @@ std::optional> ModuleDataFactory::load(const std::st DEBUG_FUNCTION_LINE("Loaded %s size: %d kilobytes", path.c_str(), totalSize / 1024); - MEMFreeToDefaultHeap(buffer); - return moduleData; } diff --git a/wumsloader/src/utils/OnLeavingScope.h b/wumsloader/src/utils/OnLeavingScope.h new file mode 100644 index 0000000..2eb97f6 --- /dev/null +++ b/wumsloader/src/utils/OnLeavingScope.h @@ -0,0 +1,122 @@ +/** +* The contents of this file are based on the article posted at the +* following location: +* +* http://crascit.com/2015/06/03/on-leaving-scope-part-2/ +* +* The material in that article has some commonality with the code made +* available as part of Facebook's folly library at: +* +* https://github.com/facebook/folly/blob/master/folly/ScopeGuard.h +* +* Furthermore, similar material is currently part of a draft proposal +* to the C++ standards committee, referencing the same work by Andrei +* Alexandresu that led to the folly implementation. The draft proposal +* can be found at: +* +* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189.pdf +* +* With the above in mind, the content below is made available under +* the same license terms as folly to minimize any legal concerns. +* Should there be ambiguity over copyright ownership between Facebook +* and myself for any material included in this file, it should be +* interpreted that Facebook is the copyright owner for the ambiguous +* section of code concerned. +* +* Craig Scott +* 3rd June 2015 +* +* ---------------------------------------------------------------------- +* +* Copyright 2015 Craig Scott +* +* 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. +*/ + +#ifndef CRASCIT_ONLEAVINGSCOPE_H +#define CRASCIT_ONLEAVINGSCOPE_H + +#include +#include + + +/** +* This class is intended to be used only to create a local object on the +* stack. It accepts a function object in its constructor and will invoke +* that function object in its destructor. The class provides a move +* constructor so it can be used with the onLeavingScope factory function, +* but it cannot be copied. +* +* Do no use this function directly, use the onLeavingScope() factory +* function instead. +*/ +template +class OnLeavingScope +{ +public: + // Prevent copying + OnLeavingScope(const OnLeavingScope&) = delete; + OnLeavingScope& operator=(const OnLeavingScope&) = delete; + + // Allow moving + OnLeavingScope(OnLeavingScope&& other) : + m_func(std::move(other.m_func)), + m_owner(other.m_owner) + { + other.m_owner = false; + } + + OnLeavingScope(const Func& f) : + m_func(f), + m_owner(true) + { + } + OnLeavingScope(Func&& f) : + m_func(std::move(f)), + m_owner(true) + { + } + ~OnLeavingScope() + { + if (m_owner) + m_func(); + } + +private: + Func m_func; + bool m_owner; +}; + + +/** +* Factory function for creating an OnLeavingScope object. It is intended +* to be used like so: +* +* auto cleanup = onLeavingScope(...); +* +* where the ... could be a lambda function, function object or pointer to +* a free function to be invoked when the cleanup object goes out of scope. +* The function object must take no function arguments, but can return any +* type (the return value is ignored). +* +* The \a Func template parameter would rarely, if ever, be manually +* specified. Normally, it would be deduced automatically by the compiler +* from the object passed as the function argument. +*/ +template +OnLeavingScope::type> onLeavingScope(Func&& f) +{ + return OnLeavingScope::type>(std::forward(f)); +} + +#endif // CRASCIT_ONLEAVINGSCOPE_H