Browse Source

[1332] handle bad data from data source. it revealed a bug in the mock
accessor, which was fixed, too.

JINMEI Tatuya 13 years ago
parent
commit
dabf62d544
2 changed files with 57 additions and 8 deletions
  1. 13 6
      src/lib/datasrc/database.cc
  2. 44 2
      src/lib/datasrc/tests/database_unittest.cc

+ 13 - 6
src/lib/datasrc/database.cc

@@ -1121,12 +1121,19 @@ public:
             return (ConstRRsetPtr());
         }
 
-        RRsetPtr rrset(new RRset(Name(data[Accessor::NAME_COLUMN]), rrclass_,
-                                 RRType(data[Accessor::TYPE_COLUMN]),
-                                 RRTTL(data[Accessor::TTL_COLUMN])));
-        rrset->addRdata(rdata::createRdata(rrset->getType(), rrclass_,
-                                           data[Accessor::RDATA_COLUMN]));
-        return (rrset);
+        try {
+            RRsetPtr rrset(new RRset(Name(data[Accessor::NAME_COLUMN]),
+                                     rrclass_,
+                                     RRType(data[Accessor::TYPE_COLUMN]),
+                                     RRTTL(data[Accessor::TTL_COLUMN])));
+            rrset->addRdata(rdata::createRdata(rrset->getType(), rrclass_,
+                                               data[Accessor::RDATA_COLUMN]));
+            return (rrset);
+        } catch (const Exception& ex) {
+            // TBD: log it.
+            isc_throw(DataSourceError, "Failed to create RRset from diff on "
+                      << accessor_->getDBName());
+        }
     }
 
 private:

+ 44 - 2
src/lib/datasrc/tests/database_unittest.cc

@@ -755,7 +755,7 @@ public:
             isc_throw(DataSourceError, "Test error");
         } else {
             journal_entries_->push_back(JournalEntry(id, serial, operation,
-                                                    data));
+                                                     data));
         }
     }
 
@@ -783,10 +783,10 @@ public:
             if ((*it).serial_ < start && selected_jnl.empty()) {
                 continue;
             }
-            selected_jnl.push_back(*it);
             if ((*it).serial_ > end) { // gone over the end serial. we're done.
                 break;
             }
+            selected_jnl.push_back(*it);
         }
 
         // Check if we've found the requested range.  If not, throw.
@@ -3174,4 +3174,46 @@ TYPED_TEST(DatabaseClientTest, journalReaderForNXZone) {
     EXPECT_FALSE(result.second);
 }
 
+// A helper function for journalWithBadData.  It installs a simple diff
+// from one serial (of 'begin') to another ('begin' + 1), tweaking a specified
+// field of data with some invalid value.
+void
+installBadDiff(MockAccessor& accessor, uint32_t begin,
+               DatabaseAccessor::DiffRecordParams modify_param,
+               const char* const data)
+{
+    string data1[] = {"example.org.", "SOA", "3600", "ns. root. 1 1 1 1 1"};
+    string data2[] = {"example.org.", "SOA", "3600", "ns. root. 2 1 1 1 1"};
+    data1[modify_param] = data;
+    accessor.addRecordDiff(READONLY_ZONE_ID, begin,
+                           DatabaseAccessor::DIFF_DELETE, data1);
+    accessor.addRecordDiff(READONLY_ZONE_ID, begin + 1,
+                           DatabaseAccessor::DIFF_ADD, data2);
+}
+
+TEST_F(MockDatabaseClientTest, journalWithBadData) {
+    MockAccessor& mock_accessor =
+        dynamic_cast<MockAccessor&>(*current_accessor_);
+
+    // One of the fields from the data source is broken as an RR parameter.
+    // The journal reader should still be constructed, but getNextDiff()
+    // should result in exception.
+    installBadDiff(mock_accessor, 1, DatabaseAccessor::DIFF_NAME,
+                   "example..org");
+    installBadDiff(mock_accessor, 3, DatabaseAccessor::DIFF_TYPE,
+                   "bad-rrtype");
+    installBadDiff(mock_accessor, 5, DatabaseAccessor::DIFF_TTL,
+                   "bad-ttl");
+    installBadDiff(mock_accessor, 7, DatabaseAccessor::DIFF_RDATA,
+                   "bad rdata");
+    EXPECT_THROW(this->client_->getJournalReader(this->zname_, 1, 2).
+                 second->getNextDiff(), DataSourceError);
+    EXPECT_THROW(this->client_->getJournalReader(this->zname_, 3, 4).
+                 second->getNextDiff(), DataSourceError);
+    EXPECT_THROW(this->client_->getJournalReader(this->zname_, 5, 6).
+                 second->getNextDiff(), DataSourceError);
+    EXPECT_THROW(this->client_->getJournalReader(this->zname_, 7, 8).
+                 second->getNextDiff(), DataSourceError);
+}
+
 }