/* Copyright 2017 - 2025 R. Thomas * Copyright 2017 - 2025 Quarkslab * * 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 #include #include "logging.hpp" #include "LIEF/BinaryStream/MemoryStream.hpp" #include "LIEF/BinaryStream/VectorStream.hpp" #include "LIEF/BinaryStream/SpanStream.hpp" #include "LIEF/BinaryStream/FileStream.hpp" #include "ELF/DataHandler/Handler.hpp" namespace LIEF { namespace ELF { namespace DataHandler { class DataHandlerStream : public BinaryStream { public: DataHandlerStream(std::vector& ref) : BinaryStream(STREAM_TYPE::ELF_DATA_HANDLER), data_{ref} { } ~DataHandlerStream() override = default; uint64_t size() const override { return data_.size(); } result read_at(uint64_t offset, uint64_t size, uint64_t /*va*/) const override { if (offset > data_.size() || (offset + size) > data_.size()) { return make_error_code(lief_errors::read_error); } return data_.data() + offset; } private: std::vector& data_; }; result> Handler::from_stream(std::unique_ptr& stream) { auto hdl = std::unique_ptr(new Handler{}); if (VectorStream::classof(*stream)) { auto& vs = static_cast(*stream); hdl->data_ = std::move(vs.move_content()); const uint64_t pos = vs.pos(); stream = std::make_unique(hdl->data_); stream->setpos(pos); return hdl; } if (SpanStream::classof(*stream)) { auto& vs = static_cast(*stream); hdl->data_ = vs.content(); return hdl; } if (FileStream::classof(*stream)) { auto& vs = static_cast(*stream); hdl->data_ = vs.content(); const uint64_t pos = vs.pos(); stream = std::make_unique(hdl->data_); stream->setpos(pos); return hdl; } if (MemoryStream::classof(*stream)) { return make_error_code(lief_errors::not_implemented); } LIEF_ERR("Unknown stream for Handler"); return make_error_code(lief_errors::not_supported); } bool Handler::has(uint64_t offset, uint64_t size, Node::Type type) { Node tmp{offset, size, type}; const auto it_node = std::find_if(std::begin(nodes_), std::end(nodes_), [&tmp] (const std::unique_ptr& node) { return tmp == *node; }); return it_node != std::end(nodes_); } result> Handler::get(uint64_t offset, uint64_t size, Node::Type type) { Node tmp{offset, size, type}; const auto it_node = std::find_if(std::begin(nodes_), std::end(nodes_), [&tmp] (const std::unique_ptr& node) { return tmp == *node; }); if (it_node == std::end(nodes_)) { return make_error_code(lief_errors::not_found); } return **it_node; } void Handler::remove(uint64_t offset, uint64_t size, Node::Type type) { Node tmp{offset, size, type}; const auto it_node = std::find_if(std::begin(nodes_), std::end(nodes_), [&tmp] (const std::unique_ptr& node) { return tmp == *node; }); if (it_node == std::end(nodes_)) { LIEF_ERR("Unable to find the node"); } nodes_.erase(it_node); } Node& Handler::create(uint64_t offset, uint64_t size, Node::Type type) { nodes_.push_back(std::make_unique(offset, size, type)); return *nodes_.back(); } Node& Handler::add(const Node& node) { nodes_.push_back(std::make_unique(node)); return *nodes_.back(); } ok_error_t Handler::make_hole(uint64_t offset, uint64_t size) { auto res = reserve(offset, size); if (!res) { return res; } data_.insert(std::begin(data_) + offset, size, 0); return ok(); } ok_error_t Handler::reserve(uint64_t offset, uint64_t size) { static constexpr auto MAX_MEMORY_SIZE = 6_GB; const auto full_size = static_cast(offset) + static_cast(size); if (full_size < 0) { return make_error_code(lief_errors::corrupted); } if (static_cast(full_size) > data_.max_size()) { return make_error_code(lief_errors::corrupted); } if (static_cast(full_size) > MAX_MEMORY_SIZE) { return make_error_code(lief_errors::corrupted); } const bool must_resize = data_.size() < (offset + size); if (!must_resize) { return ok(); } data_.resize(offset + size, 0); return ok(); } } // namespace DataHandler } // namespace ELF } // namespace LIEF