Browse Source

[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.
Jelte Jansen 12 years ago
parent
commit
ead1509187

+ 5 - 2
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 = {}

+ 140 - 60
src/lib/dns/rdata/generic/hinfo_13.cc

@@ -14,66 +14,167 @@
 
 #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, &quoted);
+    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);
 }
@@ -92,49 +193,28 @@ int
 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

+ 8 - 25
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 <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_;
 };
 
 

+ 146 - 113
src/lib/dns/rdata/generic/naptr_35.cc

@@ -14,119 +14,141 @@
 
 #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
@@ -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<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);
 }
 
@@ -158,67 +180,78 @@ int
 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

+ 9 - 22
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 <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

+ 3 - 2
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) {

+ 24 - 2
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);