rdata_char_string_unittest.cc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <util/unittests/wiredata.h>
  15. #include <dns/exceptions.h>
  16. #include <dns/rdata.h>
  17. #include <dns/rdata/generic/detail/char_string.h>
  18. #include <util/buffer.h>
  19. #include <gtest/gtest.h>
  20. #include <string>
  21. #include <vector>
  22. using namespace isc::dns;
  23. using namespace isc::dns::rdata;
  24. using isc::dns::rdata::generic::detail::CharString;
  25. using isc::dns::rdata::generic::detail::bufferToCharString;
  26. using isc::dns::rdata::generic::detail::stringToCharString;
  27. using isc::dns::rdata::generic::detail::charStringToString;
  28. using isc::dns::rdata::generic::detail::compareCharStrings;
  29. using isc::util::unittests::matchWireData;
  30. namespace {
  31. const uint8_t test_charstr[] = {
  32. sizeof("Test String") - 1,
  33. 'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'
  34. };
  35. class CharStringTest : public ::testing::Test {
  36. protected:
  37. CharStringTest() :
  38. // char-string representation for test data using two types of escape
  39. // ('r' = 114)
  40. test_str("Test\\ St\\114ing")
  41. {
  42. str_region.beg = &test_str[0];
  43. str_region.len = test_str.size();
  44. }
  45. CharString chstr; // place holder
  46. const std::string test_str;
  47. MasterToken::StringRegion str_region;
  48. };
  49. MasterToken::StringRegion
  50. createStringRegion(const std::string& str) {
  51. MasterToken::StringRegion region;
  52. region.beg = &str[0]; // note std ensures this works even if str is empty
  53. region.len = str.size();
  54. return (region);
  55. }
  56. TEST_F(CharStringTest, normalConversion) {
  57. uint8_t tmp[3]; // placeholder for expected sequence
  58. stringToCharString(str_region, chstr);
  59. matchWireData(test_charstr, sizeof(test_charstr), &chstr[0], chstr.size());
  60. // Empty string
  61. chstr.clear();
  62. stringToCharString(createStringRegion(""), chstr);
  63. tmp[0] = 0;
  64. matchWireData(tmp, 1, &chstr[0], chstr.size());
  65. // Possible largest char string
  66. chstr.clear();
  67. std::string long_str(255, 'x');
  68. stringToCharString(createStringRegion(long_str), chstr);
  69. std::vector<uint8_t> expected;
  70. expected.push_back(255); // len of char string
  71. expected.insert(expected.end(), long_str.begin(), long_str.end());
  72. matchWireData(&expected[0], expected.size(), &chstr[0], chstr.size());
  73. // Same data as the previous case, but the original string is longer than
  74. // the max; this shouldn't be rejected
  75. chstr.clear();
  76. long_str.at(254) = '\\'; // replace the last 'x' with '\'
  77. long_str.append("120"); // 'x' = 120
  78. stringToCharString(createStringRegion(long_str), chstr);
  79. matchWireData(&expected[0], expected.size(), &chstr[0], chstr.size());
  80. // Escaped '\'
  81. chstr.clear();
  82. tmp[0] = 1;
  83. tmp[1] = '\\';
  84. stringToCharString(createStringRegion("\\\\"), chstr);
  85. matchWireData(tmp, 2, &chstr[0], chstr.size());
  86. // Boundary values for \DDD
  87. chstr.clear();
  88. tmp[0] = 1;
  89. tmp[1] = 0;
  90. stringToCharString(createStringRegion("\\000"), chstr);
  91. matchWireData(tmp, 2, &chstr[0], chstr.size());
  92. chstr.clear();
  93. stringToCharString(createStringRegion("\\255"), chstr);
  94. tmp[0] = 1;
  95. tmp[1] = 255;
  96. matchWireData(tmp, 2, &chstr[0], chstr.size());
  97. // Another digit follows DDD; it shouldn't cause confusion
  98. chstr.clear();
  99. stringToCharString(createStringRegion("\\2550"), chstr);
  100. tmp[0] = 2; // string len is now 2
  101. tmp[2] = '0';
  102. matchWireData(tmp, 3, &chstr[0], chstr.size());
  103. }
  104. TEST_F(CharStringTest, badConversion) {
  105. // string cannot exceed 255 bytes
  106. EXPECT_THROW(stringToCharString(createStringRegion(std::string(256, 'a')),
  107. chstr),
  108. CharStringTooLong);
  109. // input string ending with (non escaped) '\'
  110. chstr.clear();
  111. EXPECT_THROW(stringToCharString(createStringRegion("foo\\"), chstr),
  112. InvalidRdataText);
  113. }
  114. TEST_F(CharStringTest, badDDD) {
  115. // Check various type of bad form of \DDD
  116. // Not a number
  117. EXPECT_THROW(stringToCharString(createStringRegion("\\1a2"), chstr),
  118. InvalidRdataText);
  119. EXPECT_THROW(stringToCharString(createStringRegion("\\12a"), chstr),
  120. InvalidRdataText);
  121. // Not in the range of uint8_t
  122. EXPECT_THROW(stringToCharString(createStringRegion("\\256"), chstr),
  123. InvalidRdataText);
  124. // Short buffer
  125. EXPECT_THROW(stringToCharString(createStringRegion("\\42"), chstr),
  126. InvalidRdataText);
  127. }
  128. const struct TestData {
  129. const char *data;
  130. const char *expected;
  131. } conversion_data[] = {
  132. {"Test\"Test", "Test\\\"Test"},
  133. {"Test;Test", "Test\\;Test"},
  134. {"Test\\Test", "Test\\\\Test"},
  135. {"Test\x1fTest", "Test\\031Test"},
  136. {"Test ~ Test", "Test ~ Test"},
  137. {"Test\x7fTest", "Test\\127Test"},
  138. {NULL, NULL}
  139. };
  140. TEST_F(CharStringTest, charStringToString) {
  141. for (const TestData* cur = conversion_data; cur->data != NULL; ++cur) {
  142. uint8_t idata[32];
  143. size_t length = std::strlen(cur->data);
  144. // length (1 byte) + string (length bytes)
  145. assert(sizeof(idata) > length);
  146. idata[0] = static_cast<uint8_t>(length);
  147. std::memcpy(idata + 1, cur->data, length);
  148. const CharString test_data(idata, idata + length + 1);
  149. EXPECT_EQ(cur->expected, charStringToString(test_data));
  150. }
  151. }
  152. TEST_F(CharStringTest, bufferToCharString) {
  153. const size_t chstr_size = sizeof(test_charstr);
  154. isc::util::InputBuffer buf(test_charstr, chstr_size);
  155. size_t read = bufferToCharString(buf, chstr_size, chstr);
  156. EXPECT_EQ(chstr_size, read);
  157. EXPECT_EQ("Test String", charStringToString(chstr));
  158. }
  159. TEST_F(CharStringTest, bufferToCharString_bad) {
  160. const size_t chstr_size = sizeof(test_charstr);
  161. isc::util::InputBuffer buf(test_charstr, chstr_size);
  162. // Set valid data in both so we can make sure the charstr is not
  163. // modified
  164. bufferToCharString(buf, chstr_size, chstr);
  165. ASSERT_EQ("Test String", charStringToString(chstr));
  166. // Should be at end of buffer now, so it should fail
  167. EXPECT_THROW(bufferToCharString(buf, chstr_size - 1, chstr),
  168. DNSMessageFORMERR);
  169. EXPECT_EQ("Test String", charStringToString(chstr));
  170. // reset and try to read with too low rdata_len
  171. buf.setPosition(0);
  172. EXPECT_THROW(bufferToCharString(buf, chstr_size - 1, chstr),
  173. DNSMessageFORMERR);
  174. EXPECT_EQ("Test String", charStringToString(chstr));
  175. // set internal charstring len too high
  176. const uint8_t test_charstr_err[] = {
  177. sizeof("Test String") + 1,
  178. 'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'
  179. };
  180. buf = isc::util::InputBuffer(test_charstr_err, sizeof(test_charstr_err));
  181. EXPECT_THROW(bufferToCharString(buf, chstr_size, chstr),
  182. DNSMessageFORMERR);
  183. EXPECT_EQ("Test String", charStringToString(chstr));
  184. }
  185. TEST_F(CharStringTest, compareCharString) {
  186. CharString charstr;
  187. CharString charstr2;
  188. CharString charstr_small1;
  189. CharString charstr_small2;
  190. CharString charstr_large1;
  191. CharString charstr_large2;
  192. CharString charstr_empty;
  193. stringToCharString(createStringRegion("test string"), charstr);
  194. stringToCharString(createStringRegion("test string"), charstr2);
  195. stringToCharString(createStringRegion("test strin"), charstr_small1);
  196. stringToCharString(createStringRegion("test strina"), charstr_small2);
  197. stringToCharString(createStringRegion("test stringa"), charstr_large1);
  198. stringToCharString(createStringRegion("test strinz"), charstr_large2);
  199. EXPECT_EQ(0, compareCharStrings(charstr, charstr2));
  200. EXPECT_EQ(0, compareCharStrings(charstr2, charstr));
  201. EXPECT_EQ(1, compareCharStrings(charstr, charstr_small1));
  202. EXPECT_EQ(1, compareCharStrings(charstr, charstr_small2));
  203. EXPECT_EQ(-1, compareCharStrings(charstr, charstr_large1));
  204. EXPECT_EQ(-1, compareCharStrings(charstr, charstr_large2));
  205. EXPECT_EQ(-1, compareCharStrings(charstr_small1, charstr));
  206. EXPECT_EQ(-1, compareCharStrings(charstr_small2, charstr));
  207. EXPECT_EQ(1, compareCharStrings(charstr_large1, charstr));
  208. EXPECT_EQ(1, compareCharStrings(charstr_large2, charstr));
  209. EXPECT_EQ(-1, compareCharStrings(charstr_empty, charstr));
  210. EXPECT_EQ(1, compareCharStrings(charstr, charstr_empty));
  211. EXPECT_EQ(0, compareCharStrings(charstr_empty, charstr_empty));
  212. }
  213. } // unnamed namespace