From: Tomek Mrugalski Date: Thu, 19 May 2016 13:54:23 +0000 (+0200) Subject: [4510] Fix for escaped characters (e.g. backslashes) in option contents. X-Git-Tag: trac4106_update_base~7^2~1^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22f72b302e4f3e86f8c52ab6e108718abfdf4282;p=thirdparty%2Fkea.git [4510] Fix for escaped characters (e.g. backslashes) in option contents. --- diff --git a/src/lib/cc/tests/data_unittests.cc b/src/lib/cc/tests/data_unittests.cc index a8001a29be..f5643dbb00 100644 --- a/src/lib/cc/tests/data_unittests.cc +++ b/src/lib/cc/tests/data_unittests.cc @@ -561,15 +561,26 @@ TEST(Element, escape) { EXPECT_NO_THROW(Element::fromJSON("\" \n \r \t \f \n \n \t\"")); } -// This test verifies if a backslash can be defined properly. -TEST(Element, backslash) { - string input = "SMSBoot\\\\x64"; // Two slashes put in the config file... - string exp = "SMSBoot\\x64"; // ... should result in one slash in the actual option. +// 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 ]"); diff --git a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc index 0cabcbe9c9..10222af49b 100644 --- a/src/lib/dhcpsrv/parsers/dhcp_parsers.cc +++ b/src/lib/dhcpsrv/parsers/dhcp_parsers.cc @@ -164,7 +164,14 @@ template <> void ValueParser::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_, "\""); } diff --git a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc index 99e8177f89..673707968a 100644 --- a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc +++ b/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.