Browse Source

[2383] Basic parsing in the new Name constructor

We only call the same parsing as from within the old constructor. No
appending of origin is done. Also, no checking some data came, so the
tests not only fail, but also segfault.
Michal 'vorner' Vaner 12 years ago
parent
commit
8d2205ed3f
2 changed files with 44 additions and 27 deletions
  1. 39 16
      src/lib/dns/name.cc
  2. 5 11
      src/lib/dns/tests/name_unittest.cc

+ 39 - 16
src/lib/dns/name.cc

@@ -133,11 +133,12 @@ typedef enum {
 // The parser of name from a string. It is a template, because
 // some parameters are used with two different types, while others
 // are private type aliases.
-template<class String, class Iterator, class Offsets, class Data>
+template<class Iterator, class Offsets, class Data>
 void
-stringParse(const String& namestring, Iterator s, Iterator send,
-            bool downcase, Offsets& offsets, Data& ndata)
+stringParse(Iterator s, Iterator send, bool downcase, Offsets& offsets,
+            Data& ndata)
 {
+    const Iterator orig_s(s);
     //
     // Initialize things to make the compiler happy; they're not required.
     //
@@ -150,6 +151,7 @@ stringParse(const String& namestring, Iterator s, Iterator send,
     //
     bool done = false;
     bool is_root = false;
+    const bool empty = s == send;
     ft_state state = ft_init;
 
     // Prepare the output buffers.
@@ -173,7 +175,8 @@ stringParse(const String& namestring, Iterator s, Iterator send,
             if (c == '.') {
                 if (s != send) {
                     isc_throw(EmptyLabel,
-                              "non terminating empty label in " << namestring);
+                              "non terminating empty label in " <<
+                              string(orig_s, send));
                 }
                 is_root = true;
             } else if (c == '@' && s == send) {
@@ -202,7 +205,7 @@ stringParse(const String& namestring, Iterator s, Iterator send,
             if (c == '.') {
                 if (count == 0) {
                     isc_throw(EmptyLabel,
-                              "duplicate period in " << namestring);
+                              "duplicate period in " << string(orig_s, send));
                 }
                 ndata.at(offsets.back()) = count;
                 offsets.push_back(ndata.size());
@@ -216,7 +219,7 @@ stringParse(const String& namestring, Iterator s, Iterator send,
             } else {
                 if (++count > Name::MAX_LABELLEN) {
                     isc_throw(TooLongLabel,
-                              "label is too long in " << namestring);
+                              "label is too long in " << string(orig_s, send));
                 }
                 ndata.push_back(downcase ? maptolower[c] : c);
             }
@@ -226,7 +229,7 @@ stringParse(const String& namestring, Iterator s, Iterator send,
                 // This looks like a bitstring label, which was deprecated.
                 // Intentionally drop it.
                 isc_throw(BadLabelType,
-                          "invalid label type in " << namestring);
+                          "invalid label type in " << string(orig_s, send));
             }
             state = ft_escape;
             // FALLTHROUGH
@@ -234,7 +237,7 @@ stringParse(const String& namestring, Iterator s, Iterator send,
             if (!isdigit(c & 0xff)) {
                 if (++count > Name::MAX_LABELLEN) {
                     isc_throw(TooLongLabel,
-                              "label is too long in " << namestring);
+                              "label is too long in " << string(orig_s, send));
                 }
                 ndata.push_back(downcase ? maptolower[c] : c);
                 state = ft_ordinary;
@@ -248,7 +251,7 @@ stringParse(const String& namestring, Iterator s, Iterator send,
             if (!isdigit(c & 0xff)) {
                 isc_throw(BadEscape,
                           "mixture of escaped digit and non-digit in "
-                          << namestring);
+                          << string(orig_s, send));
             }
             value *= 10;
             value += digitvalue[c];
@@ -257,11 +260,11 @@ stringParse(const String& namestring, Iterator s, Iterator send,
                 if (value > 255) {
                     isc_throw(BadEscape,
                               "escaped decimal is too large in "
-                              << namestring);
+                              << string(orig_s, send));
                 }
                 if (++count > Name::MAX_LABELLEN) {
                     isc_throw(TooLongLabel,
-                              "label is too long in " << namestring);
+                              "label is too long in " << string(orig_s, send));
                 }
                 ndata.push_back(downcase ? maptolower[value] : value);
                 state = ft_ordinary;
@@ -276,13 +279,14 @@ stringParse(const String& namestring, Iterator s, Iterator send,
     if (!done) {                // no trailing '.' was found.
         if (ndata.size() == Name::MAX_WIRE) {
             isc_throw(TooLongName,
-                      "name is too long for termination in " << namestring);
+                      "name is too long for termination in " <<
+                      string(orig_s, send));
         }
         assert(s == send);
         if (state != ft_ordinary && state != ft_at) {
             isc_throw(IncompleteName,
                       "incomplete textual name in " <<
-                      (namestring.empty() ? "<empty>" : namestring));
+                      (empty ? "<empty>" : string(orig_s, send)));
         }
         if (state == ft_ordinary) {
             assert(count != 0);
@@ -299,15 +303,15 @@ stringParse(const String& namestring, Iterator s, Iterator send,
 
 Name::Name(const std::string &namestring, bool downcase) {
     // Prepare inputs for the parser
-    std::string::const_iterator s = namestring.begin();
-    std::string::const_iterator send = namestring.end();
+    const std::string::const_iterator s = namestring.begin();
+    const std::string::const_iterator send = namestring.end();
 
     // Prepare outputs
     NameOffsets offsets;
     NameString ndata;
 
     // To the parsing
-    stringParse(namestring, s, send, downcase, offsets, ndata);
+    stringParse(s, send, downcase, offsets, ndata);
 
     // And get the output
     labelcount_ = offsets.size();
@@ -317,6 +321,25 @@ Name::Name(const std::string &namestring, bool downcase) {
     offsets_.assign(offsets.begin(), offsets.end());
 }
 
+Name::Name(const char* namedata, size_t data_len, const Name*, bool downcase) {
+    // Prepare inputs for the parser
+    const char* end = namedata + data_len;
+
+    // Prepare outputs
+    NameOffsets offsets;
+    NameString ndata;
+
+    // Do the actual parsing
+    stringParse(namedata, end, downcase, offsets, ndata);
+
+    // Get the output
+    labelcount_ = offsets.size();
+    assert(labelcount_ > 0 && labelcount_ <= Name::MAX_LABELS);
+    ndata_.assign(ndata.data(), ndata.size());
+    length_ = ndata_.size();
+    offsets_.assign(offsets.begin(), offsets.end());
+}
+
 namespace {
 ///
 /// Wire-format name parser states.

+ 5 - 11
src/lib/dns/tests/name_unittest.cc

@@ -157,14 +157,11 @@ checkBadTextName(const string& txt) {
     // NameParserException.
     EXPECT_THROW(Name(txt, false), ExceptionType);
     EXPECT_THROW(Name(txt, false), NameParserException);
-#if 0
-    // TODO: Enable once the new constructor exists.
     // The same is thrown when constructing by the master-file constructor
     EXPECT_THROW(Name(txt.c_str(), txt.length(), &Name::ROOT_NAME()),
                  ExceptionType);
     EXPECT_THROW(Name(txt.c_str(), txt.length(), &Name::ROOT_NAME()),
                  NameParserException);
-#endif
 }
 
 TEST_F(NameTest, fromText) {
@@ -239,8 +236,6 @@ TEST_F(NameTest, fromText) {
     EXPECT_EQ(Name::MAX_LABELS, maxlabels.getLabelCount());
 }
 
-#if 0
-// TODO: Enable once the constructor exists, there's a need to test the changes
 // on the rest while we prepare it.
 // Check the @ syntax is accepted and it just copies the origin.
 TEST_F(NameTest, copyOrigin) {
@@ -255,12 +250,12 @@ TEST_F(NameTest, copyOrigin) {
 // Test the master-file constructor does not append the origin when the
 // provided name is absolute
 TEST_F(NameTest, dontAppendOrigin) {
-    EXPECT_EQ(example_name, Name("www.example.org.", 16, &origin_name));
+    EXPECT_EQ(example_name, Name("www.example.com.", 16, &origin_name));
     // The downcase works (only if provided, though)
-    EXPECT_EQ(example_name, Name("WWW.EXAMPLE.ORG.", 16, &origin_name, true));
-    EXPECT_EQ(example_name_upper, Name("WWW.EXAMPLE.ORG.", 16, &origin_name));
+    EXPECT_EQ(example_name, Name("WWW.EXAMPLE.COM.", 16, &origin_name, true));
+    EXPECT_EQ(example_name_upper, Name("WWW.EXAMPLE.COM.", 16, &origin_name));
     // And it does not require the origin to be provided
-    EXPECT_NO_THROW(Name("www.example.org.", 16, NULL));
+    EXPECT_NO_THROW(Name("www.example.com.", 16, NULL));
 }
 
 // Test the master-file constructor properly appends the origin when
@@ -272,7 +267,7 @@ TEST_F(NameTest, appendOrigin) {
     EXPECT_EQ(example_name, Name("WWW", 3, &origin_name_upper, true));
     EXPECT_EQ(example_name_upper, Name("WWW", 3, &origin_name_upper));
     // Check we can prepend more than one label
-    EXPECT_EQ(Name("a.b.c.d.example.org."), Name("a.b.c.d", 7, &origin_name));
+    EXPECT_EQ(Name("a.b.c.d.example.com."), Name("a.b.c.d", 7, &origin_name));
     // When the name is relative, we throw.
     EXPECT_THROW(Name("www", 3, NULL), MissingNameOrigin);
 }
@@ -299,7 +294,6 @@ TEST_F(NameTest, combinedTooLong) {
     EXPECT_NO_THROW(Name(max_labels_str, strlen(max_labels_str),
                          &Name::ROOT_NAME()));
 }
-#endif
 
 TEST_F(NameTest, fromWire) {
     //