Parcourir la 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 il y a 12 ans
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);