Commit e21efca5 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[2107] make NSEC3Data::create() exception safe.

parent 042e6179
......@@ -40,6 +40,43 @@ using namespace isc::testutils;
namespace {
class NSEC3DataTest : public ::testing::Test {
protected:
NSEC3DataTest() : param_rdata_("1 0 12 aabbccdd")
{}
void TearDown() {
// detect any memory leak in the test memory segment
EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated());
}
MemorySegmentTest mem_sgmt_;
NSEC3Data* nsec3_data_;
const generic::NSEC3PARAM param_rdata_;
};
TEST_F(NSEC3DataTest, create) {
nsec3_data_ = NSEC3Data::create(mem_sgmt_, param_rdata_);
EXPECT_EQ(0, nsec3_data_->getNSEC3Tree()->getNodeCount());
EXPECT_EQ(1, nsec3_data_->hashalg);
EXPECT_EQ(0, nsec3_data_->flags);
EXPECT_EQ(12, nsec3_data_->iterations);
EXPECT_EQ(param_rdata_.getSalt().size(), nsec3_data_->getSaltLen());
EXPECT_EQ(0, memcmp(&param_rdata_.getSalt()[0], nsec3_data_->getSaltData(),
param_rdata_.getSalt().size()));
NSEC3Data::destroy(mem_sgmt_, nsec3_data_, RRClass::IN());
}
TEST_F(NSEC3DataTest, throwOnCreate) {
// Note: below, we use our knowledge of how memory allocation happens
// within the NSEC3Data.
// Creating internal NSEC3 tree will succeed, but allocation of NSEC3Data
// will fail due to bad_alloc. It shouldn't cause memory leak
// (that would be caught in TearDown()).
mem_sgmt_.setThrowCount(2);
EXPECT_THROW(NSEC3Data::create(mem_sgmt_, param_rdata_), std::bad_alloc);
}
class ZoneDataTest : public ::testing::Test {
protected:
ZoneDataTest() : zname_("example.com"),
......@@ -105,30 +142,4 @@ TEST_F(ZoneDataTest, addRdataSets) {
// TearDown() will confirm there's no leak on destroy
}
class NSEC3DataTest : public ::testing::Test {
protected:
NSEC3DataTest() : param_rdata_("1 0 12 aabbccdd")
{}
void TearDown() {
// detect any memory leak in the test memory segment
EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated());
}
MemorySegmentTest mem_sgmt_;
NSEC3Data* nsec3_data_;
const generic::NSEC3PARAM param_rdata_;
};
TEST_F(NSEC3DataTest, create) {
nsec3_data_ = NSEC3Data::create(mem_sgmt_, param_rdata_);
EXPECT_EQ(0, nsec3_data_->getNSEC3Tree()->getNodeCount());
EXPECT_EQ(1, nsec3_data_->hashalg);
EXPECT_EQ(0, nsec3_data_->flags);
EXPECT_EQ(12, nsec3_data_->iterations);
EXPECT_EQ(param_rdata_.getSalt().size(), nsec3_data_->getSaltLen());
EXPECT_EQ(0, memcmp(&param_rdata_.getSalt()[0], nsec3_data_->getSaltData(),
param_rdata_.getSalt().size()));
NSEC3Data::destroy(mem_sgmt_, nsec3_data_, RRClass::IN());
}
}
......@@ -58,14 +58,21 @@ NSEC3Data*
NSEC3Data::create(util::MemorySegment& mem_sgmt,
const generic::NSEC3PARAM& rdata)
{
ZoneTree* tree = ZoneTree::create(mem_sgmt, true);
// NSEC3Data allocation can throw. To avoid leaking the tree, we manage
// it in the holder.
// Note: we won't add any RdataSet, so we use the NO-OP deleter
// (with an assertion check for that).
typedef boost::function<void(RdataSet*)> RdataSetDeleterType;
detail::SegmentObjectHolder<ZoneTree, RdataSetDeleterType> holder(
mem_sgmt, ZoneTree::create(mem_sgmt, true),
boost::bind(nullDeleter, _1));
const size_t salt_len = rdata.getSalt().size();
void* p = mem_sgmt.allocate(sizeof(NSEC3Data) + salt_len + 1);
NSEC3Data* const param_data =
new(p) NSEC3Data(tree, rdata.getHashalg(), rdata.getFlags(),
rdata.getIterations());
new(p) NSEC3Data(holder.release(), rdata.getHashalg(),
rdata.getFlags(), rdata.getIterations());
uint8_t* dp = param_data->getSaltBuf();
*dp++ = salt_len;
memcpy(dp, &rdata.getSalt().at(0), salt_len); // use at for safety
......@@ -86,10 +93,8 @@ NSEC3Data::destroy(util::MemorySegment& mem_sgmt, NSEC3Data* data,
ZoneData*
ZoneData::create(util::MemorySegment& mem_sgmt, const Name& zone_origin) {
// ZoneTree::insert() and ZoneData allocation can throw. To avoid
// leaking the tree, we manage it in the holder.
// Note: we won't add any RdataSet, so we use the NO-OP deleter
// (with an assertion check for that).
// ZoneTree::insert() and ZoneData allocation can throw. See also
// NSEC3Data::create().
typedef boost::function<void(RdataSet*)> RdataSetDeleterType;
detail::SegmentObjectHolder<ZoneTree, RdataSetDeleterType> holder(
mem_sgmt, ZoneTree::create(mem_sgmt, true),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment