Browse Source

[master] Merge remote-tracking branch 'trac4510' (backslashes fix)

Tomek Mrugalski 9 years ago
parent
commit
7a6078aec8

+ 20 - 0
src/lib/cc/tests/data_unittests.cc

@@ -561,6 +561,26 @@ TEST(Element, escape) {
     EXPECT_NO_THROW(Element::fromJSON("\"  \n  \r \t \f  \n \n    \t\""));
 }
 
+// This test verifies that a backslash can be used in element content
+// when the element is created using constructor.
+TEST(Element, backslash1) {
+    string input = "SMSBoot\\x64";// One slash passed to elem constructor...
+    string exp = "SMSBoot\\x64";  // ... should result in one slash in the actual option.
+
+    StringElement elem(input);
+    EXPECT_EQ(exp, elem.stringValue());
+}
+
+// This test verifies that a backslash can be used in element content
+// when the element is created using fromJSON.
+TEST(Element, backslash2) {
+    string input = "\"SMSBoot\\\\x64\""; // Two slashes put in the config file...
+    string exp = "SMSBoot\\x64"; // ... should result in one slash in the actual option.
+
+    ElementPtr elem = Element::fromJSON(input);
+    EXPECT_EQ(exp, elem->stringValue());
+}
+
 TEST(Element, ListElement) {
     // this function checks the specific functions for ListElements
     ElementPtr el = Element::fromJSON("[ 1, \"bar\", 3 ]");

+ 8 - 1
src/lib/dhcpsrv/parsers/dhcp_parsers.cc

@@ -164,7 +164,14 @@ template <> void ValueParser<std::string>::build(ConstElementPtr value) {
     // Invoke common code for all specializations of build().
     buildCommon(value);
 
-    value_ = value->str();
+    // For strings we need to use stringValue() rather than str().
+    // str() returns fully escaped special characters, so
+    // single backslash would be misrepresented as "\\".
+    if (value->getType() == Element::string) {
+        value_ = value->stringValue();
+    } else {
+        value_ = value->str();
+    }
     boost::erase_all(value_, "\"");
 }
 

+ 44 - 0
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc

@@ -655,6 +655,50 @@ TEST_F(ParseConfigTest, minimalOptionDataTest) {
     EXPECT_EQ(val, opt_ptr->toText());
 }
 
+/// @brief Check parsing of options with escape characters.
+///
+/// Note that this tests basic operation of the OptionDataListParser and
+/// OptionDataParser.  It uses a simple configuration consisting of one
+/// one definition and matching option data.  It verifies that the option
+/// is parsed and committed to storage correctly and that its content
+/// has the actual character (e.g. an actual backslash, not double backslash).
+TEST_F(ParseConfigTest, escapedOptionDataTest) {
+
+    parser_context_->universe_ = Option::V4;
+
+    // We need to use double escapes here. The first backslash will
+    // be consumed by C++ preprocessor, so the actual string will
+    // have two backslash characters: \\SMSBoot\\x64\\wdsnbp.com.
+    //
+    std::string config =
+        "{\"option-data\": [ {"
+        "    \"name\": \"boot-file-name\","
+        "    \"data\": \"\\\\SMSBoot\\\\x64\\\\wdsnbp.com\""
+        " } ]"
+        "}";
+    std::cout << config << std::endl;
+
+    // Verify that the configuration string parses.
+    int rcode = parseConfiguration(config);
+    ASSERT_EQ(0, rcode);
+
+    // Verify that the option can be retrieved.
+    OptionPtr opt = getOptionPtr("dhcp4", DHO_BOOT_FILE_NAME);
+    ASSERT_TRUE(opt);
+
+    util::OutputBuffer buf(100);
+
+    uint8_t exp[] = { DHO_BOOT_FILE_NAME, 23, '\\', 'S', 'M', 'S', 'B', 'o', 'o',
+                      't', '\\', 'x', '6', '4', '\\', 'w', 'd', 's', 'n', 'b',
+                      'p', '.', 'c', 'o', 'm' };
+    ASSERT_EQ(25, sizeof(exp));
+
+    opt->pack(buf);
+    EXPECT_EQ(Option::OPTION4_HDR_LEN + 23, buf.getLength());
+
+    EXPECT_TRUE(0 == memcmp(buf.getData(), exp, 25));
+}
+
 // This test checks behavior of the configuration parser for option data
 // for different values of csv-format parameter and when there is an option
 // definition present.