Add safety check for multi-fragment sequential categorizers

This commit is contained in:
Marcus Holland-Moritz 2023-07-18 13:54:53 +02:00
parent 33b2dfb95f
commit a9bf89aa0c
6 changed files with 33 additions and 0 deletions

View File

@ -49,6 +49,7 @@ class categorizer {
virtual ~categorizer() = default; virtual ~categorizer() = default;
virtual std::span<std::string_view const> categories() const = 0; virtual std::span<std::string_view const> categories() const = 0;
virtual bool is_single_fragment() const = 0;
}; };
class random_access_categorizer : public categorizer { class random_access_categorizer : public categorizer {
@ -98,6 +99,10 @@ class categorizer_job {
explicit operator bool() const { return impl_ != nullptr; } explicit operator bool() const { return impl_ != nullptr; }
bool has_multi_fragment_sequential_categorizers() const {
return impl_->has_multi_fragment_sequential_categorizers();
}
class impl { class impl {
public: public:
virtual ~impl() = default; virtual ~impl() = default;
@ -106,6 +111,7 @@ class categorizer_job {
virtual void categorize_random_access(std::span<uint8_t const> data) = 0; virtual void categorize_random_access(std::span<uint8_t const> data) = 0;
virtual void categorize_sequential(std::span<uint8_t const> data) = 0; virtual void categorize_sequential(std::span<uint8_t const> data) = 0;
virtual inode_fragments result() = 0; virtual inode_fragments result() = 0;
virtual bool has_multi_fragment_sequential_categorizers() const = 0;
}; };
private: private:

View File

@ -49,6 +49,7 @@ class categorizer_manager_private : public categorizer_manager::impl {
categorizers() const = 0; categorizers() const = 0;
virtual fragment_category::value_type virtual fragment_category::value_type
category(std::string_view cat) const = 0; category(std::string_view cat) const = 0;
virtual bool has_multi_fragment_sequential_categorizers() const = 0;
}; };
template <typename LoggerPolicy> template <typename LoggerPolicy>
@ -66,6 +67,7 @@ class categorizer_job_ final : public categorizer_job::impl {
void categorize_random_access(std::span<uint8_t const> data) override; void categorize_random_access(std::span<uint8_t const> data) override;
void categorize_sequential(std::span<uint8_t const> data) override; void categorize_sequential(std::span<uint8_t const> data) override;
inode_fragments result() override; inode_fragments result() override;
bool has_multi_fragment_sequential_categorizers() const override;
private: private:
LOG_PROXY_DECL(LoggerPolicy); LOG_PROXY_DECL(LoggerPolicy);
@ -158,6 +160,12 @@ inode_fragments categorizer_job_<LoggerPolicy>::result() {
return best_; return best_;
} }
template <typename LoggerPolicy>
bool categorizer_job_<
LoggerPolicy>::has_multi_fragment_sequential_categorizers() const {
return mgr_.has_multi_fragment_sequential_categorizers();
}
categorizer_job::categorizer_job() = default; categorizer_job::categorizer_job() = default;
categorizer_job::categorizer_job(std::unique_ptr<impl> impl) categorizer_job::categorizer_job(std::unique_ptr<impl> impl)
@ -188,6 +196,10 @@ class categorizer_manager_ final : public categorizer_manager_private {
return it->second; return it->second;
} }
bool has_multi_fragment_sequential_categorizers() const override {
return has_multi_fragment_sequential_categorizers_;
}
private: private:
void add_category(std::string_view cat) { void add_category(std::string_view cat) {
if (catmap_.emplace(cat, categories_.size()).second) { if (catmap_.emplace(cat, categories_.size()).second) {
@ -202,6 +214,7 @@ class categorizer_manager_ final : public categorizer_manager_private {
std::vector<std::shared_ptr<categorizer const>> categorizers_; std::vector<std::shared_ptr<categorizer const>> categorizers_;
std::vector<std::string_view> categories_; std::vector<std::string_view> categories_;
std::unordered_map<std::string_view, fragment_category::value_type> catmap_; std::unordered_map<std::string_view, fragment_category::value_type> catmap_;
bool has_multi_fragment_sequential_categorizers_{false};
}; };
template <typename LoggerPolicy> template <typename LoggerPolicy>
@ -211,6 +224,11 @@ void categorizer_manager_<LoggerPolicy>::add(
add_category(c); add_category(c);
} }
if (!c->is_single_fragment() &&
dynamic_cast<sequential_categorizer const*>(c.get())) {
has_multi_fragment_sequential_categorizers_ = true;
}
categorizers_.emplace_back(std::move(c)); categorizers_.emplace_back(std::move(c));
} }

View File

@ -62,6 +62,8 @@ class binary_categorizer_ final : public binary_categorizer_base {
categorize(std::filesystem::path const& path, std::span<uint8_t const> data, categorize(std::filesystem::path const& path, std::span<uint8_t const> data,
category_mapper const& mapper) const override; category_mapper const& mapper) const override;
bool is_single_fragment() const override { return false; }
private: private:
LOG_PROXY_DECL(LoggerPolicy); LOG_PROXY_DECL(LoggerPolicy);
}; };

View File

@ -156,6 +156,7 @@ class incompressible_categorizer_ final : public sequential_categorizer {
std::unique_ptr<sequential_categorizer_job> std::unique_ptr<sequential_categorizer_job>
job(std::filesystem::path const& path, size_t total_size, job(std::filesystem::path const& path, size_t total_size,
category_mapper const& mapper) const override; category_mapper const& mapper) const override;
bool is_single_fragment() const override { return true; }
private: private:
logger& lgr_; logger& lgr_;

View File

@ -147,6 +147,8 @@ class libmagic_categorizer_ final : public libmagic_categorizer_base {
categorize(std::filesystem::path const& path, std::span<uint8_t const> data, categorize(std::filesystem::path const& path, std::span<uint8_t const> data,
category_mapper const& mapper) const override; category_mapper const& mapper) const override;
bool is_single_fragment() const override { return true; }
private: private:
LOG_PROXY_DECL(LoggerPolicy); LOG_PROXY_DECL(LoggerPolicy);
magic_wrapper m_; magic_wrapper m_;

View File

@ -155,6 +155,10 @@ class inode_ : public inode {
if (mm) { if (mm) {
if (catjob) { if (catjob) {
DWARFS_CHECK(
!catjob.has_multi_fragment_sequential_categorizers(),
"multi-fragment sequential categorizers are not supported");
catjob.set_total_size(mm->size()); catjob.set_total_size(mm->size());
catjob.categorize_random_access(mm->span()); catjob.categorize_random_access(mm->span());
} }