From 3f5189fb7b4c7d8fe33c06209387935f2e1686dc Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Fri, 27 Nov 2015 15:15:23 +0100 Subject: [PATCH] [4204fd] Handle universe in option code range --- src/lib/eval/eval_context.cc | 6 +- src/lib/eval/eval_context.h | 11 +-- src/lib/eval/parser.cc | 104 +++++++++++++------------ src/lib/eval/parser.h | 5 +- src/lib/eval/parser.yy | 22 ++++-- src/lib/eval/tests/context_unittest.cc | 22 +++++- 6 files changed, 101 insertions(+), 69 deletions(-) diff --git a/src/lib/eval/eval_context.cc b/src/lib/eval/eval_context.cc index ac760860f5..b9a53d1d81 100644 --- a/src/lib/eval/eval_context.cc +++ b/src/lib/eval/eval_context.cc @@ -19,8 +19,8 @@ #include EvalContext::EvalContext(const Option::Universe& option_universe) - : trace_scanning_(false), trace_parsing_(false), - option_universe_(option_universe) + : option_universe_(option_universe), + trace_scanning_(false), trace_parsing_(false) { } @@ -34,7 +34,7 @@ EvalContext::parseString(const std::string& str) file_ = ""; string_ = str; scanStringBegin(); - isc::eval::EvalParser parser(*this, option_universe_); + isc::eval::EvalParser parser(*this); parser.set_debug_level(trace_parsing_); int res = parser.parse(); scanStringEnd(); diff --git a/src/lib/eval/eval_context.h b/src/lib/eval/eval_context.h index 1e7b9b9e30..946bb9980d 100644 --- a/src/lib/eval/eval_context.h +++ b/src/lib/eval/eval_context.h @@ -85,6 +85,12 @@ public: /// cases when the EvalParser is not able to handle the packet. void error(const std::string& what); + /// @brief Option universe: DHCPv4 or DHCPv6. + /// + /// This is used by the parser to determine which option definitions + /// set should be used to map option name to option code. + Option::Universe option_universe_; + private: /// @brief Flag determining scanner debugging. bool trace_scanning_; @@ -92,11 +98,6 @@ public: /// @brief Flag determing parser debugging. bool trace_parsing_; - /// @brief Option universe: DHCPv4 or DHCPv6. - /// - /// This is used by the parser to determine which option definitions - /// set should be used to map option name to option code. - Option::Universe option_universe_; }; }; // end of isc::eval namespace diff --git a/src/lib/eval/parser.cc b/src/lib/eval/parser.cc index 4104c73853..a63da62a87 100644 --- a/src/lib/eval/parser.cc +++ b/src/lib/eval/parser.cc @@ -52,7 +52,7 @@ #line 40 "parser.yy" // lalr1.cc:413 # include "eval_context.h" -#line 73 "parser.yy" // lalr1.cc:413 +#line 70 "parser.yy" // lalr1.cc:413 namespace { @@ -70,16 +70,23 @@ convert_option_code(const std::string& option_code, // This can't happen... ctx.error(loc, "Option code has invalid value in " + option_code); } - if (n < 0 || n > 65535) { - ctx.error(loc, "Option code has invalid value in " - + option_code + ". Allowed range: 0..65535"); + if (ctx.option_universe_ == Option::V6) { + if (n < 0 || n > 65535) { + ctx.error(loc, "Option code has invalid value in " + + option_code + ". Allowed range: 0..65535"); + } + } else { + if (n < 0 || n > 255) { + ctx.error(loc, "Option code has invalid value in " + + option_code + ". Allowed range: 0..255"); + } } return (static_cast(n)); } } -#line 83 "parser.cc" // lalr1.cc:413 +#line 90 "parser.cc" // lalr1.cc:413 #ifndef YY_ @@ -165,7 +172,7 @@ convert_option_code(const std::string& option_code, #line 21 "parser.yy" // lalr1.cc:479 namespace isc { namespace eval { -#line 169 "parser.cc" // lalr1.cc:479 +#line 176 "parser.cc" // lalr1.cc:479 /* Return YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is @@ -206,14 +213,13 @@ namespace isc { namespace eval { /// Build a parser object. - EvalParser::EvalParser (EvalContext& ctx_yyarg, const Option::Universe& option_universe_yyarg) + EvalParser::EvalParser (EvalContext& ctx_yyarg) : #if YYDEBUG yydebug_ (false), yycdebug_ (&std::cerr), #endif - ctx (ctx_yyarg), - option_universe (option_universe_yyarg) + ctx (ctx_yyarg) {} EvalParser::~EvalParser () @@ -347,37 +353,37 @@ namespace isc { namespace eval { { case 15: // "constant string" -#line 70 "parser.yy" // lalr1.cc:636 +#line 67 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 353 "parser.cc" // lalr1.cc:636 +#line 359 "parser.cc" // lalr1.cc:636 break; case 16: // "integer" -#line 70 "parser.yy" // lalr1.cc:636 +#line 67 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 360 "parser.cc" // lalr1.cc:636 +#line 366 "parser.cc" // lalr1.cc:636 break; case 17: // "constant hexstring" -#line 70 "parser.yy" // lalr1.cc:636 +#line 67 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 367 "parser.cc" // lalr1.cc:636 +#line 373 "parser.cc" // lalr1.cc:636 break; case 18: // "option name" -#line 70 "parser.yy" // lalr1.cc:636 +#line 67 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 374 "parser.cc" // lalr1.cc:636 +#line 380 "parser.cc" // lalr1.cc:636 break; case 19: // TOKEN -#line 70 "parser.yy" // lalr1.cc:636 +#line 67 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 381 "parser.cc" // lalr1.cc:636 +#line 387 "parser.cc" // lalr1.cc:636 break; @@ -603,59 +609,60 @@ namespace isc { namespace eval { switch (yyn) { case 3: -#line 111 "parser.yy" // lalr1.cc:859 +#line 115 "parser.yy" // lalr1.cc:859 { TokenPtr eq(new TokenEqual()); ctx.expression.push_back(eq); } -#line 612 "parser.cc" // lalr1.cc:859 +#line 618 "parser.cc" // lalr1.cc:859 break; case 4: -#line 118 "parser.yy" // lalr1.cc:859 +#line 122 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 621 "parser.cc" // lalr1.cc:859 +#line 627 "parser.cc" // lalr1.cc:859 break; case 5: -#line 123 "parser.yy" // lalr1.cc:859 +#line 127 "parser.yy" // lalr1.cc:859 { TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(hex); } -#line 630 "parser.cc" // lalr1.cc:859 +#line 636 "parser.cc" // lalr1.cc:859 break; case 6: -#line 128 "parser.yy" // lalr1.cc:859 +#line 132 "parser.yy" // lalr1.cc:859 { uint16_t numeric_code = convert_option_code(yystack_[3].value.as< std::string > (), yystack_[3].location, ctx); TokenPtr opt(new TokenOption(numeric_code, TokenOption::TEXTUAL)); ctx.expression.push_back(opt); } -#line 640 "parser.cc" // lalr1.cc:859 +#line 646 "parser.cc" // lalr1.cc:859 break; case 7: -#line 134 "parser.yy" // lalr1.cc:859 +#line 138 "parser.yy" // lalr1.cc:859 { uint16_t numeric_code = convert_option_code(yystack_[3].value.as< std::string > (), yystack_[3].location, ctx); TokenPtr opt(new TokenOption(numeric_code, TokenOption::HEXADECIMAL)); ctx.expression.push_back(opt); } -#line 650 "parser.cc" // lalr1.cc:859 +#line 656 "parser.cc" // lalr1.cc:859 break; case 8: -#line 140 "parser.yy" // lalr1.cc:859 +#line 144 "parser.yy" // lalr1.cc:859 { try { // This may result in exception if the specified // name is unknown. - TokenPtr opt(new TokenOption(yystack_[3].value.as< std::string > (), option_universe, + TokenPtr opt(new TokenOption(yystack_[3].value.as< std::string > (), + ctx.option_universe_, TokenOption::TEXTUAL)); ctx.expression.push_back(opt); @@ -663,16 +670,17 @@ namespace isc { namespace eval { ctx.error(yystack_[3].location, ex.what()); } } -#line 667 "parser.cc" // lalr1.cc:859 +#line 674 "parser.cc" // lalr1.cc:859 break; case 9: -#line 153 "parser.yy" // lalr1.cc:859 +#line 158 "parser.yy" // lalr1.cc:859 { try { // This may result in exception if the specified // name is unknown. - TokenPtr opt(new TokenOption(yystack_[3].value.as< std::string > (), option_universe, + TokenPtr opt(new TokenOption(yystack_[3].value.as< std::string > (), + ctx.option_universe_, TokenOption::HEXADECIMAL)); ctx.expression.push_back(opt); @@ -680,47 +688,47 @@ namespace isc { namespace eval { ctx.error(yystack_[3].location, ex.what()); } } -#line 684 "parser.cc" // lalr1.cc:859 +#line 692 "parser.cc" // lalr1.cc:859 break; case 10: -#line 166 "parser.yy" // lalr1.cc:859 +#line 172 "parser.yy" // lalr1.cc:859 { TokenPtr sub(new TokenSubstring()); ctx.expression.push_back(sub); } -#line 693 "parser.cc" // lalr1.cc:859 +#line 701 "parser.cc" // lalr1.cc:859 break; case 12: -#line 175 "parser.yy" // lalr1.cc:859 +#line 181 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 702 "parser.cc" // lalr1.cc:859 +#line 710 "parser.cc" // lalr1.cc:859 break; case 13: -#line 182 "parser.yy" // lalr1.cc:859 +#line 188 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 711 "parser.cc" // lalr1.cc:859 +#line 719 "parser.cc" // lalr1.cc:859 break; case 14: -#line 187 "parser.yy" // lalr1.cc:859 +#line 193 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString("all")); ctx.expression.push_back(str); } -#line 720 "parser.cc" // lalr1.cc:859 +#line 728 "parser.cc" // lalr1.cc:859 break; -#line 724 "parser.cc" // lalr1.cc:859 +#line 732 "parser.cc" // lalr1.cc:859 default: break; } @@ -1068,8 +1076,8 @@ namespace isc { namespace eval { const unsigned char EvalParser::yyrline_[] = { - 0, 107, 107, 110, 117, 122, 127, 133, 139, 152, - 165, 170, 174, 181, 186 + 0, 111, 111, 114, 121, 126, 131, 137, 143, 157, + 171, 176, 180, 187, 192 }; // Print the state stack on the debug stream. @@ -1104,8 +1112,8 @@ namespace isc { namespace eval { #line 21 "parser.yy" // lalr1.cc:1167 } } // isc::eval -#line 1108 "parser.cc" // lalr1.cc:1167 -#line 193 "parser.yy" // lalr1.cc:1168 +#line 1116 "parser.cc" // lalr1.cc:1167 +#line 199 "parser.yy" // lalr1.cc:1168 void isc::eval::EvalParser::error(const location_type& loc, diff --git a/src/lib/eval/parser.h b/src/lib/eval/parser.h index 309daf747f..96826b60f3 100644 --- a/src/lib/eval/parser.h +++ b/src/lib/eval/parser.h @@ -521,7 +521,7 @@ namespace isc { namespace eval { /// Build a parser object. - EvalParser (EvalContext& ctx_yyarg, const Option::Universe& option_universe_yyarg); + EvalParser (EvalContext& ctx_yyarg); virtual ~EvalParser (); /// Parse. @@ -735,7 +735,6 @@ namespace isc { namespace eval { // User arguments. EvalContext& ctx; - const Option::Universe& option_universe; }; // Symbol number corresponding to token number t. @@ -1101,7 +1100,7 @@ namespace isc { namespace eval { #line 21 "parser.yy" // lalr1.cc:392 } } // isc::eval -#line 1105 "parser.h" // lalr1.cc:392 +#line 1104 "parser.h" // lalr1.cc:392 diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index d7d69e4b9f..755f5c9024 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -40,9 +40,6 @@ using namespace isc::eval; { # include "eval_context.h" } -// Option universe: DHCPv4 or DHCPv6. This is required to use correct option -// definition set to map option names to codes. -%parse-param { const Option::Universe& option_universe } %define api.token.prefix {TOKEN_} %token @@ -87,9 +84,16 @@ convert_option_code(const std::string& option_code, // This can't happen... ctx.error(loc, "Option code has invalid value in " + option_code); } - if (n < 0 || n > 65535) { - ctx.error(loc, "Option code has invalid value in " - + option_code + ". Allowed range: 0..65535"); + if (ctx.option_universe_ == Option::V6) { + if (n < 0 || n > 65535) { + ctx.error(loc, "Option code has invalid value in " + + option_code + ". Allowed range: 0..65535"); + } + } else { + if (n < 0 || n > 255) { + ctx.error(loc, "Option code has invalid value in " + + option_code + ". Allowed range: 0..255"); + } } return (static_cast(n)); } @@ -141,7 +145,8 @@ string_expr : STRING try { // This may result in exception if the specified // name is unknown. - TokenPtr opt(new TokenOption($3, option_universe, + TokenPtr opt(new TokenOption($3, + ctx.option_universe_, TokenOption::TEXTUAL)); ctx.expression.push_back(opt); @@ -154,7 +159,8 @@ string_expr : STRING try { // This may result in exception if the specified // name is unknown. - TokenPtr opt(new TokenOption($3, option_universe, + TokenPtr opt(new TokenOption($3, + ctx.option_universe_, TokenOption::HEXADECIMAL)); ctx.expression.push_back(opt); diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index 894901e270..4fe602f448 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -31,6 +31,12 @@ namespace { /// @brief Test class for testing EvalContext aka class test parsing class EvalContextTest : public ::testing::Test { public: + /// @brief constructor to initialize members + EvalContextTest() : ::testing::Test() { + parsed_ = false; + universe_ = Option::V4; + } + /// @brief checks if the given token is a string with the expected value void checkTokenString(const TokenPtr& token, const std::string& expected) { ASSERT_TRUE(token); @@ -95,7 +101,7 @@ public: /// @brief checks if the given expression raises the expected message /// when it is parsed. void checkError(const string& expr, const string& msg) { - EvalContext eval(Option::V4); + EvalContext eval(universe_); parsed_ = false; try { parsed_ = eval.parseString(expr); @@ -110,6 +116,13 @@ public: } } + /// @brief sets the universe + /// @note the default universe is DHCPv4 + void setUniverse(const Option::Universe& universe) { + universe_ = universe; + } + + Option::Universe universe_; bool parsed_; ///< Parsing status }; @@ -292,10 +305,15 @@ TEST_F(EvalContextTest, scanParseErrors) { checkError("===", ":1.1-2: syntax error, unexpected =="); checkError("option[-1].text", ":1.8-9: Option code has invalid " - "value in -1. Allowed range: 0..65535"); + "value in -1. Allowed range: 0..255"); + checkError("option[256].text", + ":1.8-10: Option code has invalid " + "value in 256. Allowed range: 0..255"); + setUniverse(Option::V6); checkError("option[65536].text", ":1.8-12: Option code has invalid " "value in 65536. Allowed range: 0..65535"); + setUniverse(Option::V4); checkError("option[12345678901234567890].text", ":1.8-27: Failed to convert 12345678901234567890 " "to an integer."); -- 2.47.3