From: Jelte Jansen Date: Wed, 9 Jan 2013 10:44:49 +0000 (+0100) Subject: [2498] Update HINFO and NAPTR to use new createFromText X-Git-Tag: bind10-1.0.0-rc-release~100^2~4^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ead15091870f4dbd5a87640be3493e36d9e9da73;p=thirdparty%2Fkea.git [2498] Update HINFO and NAPTR to use new createFromText Also change internal representation of strings to type CharString; because CharString is (currently) hidden, this meant introducing pimpl to these classes. Also the relevant getters now return copies instead of references to strings. --- diff --git a/src/lib/dns/gen-rdatacode.py.in b/src/lib/dns/gen-rdatacode.py.in index 2bf9de6f0f..1174db44d8 100755 --- a/src/lib/dns/gen-rdatacode.py.in +++ b/src/lib/dns/gen-rdatacode.py.in @@ -32,8 +32,11 @@ import sys # # Example: # new_rdata_factory_users = [('a', 'in'), ('a', 'ch'), ('soa', 'generic')] -new_rdata_factory_users = [('aaaa', 'in'), ('txt', 'generic'), - ('spf', 'generic')] +new_rdata_factory_users = [('aaaa', 'in'), + ('hinfo', 'generic'), + ('spf', 'generic'), + ('txt', 'generic') + ] re_typecode = re.compile('([\da-z]+)_(\d+)') classcode2txt = {} diff --git a/src/lib/dns/rdata/generic/hinfo_13.cc b/src/lib/dns/rdata/generic/hinfo_13.cc index 77bfdfd21f..bae435e3b1 100644 --- a/src/lib/dns/rdata/generic/hinfo_13.cc +++ b/src/lib/dns/rdata/generic/hinfo_13.cc @@ -14,66 +14,167 @@ #include -#include - -#include - #include - +#include #include #include #include #include -#include +#include #include +#include + +#include + using namespace std; using boost::lexical_cast; using namespace isc::util; using namespace isc::dns; -using namespace isc::dns::characterstr; // BEGIN_ISC_NAMESPACE // BEGIN_RDATA_NAMESPACE +// helper(s) +namespace { + +/// \brief Reads one text field from the given buffer into the given CharString +/// +/// \return The number of bytes read +size_t +readTextField(detail::CharString& target, InputBuffer& buffer, + size_t rdata_len) { + if (rdata_len < 1 || buffer.getLength() < 1) { + isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " + "HINFO RDATA: insufficient data"); + } + const uint8_t len = buffer.readUint8(); + if (rdata_len < len + 1) { + isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " + "HINFO RDATA: character string length is too large: " << + static_cast(len)); + } + if (buffer.getLength() < len) { + isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " + "HINFO RDATA: not enough data in buffer to read: " << + static_cast(len) << " bytes"); + } -HINFO::HINFO(const std::string& hinfo_str) { - string::const_iterator input_iterator = hinfo_str.begin(); + target.resize(len + 1); + target[0] = len; + buffer.readData(&target[0] + 1, len); - bool quoted; - cpu_ = getNextCharacterString(hinfo_str, input_iterator, "ed); + return (len + 1); +} - skipLeftSpaces(hinfo_str, input_iterator, quoted); +/// \brief Compare one CharString field to another +/// +/// \param self The CharString field to compare +/// \param other The CharString field to compare to +/// +/// \return -1 if \c self would be sorted before \c other +/// 1 if \c self would be sorted after \c other +/// 0 if \c self and \c other are equal +int compareField(const detail::CharString& self, + const detail::CharString& other) { + const size_t self_len = self[0]; + const size_t other_len = other[0]; + const size_t cmp_len = min(self_len, other_len); + const int cmp = memcmp(&self[1], &other[1], cmp_len); + if (cmp < 0) { + return (-1); + } else if (cmp > 0) { + return (1); + } else if (self_len < other_len) { + return (-1); + } else if (self_len > other_len) { + return (1); + } else { + return (0); + } +} - os_ = getNextCharacterString(hinfo_str, input_iterator); +} // end unnamed namespace + +class HINFOImpl { +public: + HINFOImpl(const std::string& hinfo_str) { + std::istringstream ss(hinfo_str); + MasterLexer lexer; + lexer.pushSource(ss); + + try { + parseHINFOData(lexer); + // Should be at end of data now + if (lexer.getNextToken(MasterToken::QSTRING, true).getType() != + MasterToken::END_OF_FILE) { + isc_throw(InvalidRdataText, + "Invalid HINFO text format: too many fields."); + } + } catch (const MasterLexer::LexerError& ex) { + isc_throw(InvalidRdataText, "Failed to construct HINFO RDATA from " + << hinfo_str << "': " << ex.what()); + } + } - // Skip whitespace at the end. - while (input_iterator < hinfo_str.end() && isspace(*input_iterator)) { - ++input_iterator; + HINFOImpl(InputBuffer& buffer, size_t rdata_len) { + rdata_len -= readTextField(cpu, buffer, rdata_len); + rdata_len -= readTextField(os, buffer, rdata_len); + if (rdata_len != 0) { + isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " << + "HINFO RDATA: bytes left at end: " << + static_cast(rdata_len)); + } } - if (input_iterator < hinfo_str.end()) { - isc_throw(InvalidRdataText, - "Invalid HINFO text format: too many fields."); + + HINFOImpl(MasterLexer& lexer) + { + parseHINFOData(lexer); } -} -HINFO::HINFO(InputBuffer& buffer, size_t rdata_len) { - cpu_ = getNextCharacterString(buffer, rdata_len); - os_ = getNextCharacterString(buffer, rdata_len); -} +private: + void + parseHINFOData(MasterLexer& lexer) { + MasterToken token = lexer.getNextToken(MasterToken::QSTRING); + stringToCharString(token.getStringRegion(), cpu); + token = lexer.getNextToken(MasterToken::QSTRING); + stringToCharString(token.getStringRegion(), os); + } + +public: + detail::CharString cpu; + detail::CharString os; +}; + +HINFO::HINFO(const std::string& hinfo_str) : impl_(new HINFOImpl(hinfo_str)) +{} + + +HINFO::HINFO(InputBuffer& buffer, size_t rdata_len) : + impl_(new HINFOImpl(buffer, rdata_len)) +{} HINFO::HINFO(const HINFO& source): - Rdata(), cpu_(source.cpu_), os_(source.os_) + Rdata(), impl_(new HINFOImpl(*source.impl_)) { } +HINFO::HINFO(MasterLexer& lexer, const Name*, + MasterLoader::Options, MasterLoaderCallbacks&) : + impl_(new HINFOImpl(lexer)) +{} + +HINFO::~HINFO() { + delete impl_; +} + std::string HINFO::toText() const { string result; result += "\""; - result += cpu_; + result += detail::charStringToString(impl_->cpu); result += "\" \""; - result += os_; + result += detail::charStringToString(impl_->os); result += "\""; return (result); } @@ -92,49 +193,28 @@ int HINFO::compare(const Rdata& other) const { const HINFO& other_hinfo = dynamic_cast(other); - if (cpu_ < other_hinfo.cpu_) { - return (-1); - } else if (cpu_ > other_hinfo.cpu_) { - return (1); + const int cmp = compareField(impl_->cpu, other_hinfo.impl_->cpu); + if (cmp != 0) { + return (cmp); } - - if (os_ < other_hinfo.os_) { - return (-1); - } else if (os_ > other_hinfo.os_) { - return (1); - } - - return (0); + return (compareField(impl_->os, other_hinfo.impl_->os)); } -const std::string& +const std::string HINFO::getCPU() const { - return (cpu_); + return (detail::charStringToString(impl_->cpu)); } -const std::string& +const std::string HINFO::getOS() const { - return (os_); + return (detail::charStringToString(impl_->os)); } +template void -HINFO::skipLeftSpaces(const std::string& input_str, - std::string::const_iterator& input_iterator, - bool optional) -{ - if (input_iterator >= input_str.end()) { - isc_throw(InvalidRdataText, - "Invalid HINFO text format: field is missing."); - } - - if (!isspace(*input_iterator) && !optional) { - isc_throw(InvalidRdataText, - "Invalid HINFO text format: fields are not separated by space."); - } - // Skip white spaces - while (input_iterator < input_str.end() && isspace(*input_iterator)) { - ++input_iterator; - } +HINFO::toWireHelper(T& outputer) const { + outputer.writeData(&impl_->cpu[0], impl_->cpu.size()); + outputer.writeData(&impl_->os[0], impl_->os.size()); } // END_RDATA_NAMESPACE diff --git a/src/lib/dns/rdata/generic/hinfo_13.h b/src/lib/dns/rdata/generic/hinfo_13.h index 5534a7e794..045d7fedf5 100644 --- a/src/lib/dns/rdata/generic/hinfo_13.h +++ b/src/lib/dns/rdata/generic/hinfo_13.h @@ -28,6 +28,8 @@ // BEGIN_RDATA_NAMESPACE +class HINFOImpl; + /// \brief \c HINFO class represents the HINFO rdata defined in /// RFC1034, RFC1035 /// @@ -40,38 +42,19 @@ public: // END_COMMON_MEMBERS // HINFO specific methods - const std::string& getCPU() const; - const std::string& getOS() const; + ~HINFO(); -private: - /// Skip the left whitespaces of the input string - /// - /// If \c optional argument is \c true and no spaces occur at the - /// current location, then nothing happens. If \c optional is - /// \c false and no spaces occur at the current location, then - /// the \c InvalidRdataText exception is thrown. - /// - /// \param input_str The input string - /// \param input_iterator From which the skipping started - /// \param optional If true, the spaces are optionally skipped. - void skipLeftSpaces(const std::string& input_str, - std::string::const_iterator& input_iterator, - bool optional); + const std::string getCPU() const; + const std::string getOS() const; +private: /// Helper template function for toWire() /// /// \param outputer Where to write data in template - void toWireHelper(T& outputer) const { - outputer.writeUint8(cpu_.size()); - outputer.writeData(cpu_.c_str(), cpu_.size()); - - outputer.writeUint8(os_.size()); - outputer.writeData(os_.c_str(), os_.size()); - } + void toWireHelper(T& outputer) const; - std::string cpu_; - std::string os_; + HINFOImpl* impl_; }; diff --git a/src/lib/dns/rdata/generic/naptr_35.cc b/src/lib/dns/rdata/generic/naptr_35.cc index 0958eff5ee..611fc5b16d 100644 --- a/src/lib/dns/rdata/generic/naptr_35.cc +++ b/src/lib/dns/rdata/generic/naptr_35.cc @@ -14,119 +14,141 @@ #include -#include - -#include - -#include - -#include #include #include #include #include +#include +#include + +#include +#include using namespace std; using boost::lexical_cast; using namespace isc::util; using namespace isc::dns; -using namespace isc::dns::characterstr; // BEGIN_ISC_NAMESPACE // BEGIN_RDATA_NAMESPACE -namespace { -/// Skip the left whitespaces of the input string -/// -/// \param input_str The input string -/// \param input_iterator From which the skipping started -void -skipLeftSpaces(const std::string& input_str, - std::string::const_iterator& input_iterator) -{ - if (input_iterator >= input_str.end()) { - isc_throw(InvalidRdataText, - "Invalid NAPTR text format, field is missing."); +class NAPTRImpl { +public: + NAPTRImpl() : replacement(".") {} + + NAPTRImpl(InputBuffer& buffer, size_t rdata_len) : replacement(".") { + if (rdata_len < 4 || buffer.getLength() < 4) { + isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " + "NAPTR RDATA wire format: insufficient length "); + } + order = buffer.readUint16(); + preference = buffer.readUint16(); + rdata_len -= 4; + + rdata_len -= readTextField(flags, buffer, rdata_len); + rdata_len -= readTextField(services, buffer, rdata_len); + rdata_len -= readTextField(regexp, buffer, rdata_len); + replacement = Name(buffer); + if (rdata_len < 1) { + isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " + "NAPTR RDATA wire format: missing replacement name"); + } + rdata_len -= replacement.getLength(); + + if (rdata_len != 0) { + isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " << + "NAPTR RDATA: bytes left at end: " << + static_cast(rdata_len)); + } } - if (!isspace(*input_iterator)) { - isc_throw(InvalidRdataText, - "Invalid NAPTR text format, fields are not separated by space."); + NAPTRImpl(const std::string& naptr_str) : replacement(".") { + std::istringstream ss(naptr_str); + MasterLexer lexer; + lexer.pushSource(ss); + + try { + parseNAPTRData(lexer); + // Should be at end of data now + if (lexer.getNextToken(MasterToken::QSTRING, true).getType() != + MasterToken::END_OF_FILE) { + isc_throw(InvalidRdataText, + "Invalid NAPTR text format: too many fields."); + } + } catch (const MasterLexer::LexerError& ex) { + isc_throw(InvalidRdataText, "Failed to construct NAPTR RDATA from " + << naptr_str << "': " << ex.what()); + } } - // Skip white spaces - while (input_iterator < input_str.end() && isspace(*input_iterator)) { - ++input_iterator; + + NAPTRImpl(MasterLexer& lexer) : replacement(".") + { + parseNAPTRData(lexer); } -} -} // Anonymous namespace +private: + void + parseNAPTRData(MasterLexer& lexer) { + MasterToken token = lexer.getNextToken(MasterToken::NUMBER); + if (token.getNumber() > 65535) { + isc_throw(InvalidRdataText, + "Invalid NAPTR text format: order out of range: " + << token.getNumber()); + } + order = token.getNumber(); + token = lexer.getNextToken(MasterToken::NUMBER); + if (token.getNumber() > 65535) { + isc_throw(InvalidRdataText, + "Invalid NAPTR text format: preference out of range: " + << token.getNumber()); + } + preference = token.getNumber(); + + token = lexer.getNextToken(MasterToken::QSTRING); + stringToCharString(token.getStringRegion(), flags); + token = lexer.getNextToken(MasterToken::QSTRING); + stringToCharString(token.getStringRegion(), services); + token = lexer.getNextToken(MasterToken::QSTRING); + stringToCharString(token.getStringRegion(), regexp); + + token = lexer.getNextToken(MasterToken::STRING); + replacement = Name(token.getString()); + } -NAPTR::NAPTR(InputBuffer& buffer, size_t len): - replacement_(".") -{ - order_ = buffer.readUint16(); - preference_ = buffer.readUint16(); - flags_ = getNextCharacterString(buffer, len); - services_ = getNextCharacterString(buffer, len); - regexp_ = getNextCharacterString(buffer, len); - replacement_ = Name(buffer); -} - -NAPTR::NAPTR(const std::string& naptr_str): - replacement_(".") -{ - istringstream iss(naptr_str); +public: uint16_t order; uint16_t preference; - - iss >> order >> preference; - - if (iss.bad() || iss.fail()) { - isc_throw(InvalidRdataText, "Invalid NAPTR text format"); - } - - order_ = order; - preference_ = preference; - - string::const_iterator input_iterator = naptr_str.begin() + iss.tellg(); - - skipLeftSpaces(naptr_str, input_iterator); - - flags_ = getNextCharacterString(naptr_str, input_iterator); - - skipLeftSpaces(naptr_str, input_iterator); - - services_ = getNextCharacterString(naptr_str, input_iterator); - - skipLeftSpaces(naptr_str, input_iterator); - - regexp_ = getNextCharacterString(naptr_str, input_iterator); - - skipLeftSpaces(naptr_str, input_iterator); - - if (input_iterator < naptr_str.end()) { - string replacementStr(input_iterator, naptr_str.end()); - - replacement_ = Name(replacementStr); - } else { - isc_throw(InvalidRdataText, - "Invalid NAPTR text format, replacement field is missing"); - } -} - -NAPTR::NAPTR(const NAPTR& naptr): - Rdata(), order_(naptr.order_), preference_(naptr.preference_), - flags_(naptr.flags_), services_(naptr.services_), regexp_(naptr.regexp_), - replacement_(naptr.replacement_) -{ + detail::CharString flags; + detail::CharString services; + detail::CharString regexp; + Name replacement; +}; + +NAPTR::NAPTR(InputBuffer& buffer, size_t rdata_len) : + impl_(new NAPTRImpl(buffer, rdata_len)) +{} + +NAPTR::NAPTR(const std::string& naptr_str) : impl_(new NAPTRImpl(naptr_str)) +{} + +NAPTR::NAPTR(MasterLexer& lexer, const Name*, + MasterLoader::Options, MasterLoaderCallbacks&) : + impl_(new NAPTRImpl(lexer)) +{} + +NAPTR::NAPTR(const NAPTR& naptr) : Rdata(), + impl_(new NAPTRImpl(*naptr.impl_)) +{} + +NAPTR::~NAPTR() { + delete impl_; } void NAPTR::toWire(OutputBuffer& buffer) const { toWireHelper(buffer); - replacement_.toWire(buffer); - + impl_->replacement.toWire(buffer); } void @@ -134,23 +156,23 @@ NAPTR::toWire(AbstractMessageRenderer& renderer) const { toWireHelper(renderer); // Type NAPTR is not "well-known", and name compression must be disabled // per RFC3597. - renderer.writeName(replacement_, false); + renderer.writeName(impl_->replacement, false); } string NAPTR::toText() const { string result; - result += lexical_cast(order_); + result += lexical_cast(impl_->order); result += " "; - result += lexical_cast(preference_); + result += lexical_cast(impl_->preference); result += " \""; - result += flags_; + result += detail::charStringToString(impl_->flags); result += "\" \""; - result += services_; + result += detail::charStringToString(impl_->services); result += "\" \""; - result += regexp_; + result += detail::charStringToString(impl_->regexp); result += "\" "; - result += replacement_.toText(); + result += impl_->replacement.toText(); return (result); } @@ -158,67 +180,78 @@ int NAPTR::compare(const Rdata& other) const { const NAPTR other_naptr = dynamic_cast(other); - if (order_ < other_naptr.order_) { + if (impl_->order < other_naptr.impl_->order) { return (-1); - } else if (order_ > other_naptr.order_) { + } else if (impl_->order > other_naptr.impl_->order) { return (1); } - if (preference_ < other_naptr.preference_) { + if (impl_->preference < other_naptr.impl_->preference) { return (-1); - } else if (preference_ > other_naptr.preference_) { + } else if (impl_->preference > other_naptr.impl_->preference) { return (1); } - if (flags_ < other_naptr.flags_) { + if (impl_->flags < other_naptr.impl_->flags) { return (-1); - } else if (flags_ > other_naptr.flags_) { + } else if (impl_->flags > other_naptr.impl_->flags) { return (1); } - if (services_ < other_naptr.services_) { + if (impl_->services < other_naptr.impl_->services) { return (-1); - } else if (services_ > other_naptr.services_) { + } else if (impl_->services > other_naptr.impl_->services) { return (1); } - if (regexp_ < other_naptr.regexp_) { + if (impl_->regexp < other_naptr.impl_->regexp) { return (-1); - } else if (regexp_ > other_naptr.regexp_) { + } else if (impl_->regexp > other_naptr.impl_->regexp) { return (1); } - return (compareNames(replacement_, other_naptr.replacement_)); + return (compareNames(impl_->replacement, other_naptr.impl_->replacement)); } uint16_t NAPTR::getOrder() const { - return (order_); + return (impl_->order); } uint16_t NAPTR::getPreference() const { - return (preference_); + return (impl_->preference); } -const std::string& +const std::string NAPTR::getFlags() const { - return (flags_); + return (detail::charStringToString(impl_->flags)); } -const std::string& +const std::string NAPTR::getServices() const { - return (services_); + return (detail::charStringToString(impl_->services)); } -const std::string& +const std::string NAPTR::getRegexp() const { - return (regexp_); + return (detail::charStringToString(impl_->regexp)); } const Name& NAPTR::getReplacement() const { - return (replacement_); + return (impl_->replacement); +} + +template +void +NAPTR::toWireHelper(T& outputer) const { + outputer.writeUint16(impl_->order); + outputer.writeUint16(impl_->preference); + + outputer.writeData(&impl_->flags[0], impl_->flags.size()); + outputer.writeData(&impl_->services[0], impl_->services.size()); + outputer.writeData(&impl_->regexp[0], impl_->regexp.size()); } // END_RDATA_NAMESPACE diff --git a/src/lib/dns/rdata/generic/naptr_35.h b/src/lib/dns/rdata/generic/naptr_35.h index c82ef87678..567630224d 100644 --- a/src/lib/dns/rdata/generic/naptr_35.h +++ b/src/lib/dns/rdata/generic/naptr_35.h @@ -27,6 +27,8 @@ // BEGIN_RDATA_NAMESPACE +class NAPTRImpl; + /// \brief \c NAPTR class represents the NAPTR rdata defined in /// RFC2915, RFC2168 and RFC3403 /// @@ -39,37 +41,22 @@ public: // END_COMMON_MEMBERS // NAPTR specific methods + ~NAPTR(); + uint16_t getOrder() const; uint16_t getPreference() const; - const std::string& getFlags() const; - const std::string& getServices() const; - const std::string& getRegexp() const; + const std::string getFlags() const; + const std::string getServices() const; + const std::string getRegexp() const; const Name& getReplacement() const; private: /// Helper template function for toWire() /// /// \param outputer Where to write data in template - void toWireHelper(T& outputer) const { - outputer.writeUint16(order_); - outputer.writeUint16(preference_); - - outputer.writeUint8(flags_.size()); - outputer.writeData(flags_.c_str(), flags_.size()); - - outputer.writeUint8(services_.size()); - outputer.writeData(services_.c_str(), services_.size()); - - outputer.writeUint8(regexp_.size()); - outputer.writeData(regexp_.c_str(), regexp_.size()); - } + void toWireHelper(T& outputer) const; - uint16_t order_; - uint16_t preference_; - std::string flags_; - std::string services_; - std::string regexp_; - Name replacement_; + NAPTRImpl* impl_; }; // END_RDATA_NAMESPACE diff --git a/src/lib/dns/tests/rdata_hinfo_unittest.cc b/src/lib/dns/tests/rdata_hinfo_unittest.cc index f592066b6f..8d1b797f95 100644 --- a/src/lib/dns/tests/rdata_hinfo_unittest.cc +++ b/src/lib/dns/tests/rdata_hinfo_unittest.cc @@ -51,10 +51,9 @@ TEST_F(Rdata_HINFO_Test, createFromText) { HINFO hinfo(hinfo_str); EXPECT_EQ(string("Pentium"), hinfo.getCPU()); EXPECT_EQ(string("Linux"), hinfo.getOS()); - // Test the text with double quotes in the middle of string HINFO hinfo1(hinfo_str1); - EXPECT_EQ(string("Pen\"tium"), hinfo1.getCPU()); + EXPECT_EQ(string("Pen\\\"tium"), hinfo1.getCPU()); } TEST_F(Rdata_HINFO_Test, badText) { @@ -96,6 +95,8 @@ TEST_F(Rdata_HINFO_Test, createFromLexer) { EXPECT_FALSE(test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(), "\"Pentium\" \"Linux\" " "\"Computer\"")); + EXPECT_FALSE(test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(), + "\"Pentium\"")); } TEST_F(Rdata_HINFO_Test, toText) { diff --git a/src/lib/dns/tests/rdata_naptr_unittest.cc b/src/lib/dns/tests/rdata_naptr_unittest.cc index fed98cbda8..1bab91d1b6 100644 --- a/src/lib/dns/tests/rdata_naptr_unittest.cc +++ b/src/lib/dns/tests/rdata_naptr_unittest.cc @@ -99,10 +99,12 @@ TEST_F(Rdata_NAPTR_Test, badText) { // Order or preference cannot be missed EXPECT_THROW(const NAPTR naptr("10 \"S\" SIP \"\" _sip._udp.example.com."), InvalidRdataText); - // Fields must be seperated by spaces + // Unquoted fields must be seperated by spaces EXPECT_THROW(const NAPTR naptr("100 10S SIP \"\" _sip._udp.example.com."), InvalidRdataText); - EXPECT_THROW(const NAPTR naptr("100 10 \"S\"\"SIP\" \"\" _sip._udp.example.com."), + EXPECT_THROW(const NAPTR naptr("10010 \"S\" \"SIP\" \"\" _sip._udp.example.com."), + InvalidRdataText); + EXPECT_THROW(const NAPTR naptr("100 10 SSIP \"\" _sip._udp.example.com."), InvalidRdataText); // Field cannot be missing EXPECT_THROW(const NAPTR naptr("100 10 \"S\""), InvalidRdataText); @@ -128,6 +130,26 @@ TEST_F(Rdata_NAPTR_Test, createFromWire) { EXPECT_EQ(Name("_sip._udp.example.com."), naptr.getReplacement()); } +TEST_F(Rdata_NAPTR_Test, createFromWireTooLongDataLen) { + static uint8_t naptr_rdata_long[] = { + 0x00,0x0a,0x00,0x64,0x01,0x53,0x07,0x53,0x49,0x50,0x2b,0x44,0x32,0x55, + 0x00,0x04,0x5f,0x73,0x69,0x70,0x04,0x5f,0x75,0x64,0x70,0x07,0x65,0x78, + 0x61,0x6d,0x70,0x6c,0x65,0x03,0x63,0x6f,0x6d,0x00,0xff,0xff,0xff,0xff}; + InputBuffer input_buffer(naptr_rdata_long, sizeof(naptr_rdata_long)); + EXPECT_THROW(NAPTR naptr(input_buffer, sizeof(naptr_rdata_long)), + isc::dns::DNSMessageFORMERR); +} + +TEST_F(Rdata_NAPTR_Test, createFromWireTooShortDataLen) { + // missing data (just set rdata_len too low) + for (size_t i = 0; i < sizeof(naptr_rdata); ++i) { + // Just use existing correct buffer but set rdata_len too low + InputBuffer input_buffer(naptr_rdata, sizeof(naptr_rdata)); + EXPECT_THROW(NAPTR naptr(input_buffer, i), + isc::dns::DNSMessageFORMERR); + } +} + TEST_F(Rdata_NAPTR_Test, createFromLexer) { const NAPTR rdata_naptr(naptr_str);