#
# 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 = {}
#include <config.h>
-#include <string>
-
-#include <boost/lexical_cast.hpp>
-
#include <exceptions/exceptions.h>
-
+#include <dns/exceptions.h>
#include <dns/name.h>
#include <dns/messagerenderer.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
-#include <dns/character_string.h>
+#include <dns/rdata/generic/detail/char_string.h>
#include <util/strutil.h>
+#include <string>
+
+#include <boost/lexical_cast.hpp>
+
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<int>(len));
+ }
+ if (buffer.getLength() < len) {
+ isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing "
+ "HINFO RDATA: not enough data in buffer to read: " <<
+ static_cast<int>(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<int>(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);
}
HINFO::compare(const Rdata& other) const {
const HINFO& other_hinfo = dynamic_cast<const HINFO&>(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 <typename T>
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
// BEGIN_RDATA_NAMESPACE
+class HINFOImpl;
+
/// \brief \c HINFO class represents the HINFO rdata defined in
/// RFC1034, RFC1035
///
// 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 <typename T>
- 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_;
};
#include <config.h>
-#include <string>
-
-#include <boost/lexical_cast.hpp>
-
-#include <exceptions/exceptions.h>
-
-#include <dns/character_string.h>
#include <dns/name.h>
#include <dns/messagerenderer.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/char_string.h>
+#include <exceptions/exceptions.h>
+
+#include <string>
+#include <boost/lexical_cast.hpp>
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<int>(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
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<string>(order_);
+ result += lexical_cast<string>(impl_->order);
result += " ";
- result += lexical_cast<string>(preference_);
+ result += lexical_cast<string>(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);
}
NAPTR::compare(const Rdata& other) const {
const NAPTR other_naptr = dynamic_cast<const NAPTR&>(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 <typename T>
+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
// BEGIN_RDATA_NAMESPACE
+class NAPTRImpl;
+
/// \brief \c NAPTR class represents the NAPTR rdata defined in
/// RFC2915, RFC2168 and RFC3403
///
// 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 <typename T>
- 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
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) {
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) {
// 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);
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);