BIND 10 trac2850_2, updated. 1fd14dfefcd2339d9dea25b30dc9204bd10548f4 [2850] Add corruption tests

BIND 10 source code commits bind10-changes at lists.isc.org
Mon May 6 08:24:56 UTC 2013


The branch, trac2850_2 has been updated
       via  1fd14dfefcd2339d9dea25b30dc9204bd10548f4 (commit)
       via  39fba2a15cb200dbe77ae3c9a4d894496f9eee66 (commit)
       via  557794895c01555c32906ad8422d5d6fbb878fe8 (commit)
       via  3af2603f0f08ad709590766051eea370c470642f (commit)
      from  03ce449ee10c5a8d8f60a68cb42839b9ae63ec00 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 1fd14dfefcd2339d9dea25b30dc9204bd10548f4
Author: Mukund Sivaraman <muks at isc.org>
Date:   Mon May 6 13:54:40 2013 +0530

    [2850] Add corruption tests

commit 39fba2a15cb200dbe77ae3c9a4d894496f9eee66
Author: Mukund Sivaraman <muks at isc.org>
Date:   Mon May 6 13:54:22 2013 +0530

    [2850] Add a sync() method and make reset() and the destructor call it
    
    This is so that checksums and such are synchronized.

commit 557794895c01555c32906ad8422d5d6fbb878fe8
Author: Mukund Sivaraman <muks at isc.org>
Date:   Mon May 6 13:53:09 2013 +0530

    [2850] Unify code

commit 3af2603f0f08ad709590766051eea370c470642f
Author: Mukund Sivaraman <muks at isc.org>
Date:   Mon May 6 13:52:52 2013 +0530

    [2850] Fix type of checksum

-----------------------------------------------------------------------

Summary of changes:
 .../datasrc/memory/zone_table_segment_mapped.cc    |   72 ++++++-------
 src/lib/datasrc/memory/zone_table_segment_mapped.h |    5 +
 .../memory/zone_table_segment_mapped_unittest.cc   |  107 +++++++++++++++++++-
 3 files changed, 147 insertions(+), 37 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/datasrc/memory/zone_table_segment_mapped.cc b/src/lib/datasrc/memory/zone_table_segment_mapped.cc
index ccd172e..d7ef8e2 100644
--- a/src/lib/datasrc/memory/zone_table_segment_mapped.cc
+++ b/src/lib/datasrc/memory/zone_table_segment_mapped.cc
@@ -41,6 +41,10 @@ ZoneTableSegmentMapped::ZoneTableSegmentMapped(const RRClass& rrclass) :
 {
 }
 
+ZoneTableSegmentMapped::~ZoneTableSegmentMapped() {
+    sync();
+}
+
 bool
 ZoneTableSegmentMapped::processChecksum(MemorySegmentMapped& segment,
                                         bool create,
@@ -58,12 +62,12 @@ ZoneTableSegmentMapped::processChecksum(MemorySegmentMapped& segment,
             // The segment was already shrunk when it was last
             // closed. Check that its checksum is consistent.
             assert(result.second);
-            uint32_t* checksum = static_cast<uint32_t*>(result.second);
-            const uint32_t saved_checksum = *checksum;
+            size_t* checksum = static_cast<size_t*>(result.second);
+            const size_t saved_checksum = *checksum;
             // First, clear the checksum so that getCheckSum() returns a
             // consistent value.
             *checksum = 0;
-            const uint32_t new_checksum = segment.getCheckSum();
+            const size_t new_checksum = segment.getCheckSum();
             if (saved_checksum != new_checksum) {
                 error_msg = "Saved checksum doesn't match segment data";
                 return (false);
@@ -79,12 +83,12 @@ ZoneTableSegmentMapped::processChecksum(MemorySegmentMapped& segment,
         void* checksum = NULL;
         while (!checksum) {
             try {
-                checksum = segment.allocate(sizeof(uint32_t));
+                checksum = segment.allocate(sizeof(size_t));
             } catch (const MemorySegmentGrown&) {
                 // Do nothing and try again.
             }
         }
-        *static_cast<uint32_t*>(checksum) = 0;
+        *static_cast<size_t*>(checksum) = 0;
         const bool grew = segment.setNamedAddress(ZONE_TABLE_CHECKSUM_NAME,
                                                   checksum);
         if (grew) {
@@ -165,19 +169,8 @@ ZoneTableSegmentMapped::openReadWrite(const std::string& filename,
         (new MemorySegmentMapped(filename, mode));
 
     std::string error_msg;
-    if (!processChecksum(*segment, create, error_msg)) {
-         if (mem_sgmt_) {
-              isc_throw(ResetFailed,
-                        "Error in resetting zone table segment to use "
-                        << filename << ": " << error_msg);
-         } else {
-              isc_throw(ResetFailedAndSegmentCleared,
-                        "Error in resetting zone table segment to use "
-                        << filename << ": " << error_msg);
-         }
-    }
-
-    if (!processHeader(*segment, create, error_msg)) {
+    if ((!processChecksum(*segment, create, error_msg)) ||
+        (!processHeader(*segment, create, error_msg))) {
          if (mem_sgmt_) {
               isc_throw(ResetFailed,
                         "Error in resetting zone table segment to use "
@@ -270,6 +263,8 @@ ZoneTableSegmentMapped::reset(MemorySegmentOpenMode mode,
         // mapped file. We cannot do this in many mode combinations
         // unless we close the existing mapped file. So just close it.
         clear();
+    } else {
+        sync();
     }
 
     switch (mode) {
@@ -290,27 +285,32 @@ ZoneTableSegmentMapped::reset(MemorySegmentOpenMode mode,
 }
 
 void
+ZoneTableSegmentMapped::sync()
+{
+    // Synchronize checksum, etc.
+    if (mem_sgmt_ && isWritable()) {
+        // If there is a previously opened segment, and it was opened in
+        // read-write mode, update its checksum.
+        mem_sgmt_->shrinkToFit();
+        const MemorySegment::NamedAddressResult result =
+            mem_sgmt_->getNamedAddress(ZONE_TABLE_CHECKSUM_NAME);
+        assert(result.first);
+        assert(result.second);
+        size_t* checksum = static_cast<size_t*>(result.second);
+        // First, clear the checksum so that getCheckSum() returns a
+        // consistent value.
+        *checksum = 0;
+        const size_t new_checksum = mem_sgmt_->getCheckSum();
+        // Now, update it into place.
+        *checksum = new_checksum;
+    }
+}
+
+void
 ZoneTableSegmentMapped::clear()
 {
     if (mem_sgmt_) {
-        if (isWritable()) {
-            // If there is a previously opened segment, and it was
-            // opened in read-write mode, update its checksum.
-            mem_sgmt_->shrinkToFit();
-            const MemorySegment::NamedAddressResult result =
-                mem_sgmt_->getNamedAddress(ZONE_TABLE_CHECKSUM_NAME);
-            assert(result.first);
-            assert(result.second);
-            uint32_t* checksum = static_cast<uint32_t*>(result.second);
-            // First, clear the checksum so that getCheckSum() returns
-            // a consistent value.
-            *checksum = 0;
-            const uint32_t new_checksum = mem_sgmt_->getCheckSum();
-            // Now, update it into place.
-            *checksum = new_checksum;
-        }
-        // Close the segment here in case the code further below
-        // doesn't complete successfully.
+        sync();
         header_ = NULL;
         mem_sgmt_.reset();
     }
diff --git a/src/lib/datasrc/memory/zone_table_segment_mapped.h b/src/lib/datasrc/memory/zone_table_segment_mapped.h
index 2206630..208070c 100644
--- a/src/lib/datasrc/memory/zone_table_segment_mapped.h
+++ b/src/lib/datasrc/memory/zone_table_segment_mapped.h
@@ -43,6 +43,9 @@ protected:
     ZoneTableSegmentMapped(const isc::dns::RRClass& rrclass);
 
 public:
+    /// \brief Destructor
+    virtual ~ZoneTableSegmentMapped();
+
     /// \brief Return the ZoneTableHeader for the mapped zone table
     /// segment implementation.
     ///
@@ -105,6 +108,8 @@ public:
     virtual void clear();
 
 private:
+    void sync();
+
     bool processChecksum(isc::util::MemorySegmentMapped& segment, bool create,
                          std::string& error_msg);
     bool processHeader(isc::util::MemorySegmentMapped& segment, bool create,
diff --git a/src/lib/datasrc/tests/memory/zone_table_segment_mapped_unittest.cc b/src/lib/datasrc/tests/memory/zone_table_segment_mapped_unittest.cc
index a4a6565..198a2f6 100644
--- a/src/lib/datasrc/tests/memory/zone_table_segment_mapped_unittest.cc
+++ b/src/lib/datasrc/tests/memory/zone_table_segment_mapped_unittest.cc
@@ -34,6 +34,7 @@ using boost::scoped_ptr;
 namespace {
 
 const char* mapped_file = TEST_DATA_BUILDDIR "/test.mapped";
+const char* mapped_file2 = TEST_DATA_BUILDDIR "/test2.mapped";
 
 class ZoneTableSegmentMappedTest : public ::testing::Test {
 protected:
@@ -42,7 +43,10 @@ protected:
             ZoneTableSegment::create(RRClass::IN(), "mapped")),
         config_params_(
             Element::fromJSON(
-                "{\"mapped-file\": \"" + std::string(mapped_file) + "\"}"))
+                "{\"mapped-file\": \"" + std::string(mapped_file) + "\"}")),
+        config_params2_(
+            Element::fromJSON(
+                "{\"mapped-file\": \"" + std::string(mapped_file2) + "\"}"))
     {
         EXPECT_NE(static_cast<void*>(NULL), ztable_segment_);
         // Verify that a ZoneTableSegmentMapped is created.
@@ -54,10 +58,14 @@ protected:
     ~ZoneTableSegmentMappedTest() {
         ZoneTableSegment::destroy(ztable_segment_);
         boost::interprocess::file_mapping::remove(mapped_file);
+        boost::interprocess::file_mapping::remove(mapped_file2);
     }
 
+    void setupMappedFiles();
+
     ZoneTableSegment* ztable_segment_;
     const ConstElementPtr config_params_;
+    const ConstElementPtr config_params2_;
 };
 
 bool
@@ -109,6 +117,40 @@ verifyData(const MemorySegment& segment) {
     return (true);
 }
 
+void
+deleteChecksum(MemorySegment& segment) {
+    segment.clearNamedAddress("zone_table_checksum");
+}
+
+void
+corruptChecksum(MemorySegment& segment) {
+    const MemorySegment::NamedAddressResult result =
+        segment.getNamedAddress("zone_table_checksum");
+    ASSERT_TRUE(result.first);
+
+    size_t checksum = *static_cast<size_t*>(result.second);
+    checksum ^= 0x55555555;
+    *static_cast<size_t*>(result.second) = checksum;
+}
+
+void
+deleteHeader(MemorySegment& segment) {
+    segment.clearNamedAddress("zone_table_header");
+}
+
+void
+ZoneTableSegmentMappedTest::setupMappedFiles() {
+    ztable_segment_->reset(ZoneTableSegment::CREATE, config_params_);
+    createData(ztable_segment_->getMemorySegment());
+    EXPECT_TRUE(verifyData(ztable_segment_->getMemorySegment()));
+
+    ztable_segment_->reset(ZoneTableSegment::CREATE, config_params2_);
+    createData(ztable_segment_->getMemorySegment());
+    EXPECT_TRUE(verifyData(ztable_segment_->getMemorySegment()));
+
+    // Now, clear the segment, closing the underlying mapped file.
+    ztable_segment_->clear();
+}
 
 TEST_F(ZoneTableSegmentMappedTest, getHeaderUninitialized) {
     // This should throw as we haven't called reset() yet.
@@ -341,4 +383,67 @@ TEST_F(ZoneTableSegmentMappedTest, clear) {
     EXPECT_THROW(ztable_segment_->getMemorySegment(), isc::InvalidOperation);
 }
 
+TEST_F(ZoneTableSegmentMappedTest, resetFailedCorruptedChecksum) {
+    setupMappedFiles();
+
+    // Open mapped file 1 in read-write mode
+    ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
+
+    // Corrupt mapped file 2.
+    scoped_ptr<MemorySegmentMapped> segment
+        (new MemorySegmentMapped(mapped_file2,
+                                 MemorySegmentMapped::OPEN_OR_CREATE));
+    EXPECT_TRUE(verifyData(*segment));
+    corruptChecksum(*segment);
+    segment.reset();
+
+    // Opening mapped file 2 in read-write mode should fail
+    EXPECT_THROW({
+        ztable_segment_->reset(ZoneTableSegment::READ_WRITE,
+                               config_params2_);
+    }, ResetFailed);
+}
+
+TEST_F(ZoneTableSegmentMappedTest, resetFailedMissingChecksum) {
+    setupMappedFiles();
+
+    // Open mapped file 1 in read-write mode
+    ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
+
+    // Corrupt mapped file 2.
+    scoped_ptr<MemorySegmentMapped> segment
+        (new MemorySegmentMapped(mapped_file2,
+                                 MemorySegmentMapped::OPEN_OR_CREATE));
+    EXPECT_TRUE(verifyData(*segment));
+    deleteChecksum(*segment);
+    segment.reset();
+
+    // Opening mapped file 2 in read-only mode should fail
+    EXPECT_THROW({
+        ztable_segment_->reset(ZoneTableSegment::READ_ONLY,
+                               config_params2_);
+    }, ResetFailed);
+}
+
+TEST_F(ZoneTableSegmentMappedTest, resetFailedMissingHeader) {
+    setupMappedFiles();
+
+    // Open mapped file 1 in read-write mode
+    ztable_segment_->reset(ZoneTableSegment::READ_WRITE, config_params_);
+
+    // Corrupt mapped file 2.
+    scoped_ptr<MemorySegmentMapped> segment
+        (new MemorySegmentMapped(mapped_file2,
+                                 MemorySegmentMapped::OPEN_OR_CREATE));
+    EXPECT_TRUE(verifyData(*segment));
+    deleteHeader(*segment);
+    segment.reset();
+
+    // Opening mapped file 2 in read-only mode should fail
+    EXPECT_THROW({
+        ztable_segment_->reset(ZoneTableSegment::READ_ONLY,
+                               config_params2_);
+    }, ResetFailed);
+}
+
 } // anonymous namespace



More information about the bind10-changes mailing list