From 48e7ab89a56998ed63f24549d4fc7fc1289ad508 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Thu, 21 Sep 2017 10:22:38 +0100 Subject: [PATCH] [*_dump] Fix segfault when given a tiny metadata file --- caching/metadata.cc | 6 +++++- era/metadata.cc | 6 +++++- functional-tests/cache-functional-tests.scm | 5 +++++ functional-tests/era-functional-tests.scm | 8 ++++++++ functional-tests/thin-functional-tests.scm | 9 +++++++++ thin-provisioning/metadata.cc | 6 +++++- 6 files changed, 37 insertions(+), 3 deletions(-) diff --git a/caching/metadata.cc b/caching/metadata.cc index 7d8bfae..91806f4 100644 --- a/caching/metadata.cc +++ b/caching/metadata.cc @@ -13,7 +13,11 @@ namespace { // FIXME: duplication transaction_manager::ptr open_tm(block_manager<>::ptr bm) { - space_map::ptr sm(new core_map(bm->get_nr_blocks())); + auto nr_blocks = bm->get_nr_blocks(); + if (!nr_blocks) + throw runtime_error("Metadata is not large enough for superblock."); + + space_map::ptr sm(new core_map(nr_blocks)); sm->inc(SUPERBLOCK_LOCATION); transaction_manager::ptr tm(new transaction_manager(bm, sm)); return tm; diff --git a/era/metadata.cc b/era/metadata.cc index dd4fe7a..40861b1 100644 --- a/era/metadata.cc +++ b/era/metadata.cc @@ -11,7 +11,11 @@ namespace { // FIXME: duplication transaction_manager::ptr open_tm(block_manager<>::ptr bm) { - space_map::ptr sm(new core_map(bm->get_nr_blocks())); + auto nr_blocks = bm->get_nr_blocks(); + if (!nr_blocks) + throw runtime_error("Metadata is not large enough for superblock."); + + space_map::ptr sm(new core_map(nr_blocks)); sm->inc(SUPERBLOCK_LOCATION); transaction_manager::ptr tm(new transaction_manager(bm, sm)); return tm; diff --git a/functional-tests/cache-functional-tests.scm b/functional-tests/cache-functional-tests.scm index eabca3d..4084c11 100644 --- a/functional-tests/cache-functional-tests.scm +++ b/functional-tests/cache-functional-tests.scm @@ -245,6 +245,11 @@ (receive (stdout stderr) (run-fail "cache_dump") (assert-starts-with "No input file provided." stderr))) + (define-scenario (cache-dump small-input-file) + "Fails with small input file" + (with-temp-file-sized ((md "cache.bin" 512)) + (run-fail "cache_dump" md))) + (define-scenario (cache-dump restore-is-noop) "cache_dump followed by cache_restore is a noop." (with-valid-metadata (md) diff --git a/functional-tests/era-functional-tests.scm b/functional-tests/era-functional-tests.scm index d381cea..bf124ad 100644 --- a/functional-tests/era-functional-tests.scm +++ b/functional-tests/era-functional-tests.scm @@ -180,6 +180,14 @@ (assert-eof stdout) (assert-starts-with "Couldn't stat file" stderr))))) + ;;;----------------------------------------------------------- + ;;; era_dump scenarios + ;;;----------------------------------------------------------- + (define-scenario (era-dump small-input-file) + "Fails with small input file" + (with-temp-file-sized ((md "era.bin" 512)) + (run-fail "era_dump" md))) + (define-scenario (era-dump restore-is-noop) "era_dump followed by era_restore is a noop." (with-valid-metadata (md) diff --git a/functional-tests/thin-functional-tests.scm b/functional-tests/thin-functional-tests.scm index a2991d6..eb96d51 100644 --- a/functional-tests/thin-functional-tests.scm +++ b/functional-tests/thin-functional-tests.scm @@ -187,6 +187,15 @@ (receive (stdout _) (thin-restore "-i" xml "-o" md "--quiet") (assert-eof stdout))))) + ;;;----------------------------------------------------------- + ;;; thin_dump scenarios + ;;;----------------------------------------------------------- + + (define-scenario (thin-dump small-input-file) + "Fails with small input file" + (with-temp-file-sized ((md "thin.bin" 512)) + (run-fail "thin_dump" md))) + (define-scenario (thin-dump restore-is-noop) "thin_dump followed by thin_restore is a noop." (with-valid-metadata (md) diff --git a/thin-provisioning/metadata.cc b/thin-provisioning/metadata.cc index 77e0428..ac8b63e 100644 --- a/thin-provisioning/metadata.cc +++ b/thin-provisioning/metadata.cc @@ -42,7 +42,11 @@ namespace { transaction_manager::ptr open_tm(block_manager<>::ptr bm) { - space_map::ptr sm(new core_map(bm->get_nr_blocks())); + auto nr_blocks = bm->get_nr_blocks(); + if (!nr_blocks) + throw runtime_error("Metadata is not large enough for superblock."); + + space_map::ptr sm(new core_map(nr_blocks)); sm->inc(SUPERBLOCK_LOCATION); transaction_manager::ptr tm(new transaction_manager(bm, sm)); return tm;