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

[1667] added workaround support for end-of-line comments in masterLoad().

parent 18eda222
......@@ -37,6 +37,30 @@ using namespace isc::dns::rdata;
namespace isc {
namespace dns {
namespace {
// A helper function that strips off any comment placed at the end of an RR.
// This is an incomplete implementation, and cannot handle all such comments;
// it's considered a short term workaround to deal with some real world
// cases.
string
stripComment(string& s, const Exception& ex) {
// Find any ';' in the text data, and locate the position of the last
// occurrence. Note that unless/until we support empty RDATA it
// shouldn't be placed at the beginning of the data.
const size_t pos_semicolon = s.rfind(';');
if (pos_semicolon == string::npos || pos_semicolon == 0) {
throw ex;
}
// Remove any trailing space and comments and return the resulting text.
const size_t pos_end_data = s.find_last_not_of(" /t", pos_semicolon - 1);
if (pos_end_data != string::npos) {
s.erase(pos_end_data + 1);
return (s);
}
throw ex;
}
}
void
masterLoad(const char* const filename, const Name& origin,
const RRClass& zone_class, MasterLoadCallback callback)
......@@ -116,7 +140,16 @@ masterLoad(istream& input, const Name& origin, const RRClass& zone_class,
ttl.reset(new RRTTL(ttl_txt));
rrclass.reset(new RRClass(rrclass_txt));
rrtype.reset(new RRType(rrtype_txt));
rdata = createRdata(*rrtype, *rrclass, rdatabuf.str());
string rdtext = rdatabuf.str();
try {
rdata = createRdata(*rrtype, *rrclass, rdtext);
} catch (const Exception& ex) {
// If the parse for the RDATA fails, check if it has comments
// at the end, and if so, retry the conversion after stripping
// off the comment.
rdata = createRdata(*rrtype, *rrclass, stripComment(rdtext,
ex));
}
} catch (const Exception& ex) {
isc_throw(MasterLoadError, "Invalid RR text at line " << line_count
<< ": " << ex.what());
......
......@@ -25,6 +25,7 @@
#include <dns/masterload.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rrclass.h>
#include <dns/rrset.h>
......@@ -80,6 +81,11 @@ const char* const rrsig_rr2 =
"www.example.com. 60 IN RRSIG AAAA 5 3 3600 20000101000000 20000201000000 "
"12345 example.com. FAKEFAKEFAKE\n";
// Commonly used for some tests to check the constructed RR content.
const char* const dnskey_rdata =
"256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH "
"zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE=\n";
TEST_F(MasterLoadTest, loadRRs) {
// a simple case: loading 3 RRs, each consists of a single RRset.
rr_stream << txt_rr << a_rr1 << soa_rr;
......@@ -161,6 +167,50 @@ TEST_F(MasterLoadTest, loadRRsigs) {
EXPECT_EQ(2, results.size());
}
TEST_F(MasterLoadTest, loadRRWithComment) {
// Comment at the end of line should be ignored and the RR should be
// accepted.
rr_stream << "example.com. 3600 IN DNSKEY 256 3 7 "
"AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH "
"zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE= ; key id = 40430\n";
masterLoad(rr_stream, origin, zclass, callback);
ASSERT_EQ(1, results.size());
EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
*rdata::createRdata(RRType::DNSKEY(), zclass,
dnskey_rdata)));
}
TEST_F(MasterLoadTest, loadRRWithCommentNoSpace) {
// Similar to the previous one, but there's no space before comments.
// It should still work.
rr_stream << "example.com. 3600 IN DNSKEY 256 3 7 "
"AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH "
"zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE=; key id = 40430\n";
masterLoad(rr_stream, origin, zclass, callback);
ASSERT_EQ(1, results.size());
EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
*rdata::createRdata(RRType::DNSKEY(), zclass,
dnskey_rdata)));
}
TEST_F(MasterLoadTest, loadRRNoComment) {
// A semicolon in a character-string shouldn't confuse the parser.
rr_stream << "example.com. 3600 IN TXT \"aaa;bbb\"\n";
masterLoad(rr_stream, origin, zclass, callback);
EXPECT_EQ(1, results.size());
EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare(
*rdata::createRdata(RRType::TXT(), zclass,
"\"aaa;bbb\"")));
}
TEST_F(MasterLoadTest, loadRREmptyAndComment) {
// There's no RDATA (invalid in this case) but a comment. This position
// shouldn't cause any disruption and should be treated as a normal error.
rr_stream << "example.com. 3600 IN A ;\n";
EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback),
MasterLoadError);
}
TEST_F(MasterLoadTest, loadWithNoEOF) {
// the input stream doesn't end with a new line (and the following blank
// line). It should be accepted.
......
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