Moar checks

This commit is contained in:
Marcus Holland-Moritz 2021-03-31 08:21:41 +02:00
parent 69fc251cd6
commit 9112f1f7ac
2 changed files with 75 additions and 0 deletions

View File

@ -136,6 +136,26 @@ void check_index_range(global_metadata::Meta const* meta) {
auto num_inodes = meta->inodes().size(); auto num_inodes = meta->inodes().size();
bool v2_2 = !static_cast<bool>(meta->dir_entries()); bool v2_2 = !static_cast<bool>(meta->dir_entries());
if (num_modes >= std::numeric_limits<uint16_t>::max()) {
DWARFS_THROW(runtime_error, "invalid number of modes");
}
if (num_uids >= std::numeric_limits<uint16_t>::max()) {
DWARFS_THROW(runtime_error, "invalid number of uids");
}
if (num_gids >= std::numeric_limits<uint16_t>::max()) {
DWARFS_THROW(runtime_error, "invalid number of gids");
}
if (num_names >= std::numeric_limits<uint32_t>::max()) {
DWARFS_THROW(runtime_error, "invalid number of names");
}
if (num_inodes >= std::numeric_limits<uint32_t>::max()) {
DWARFS_THROW(runtime_error, "invalid number of inodes");
}
for (auto ino : meta->inodes()) { for (auto ino : meta->inodes()) {
if (ino.mode_index() >= num_modes) { if (ino.mode_index() >= num_modes) {
DWARFS_THROW(runtime_error, "mode_index out of range"); DWARFS_THROW(runtime_error, "mode_index out of range");
@ -154,6 +174,10 @@ void check_index_range(global_metadata::Meta const* meta) {
} }
if (auto dep = meta->dir_entries()) { if (auto dep = meta->dir_entries()) {
if (dep->size() >= std::numeric_limits<uint32_t>::max()) {
DWARFS_THROW(runtime_error, "invalid number of dir_entries");
}
if (auto cn = meta->compact_names()) { if (auto cn = meta->compact_names()) {
num_names = cn->index().size(); num_names = cn->index().size();
if (!cn->packed_index()) { if (!cn->packed_index()) {
@ -173,6 +197,11 @@ void check_index_range(global_metadata::Meta const* meta) {
} }
} }
} else { } else {
if (meta->entry_table_v2_2().size() >=
std::numeric_limits<uint32_t>::max()) {
DWARFS_THROW(runtime_error, "invalid number of entries");
}
for (auto ent : meta->entry_table_v2_2()) { for (auto ent : meta->entry_table_v2_2()) {
if (ent >= num_inodes) { if (ent >= num_inodes) {
DWARFS_THROW(runtime_error, "entry_table_v2_2 value out of range"); DWARFS_THROW(runtime_error, "entry_table_v2_2 value out of range");
@ -182,6 +211,14 @@ void check_index_range(global_metadata::Meta const* meta) {
} }
void check_packed_tables(global_metadata::Meta const* meta) { void check_packed_tables(global_metadata::Meta const* meta) {
if (meta->directories().size() >= std::numeric_limits<uint32_t>::max()) {
DWARFS_THROW(runtime_error, "invalid number of directories");
}
if (meta->chunk_table().size() >= std::numeric_limits<uint32_t>::max()) {
DWARFS_THROW(runtime_error, "invalid number of chunk_table entries");
}
if (auto opt = meta->options(); opt and opt->packed_directories()) { if (auto opt = meta->options(); opt and opt->packed_directories()) {
if (std::any_of(meta->directories().begin(), meta->directories().end(), if (std::any_of(meta->directories().begin(), meta->directories().end(),
[](auto i) { return i.parent_entry() != 0; })) { [](auto i) { return i.parent_entry() != 0; })) {
@ -229,6 +266,10 @@ void check_chunks(global_metadata::Meta const* meta) {
DWARFS_THROW(runtime_error, "invalid block size"); DWARFS_THROW(runtime_error, "invalid block size");
} }
if (meta->chunks().size() >= std::numeric_limits<uint32_t>::max()) {
DWARFS_THROW(runtime_error, "invalid number of chunks");
}
for (auto c : meta->chunks()) { for (auto c : meta->chunks()) {
if (c.offset() >= block_size || c.size() > block_size) { if (c.offset() >= block_size || c.size() > block_size) {
DWARFS_THROW(runtime_error, "chunk offset/size out of range"); DWARFS_THROW(runtime_error, "chunk offset/size out of range");

View File

@ -57,6 +57,8 @@
#include "dwarfs/gen-cpp2/metadata_layouts.h" #include "dwarfs/gen-cpp2/metadata_layouts.h"
#include "dwarfs/gen-cpp2/metadata_types_custom_protocol.h" #include "dwarfs/gen-cpp2/metadata_types_custom_protocol.h"
#include "thrift/lib/thrift/gen-cpp2/frozen_types_custom_protocol.h"
namespace dwarfs { namespace dwarfs {
namespace { namespace {
@ -89,9 +91,41 @@ freeze_to_buffer(const T& x) {
return {schema_buffer, data_buffer}; return {schema_buffer, data_buffer};
} }
void check_schema(folly::ByteRange data) {
using namespace ::apache::thrift;
frozen::schema::Schema schema;
size_t schemaSize = CompactSerializer::deserialize(data, schema);
// std::cerr << debugString(schema) << '\n';
if (schemaSize != data.size()) {
DWARFS_THROW(runtime_error, "invalid schema size");
}
if (schema.layouts_ref()->count(*schema.rootLayout_ref()) == 0) {
DWARFS_THROW(runtime_error, "invalid rootLayout in schema");
}
for (auto const& kvl : *schema.layouts_ref()) {
auto const& layout = kvl.second;
if (kvl.first >= static_cast<int64_t>(schema.layouts_ref()->size())) {
DWARFS_THROW(runtime_error, "invalid layout key in schema");
}
if (*layout.size_ref() < 0) {
DWARFS_THROW(runtime_error, "negative size in schema");
}
if (*layout.bits_ref() < 0) {
DWARFS_THROW(runtime_error, "negative bits in schema");
}
for (auto const& kvf : *layout.fields_ref()) {
auto const& field = kvf.second;
if (schema.layouts_ref()->count(*field.layoutId_ref()) == 0) {
DWARFS_THROW(runtime_error, "invalid layoutId in field");
}
}
}
}
template <typename T> template <typename T>
MappedFrozen<T> map_frozen(folly::ByteRange schema, folly::ByteRange data) { MappedFrozen<T> map_frozen(folly::ByteRange schema, folly::ByteRange data) {
using namespace ::apache::thrift::frozen; using namespace ::apache::thrift::frozen;
check_schema(schema);
auto layout = std::make_unique<Layout<T>>(); auto layout = std::make_unique<Layout<T>>();
deserializeRootLayout(schema, *layout); deserializeRootLayout(schema, *layout);
MappedFrozen<T> ret(layout->view({data.begin(), 0})); MappedFrozen<T> ret(layout->view({data.begin(), 0}));