From 6ae4da980b84588f76726cb5ca2c9e0534e4743e Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Wed, 11 Nov 2015 15:33:00 +0100 Subject: [PATCH] [4088fd] Moved option code range check to the parser, freeing INTEGER tokens --- src/lib/eval/lexer.cc | 147 ++++++++++++------------- src/lib/eval/lexer.ll | 19 +--- src/lib/eval/parser.cc | 104 +++++++++-------- src/lib/eval/parser.h | 56 +++++----- src/lib/eval/parser.yy | 24 +++- src/lib/eval/tests/context_unittest.cc | 19 ++-- 6 files changed, 191 insertions(+), 178 deletions(-) diff --git a/src/lib/eval/lexer.cc b/src/lib/eval/lexer.cc index 92573d9260..696de045ec 100644 --- a/src/lib/eval/lexer.cc +++ b/src/lib/eval/lexer.cc @@ -478,14 +478,14 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[55] = +static yyconst flex_int16_t yy_accept[56] = { 0, 0, 0, 19, 17, 1, 2, 17, 12, 13, 16, - 7, 7, 17, 14, 15, 17, 17, 17, 1, 2, - 0, 5, 0, 0, 0, 7, 0, 8, 0, 0, - 0, 3, 0, 6, 0, 0, 0, 0, 0, 0, - 0, 4, 0, 0, 0, 9, 0, 0, 0, 0, - 0, 11, 10, 0 + 17, 7, 7, 17, 14, 15, 17, 17, 17, 1, + 2, 0, 5, 0, 0, 0, 7, 0, 8, 0, + 0, 0, 3, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 11, 10, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -528,58 +528,58 @@ static yyconst flex_int32_t yy_meta[32] = 1 } ; -static yyconst flex_int16_t yy_base[57] = +static yyconst flex_int16_t yy_base[58] = { 0, - 0, 0, 84, 85, 81, 79, 28, 85, 85, 85, - 25, 31, 69, 85, 85, 54, 49, 54, 75, 73, - 71, 85, 38, 40, 29, 44, 0, 85, 45, 55, - 43, 85, 39, 0, 49, 42, 38, 64, 42, 37, - 38, 85, 37, 33, 39, 85, 36, 38, 32, 44, - 30, 85, 85, 85, 62, 43 + 0, 0, 86, 87, 83, 81, 28, 87, 87, 87, + 24, 30, 32, 71, 87, 87, 56, 51, 56, 77, + 75, 73, 87, 39, 42, 31, 46, 0, 87, 47, + 57, 45, 87, 43, 0, 51, 44, 40, 66, 43, + 36, 38, 87, 39, 35, 41, 87, 38, 40, 34, + 46, 32, 87, 87, 87, 66, 47 } ; -static yyconst flex_int16_t yy_def[57] = +static yyconst flex_int16_t yy_def[58] = { 0, - 54, 1, 54, 54, 54, 54, 55, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 55, 54, 55, 55, 55, 54, 56, 54, 54, 54, - 54, 54, 55, 56, 54, 54, 54, 55, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 0, 54, 54 + 55, 1, 55, 55, 55, 55, 56, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 56, 55, 56, 56, 56, 55, 57, 55, 55, + 55, 55, 55, 56, 57, 55, 55, 55, 56, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 0, 55, 55 } ; -static yyconst flex_int16_t yy_nxt[117] = +static yyconst flex_int16_t yy_nxt[119] = { 0, - 4, 5, 6, 7, 8, 9, 10, 4, 11, 12, - 4, 13, 4, 4, 14, 15, 4, 4, 4, 4, - 4, 4, 4, 4, 16, 4, 4, 17, 4, 18, - 4, 22, 22, 26, 26, 23, 24, 24, 27, 26, - 26, 22, 22, 32, 25, 34, 24, 24, 24, 24, - 53, 33, 26, 26, 52, 51, 50, 49, 48, 47, - 46, 38, 21, 45, 21, 44, 43, 42, 41, 40, - 39, 37, 36, 35, 22, 20, 19, 31, 30, 29, - 28, 20, 19, 54, 3, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54 + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 4, 14, 4, 4, 15, 16, 4, 4, 4, 4, + 4, 4, 4, 4, 17, 4, 4, 18, 4, 19, + 4, 23, 27, 27, 23, 24, 25, 25, 27, 27, + 27, 27, 23, 28, 26, 33, 23, 25, 25, 35, + 25, 25, 54, 34, 27, 27, 53, 52, 51, 50, + 49, 48, 47, 46, 45, 39, 22, 44, 22, 43, + 42, 41, 40, 38, 37, 36, 23, 21, 20, 32, + 31, 30, 29, 21, 20, 55, 3, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55 } ; -static yyconst flex_int16_t yy_chk[117] = +static yyconst flex_int16_t yy_chk[119] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 7, 25, 11, 11, 7, 7, 7, 11, 12, - 12, 23, 33, 24, 7, 56, 23, 23, 24, 24, - 51, 25, 26, 26, 50, 49, 48, 47, 45, 44, - 43, 33, 55, 41, 55, 40, 39, 38, 37, 36, - 35, 31, 30, 29, 21, 20, 19, 18, 17, 16, - 13, 6, 5, 3, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54 + 1, 7, 11, 11, 26, 7, 7, 7, 12, 12, + 13, 13, 24, 12, 7, 25, 34, 24, 24, 57, + 25, 25, 52, 26, 27, 27, 51, 50, 49, 48, + 46, 45, 44, 42, 41, 34, 56, 40, 56, 39, + 38, 37, 36, 32, 31, 30, 22, 21, 20, 19, + 18, 17, 14, 6, 5, 3, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + + 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 55, 55, 55, 55, 55 } ; /* Table of booleans, true if rule could match eol. */ @@ -595,8 +595,8 @@ int yy_flex_debug = 1; static yyconst flex_int16_t yy_rule_linenum[18] = { 0, - 83, 87, 93, 101, 107, 117, 123, 146, 147, 148, - 149, 150, 151, 152, 153, 154, 156 + 83, 87, 93, 101, 107, 117, 123, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 147 } ; /* The intent behind this definition is that it'll catch @@ -975,13 +975,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 55 ) + if ( yy_current_state >= 56 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 54 ); + while ( yy_current_state != 55 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); @@ -1096,88 +1096,79 @@ case 7: YY_RULE_SETUP #line 123 "lexer.ll" { - // A code (16 bit unsigned integer) was found. + // An integer was found. std::string tmp(yytext); int n; try { n = boost::lexical_cast(tmp); } catch (const boost::bad_lexical_cast &) { - driver.error(loc, "Failed to convert specified option code to " - "number in " + tmp + "."); + driver.error(loc, "Failed to convert " + tmp + " to an integer."); } - // 65535 is the maximum value of the option code in DHCPv6. We want the - // code to be the same for v4 and v6, so let's ignore for a moment that - // max. option code in DHCPv4 is 255. - if (n < 0 || n > 65535) { - driver.error(loc, "Option code has invalid value in " + - std::string(yytext) + ". Allowed range: 0..65535"); - } - - return isc::eval::EvalParser::make_CODE(static_cast(n), loc); + return isc::eval::EvalParser::make_INTEGER(n, loc); } YY_BREAK case 8: YY_RULE_SETUP -#line 146 "lexer.ll" +#line 137 "lexer.ll" return isc::eval::EvalParser::make_EQUAL(loc); YY_BREAK case 9: YY_RULE_SETUP -#line 147 "lexer.ll" +#line 138 "lexer.ll" return isc::eval::EvalParser::make_OPTION(loc); YY_BREAK case 10: YY_RULE_SETUP -#line 148 "lexer.ll" +#line 139 "lexer.ll" return isc::eval::EvalParser::make_SUBSTRING(loc); YY_BREAK case 11: YY_RULE_SETUP -#line 149 "lexer.ll" +#line 140 "lexer.ll" return isc::eval::EvalParser::make_UNTYPED(loc); YY_BREAK case 12: YY_RULE_SETUP -#line 150 "lexer.ll" +#line 141 "lexer.ll" return isc::eval::EvalParser::make_LPAREN(loc); YY_BREAK case 13: YY_RULE_SETUP -#line 151 "lexer.ll" +#line 142 "lexer.ll" return isc::eval::EvalParser::make_RPAREN(loc); YY_BREAK case 14: YY_RULE_SETUP -#line 152 "lexer.ll" +#line 143 "lexer.ll" return isc::eval::EvalParser::make_LBRACKET(loc); YY_BREAK case 15: YY_RULE_SETUP -#line 153 "lexer.ll" +#line 144 "lexer.ll" return isc::eval::EvalParser::make_RBRACKET(loc); YY_BREAK case 16: YY_RULE_SETUP -#line 154 "lexer.ll" +#line 145 "lexer.ll" return isc::eval::EvalParser::make_COMA(loc); YY_BREAK case 17: YY_RULE_SETUP -#line 156 "lexer.ll" +#line 147 "lexer.ll" driver.error (loc, "Invalid character: " + std::string(yytext)); YY_BREAK case YY_STATE_EOF(INITIAL): -#line 157 "lexer.ll" +#line 148 "lexer.ll" return isc::eval::EvalParser::make_END(loc); YY_BREAK case 18: YY_RULE_SETUP -#line 158 "lexer.ll" +#line 149 "lexer.ll" ECHO; YY_BREAK -#line 1181 "lexer.cc" +#line 1172 "lexer.cc" case YY_END_OF_BUFFER: { @@ -1490,7 +1481,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 55 ) + if ( yy_current_state >= 56 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1523,11 +1514,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 55 ) + if ( yy_current_state >= 56 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 54); + yy_is_jam = (yy_current_state == 55); return yy_is_jam ? 0 : yy_current_state; } @@ -2265,7 +2256,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 158 "lexer.ll" +#line 149 "lexer.ll" diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll index 6a581adf29..61d851b474 100644 --- a/src/lib/eval/lexer.ll +++ b/src/lib/eval/lexer.ll @@ -62,7 +62,7 @@ static isc::eval::location loc; /* These are not token expressions yet, just convenience expressions that can be used during actual token definitions. */ -int [0-9]+ +int \-?[0-9]+ hex [0-9a-fA-F]+ blank [ \t] @@ -90,7 +90,7 @@ blank [ \t] loc.step(); } -\'\-?{int}\' { +\'{int}\' { // A string containing a number. Quotes should be removed, see below. std::string tmp(yytext+1); tmp.resize(tmp.size() - 1); @@ -121,26 +121,17 @@ blank [ \t] } {int} { - // A code (16 bit unsigned integer) was found. + // An integer was found. std::string tmp(yytext); int n; try { n = boost::lexical_cast(tmp); } catch (const boost::bad_lexical_cast &) { - driver.error(loc, "Failed to convert specified option code to " - "number in " + tmp + "."); + driver.error(loc, "Failed to convert " + tmp + " to an integer."); } - // 65535 is the maximum value of the option code in DHCPv6. We want the - // code to be the same for v4 and v6, so let's ignore for a moment that - // max. option code in DHCPv4 is 255. - if (n < 0 || n > 65535) { - driver.error(loc, "Option code has invalid value in " + - std::string(yytext) + ". Allowed range: 0..65535"); - } - - return isc::eval::EvalParser::make_CODE(static_cast(n), loc); + return isc::eval::EvalParser::make_INTEGER(n, loc); } "==" return isc::eval::EvalParser::make_EQUAL(loc); diff --git a/src/lib/eval/parser.cc b/src/lib/eval/parser.cc index cac8768118..360dc92c58 100644 --- a/src/lib/eval/parser.cc +++ b/src/lib/eval/parser.cc @@ -251,6 +251,10 @@ namespace isc { namespace eval { { switch (that.type_get ()) { + case 16: // "integer" + value.move< int > (that.value); + break; + case 12: // "a number in a constant string" case 13: // "the all constant string" case 14: // "constant string" @@ -258,10 +262,6 @@ namespace isc { namespace eval { value.move< std::string > (that.value); break; - case 16: // "option code" - value.move< uint16_t > (that.value); - break; - default: break; } @@ -277,6 +277,10 @@ namespace isc { namespace eval { state = that.state; switch (that.type_get ()) { + case 16: // "integer" + value.copy< int > (that.value); + break; + case 12: // "a number in a constant string" case 13: // "the all constant string" case 14: // "constant string" @@ -284,10 +288,6 @@ namespace isc { namespace eval { value.copy< std::string > (that.value); break; - case 16: // "option code" - value.copy< uint16_t > (that.value); - break; - default: break; } @@ -352,10 +352,10 @@ namespace isc { namespace eval { #line 353 "parser.cc" // lalr1.cc:636 break; - case 16: // "option code" + case 16: // "integer" #line 59 "parser.yy" // lalr1.cc:636 - { yyoutput << yysym.value.template as< uint16_t > (); } + { yyoutput << yysym.value.template as< int > (); } #line 360 "parser.cc" // lalr1.cc:636 break; @@ -556,6 +556,10 @@ namespace isc { namespace eval { when using variants. */ switch (yyr1_[yyn]) { + case 16: // "integer" + yylhs.value.build< int > (); + break; + case 12: // "a number in a constant string" case 13: // "the all constant string" case 14: // "constant string" @@ -563,10 +567,6 @@ namespace isc { namespace eval { yylhs.value.build< std::string > (); break; - case 16: // "option code" - yylhs.value.build< uint16_t > (); - break; - default: break; } @@ -632,113 +632,127 @@ namespace isc { namespace eval { case 10: #line 97 "parser.yy" // lalr1.cc:859 { - TokenPtr opt(new TokenOption(yystack_[1].value.as< uint16_t > ())); + int n = yystack_[1].value.as< int > (); + if (n < 0 || n > 65535) { + std::ostringstream oss; + oss << "Option code has invalid value in " << n + << ". Allowed range: 0..65535"; + ctx.error(yystack_[1].location, oss.str()); + } + TokenPtr opt(new TokenOption(static_cast(n))); ctx.expression.push_back(opt); } -#line 639 "parser.cc" // lalr1.cc:859 +#line 646 "parser.cc" // lalr1.cc:859 break; case 11: -#line 101 "parser.yy" // lalr1.cc:859 +#line 108 "parser.yy" // lalr1.cc:859 { TokenPtr sub(new TokenSubstring()); ctx.expression.push_back(sub); } -#line 648 "parser.cc" // lalr1.cc:859 +#line 655 "parser.cc" // lalr1.cc:859 break; case 12: -#line 108 "parser.yy" // lalr1.cc:859 +#line 115 "parser.yy" // lalr1.cc:859 { TokenPtr eq(new TokenEqual()); ctx.expression.push_back(eq); } -#line 657 "parser.cc" // lalr1.cc:859 +#line 664 "parser.cc" // lalr1.cc:859 break; case 13: -#line 115 "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 666 "parser.cc" // lalr1.cc:859 +#line 673 "parser.cc" // lalr1.cc:859 break; case 14: -#line 119 "parser.yy" // lalr1.cc:859 +#line 126 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 675 "parser.cc" // lalr1.cc:859 +#line 682 "parser.cc" // lalr1.cc:859 break; case 15: -#line 123 "parser.yy" // lalr1.cc:859 +#line 130 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString("all")); ctx.expression.push_back(str); } -#line 684 "parser.cc" // lalr1.cc:859 +#line 691 "parser.cc" // lalr1.cc:859 break; case 16: -#line 127 "parser.yy" // lalr1.cc:859 +#line 134 "parser.yy" // lalr1.cc:859 { TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(hex); } -#line 693 "parser.cc" // lalr1.cc:859 +#line 700 "parser.cc" // lalr1.cc:859 break; case 17: -#line 131 "parser.yy" // lalr1.cc:859 +#line 138 "parser.yy" // lalr1.cc:859 { - TokenPtr opt(new TokenOption(yystack_[1].value.as< uint16_t > ())); + int n = yystack_[1].value.as< int > (); + if (n < 0 || n > 65535) { + std::ostringstream oss; + oss << "Option code has invalid value in " << n + << ". Allowed range: 0..65535"; + ctx.error(yystack_[1].location, oss.str()); + } + TokenPtr opt(new TokenOption(static_cast(n))); ctx.expression.push_back(opt); } -#line 702 "parser.cc" // lalr1.cc:859 +#line 716 "parser.cc" // lalr1.cc:859 break; case 18: -#line 135 "parser.yy" // lalr1.cc:859 +#line 149 "parser.yy" // lalr1.cc:859 { TokenPtr sub(new TokenSubstring()); ctx.expression.push_back(sub); } -#line 711 "parser.cc" // lalr1.cc:859 +#line 725 "parser.cc" // lalr1.cc:859 break; case 19: -#line 142 "parser.yy" // lalr1.cc:859 +#line 156 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 720 "parser.cc" // lalr1.cc:859 +#line 734 "parser.cc" // lalr1.cc:859 break; case 20: -#line 149 "parser.yy" // lalr1.cc:859 +#line 163 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 729 "parser.cc" // lalr1.cc:859 +#line 743 "parser.cc" // lalr1.cc:859 break; case 21: -#line 153 "parser.yy" // lalr1.cc:859 +#line 167 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString("all")); ctx.expression.push_back(str); } -#line 738 "parser.cc" // lalr1.cc:859 +#line 752 "parser.cc" // lalr1.cc:859 break; -#line 742 "parser.cc" // lalr1.cc:859 +#line 756 "parser.cc" // lalr1.cc:859 default: break; } @@ -1086,7 +1100,7 @@ namespace isc { namespace eval { "\"substring\"", "\"untyped:\"", "\",\"", "\"(\"", "\")\"", "\"[\"", "\"]\"", "\"a number in a constant string\"", "\"the all constant string\"", "\"constant string\"", - "\"constant hexstring\"", "\"option code\"", "$accept", "expression", + "\"constant hexstring\"", "\"integer\"", "$accept", "expression", "untyped_expr", "token", "bool_expr", "string_expr", "start_expr", "length_expr", YY_NULLPTR }; @@ -1096,8 +1110,8 @@ namespace isc { namespace eval { EvalParser::yyrline_[] = { 0, 68, 68, 69, 73, 77, 81, 85, 89, 93, - 97, 101, 108, 115, 119, 123, 127, 131, 135, 142, - 149, 153 + 97, 108, 115, 122, 126, 130, 134, 138, 149, 156, + 163, 167 }; // Print the state stack on the debug stream. @@ -1132,8 +1146,8 @@ namespace isc { namespace eval { #line 21 "parser.yy" // lalr1.cc:1167 } } // isc::eval -#line 1136 "parser.cc" // lalr1.cc:1167 -#line 159 "parser.yy" // lalr1.cc:1168 +#line 1150 "parser.cc" // lalr1.cc:1167 +#line 173 "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 ec2b500803..df6a198caa 100644 --- a/src/lib/eval/parser.h +++ b/src/lib/eval/parser.h @@ -293,14 +293,14 @@ namespace isc { namespace eval { /// An auxiliary type to compute the largest semantic type. union union_type { + // "integer" + char dummy1[sizeof(int)]; + // "a number in a constant string" // "the all constant string" // "constant string" // "constant hexstring" - char dummy1[sizeof(std::string)]; - - // "option code" - char dummy2[sizeof(uint16_t)]; + char dummy2[sizeof(std::string)]; }; /// Symbol semantic values. @@ -337,7 +337,7 @@ namespace isc { namespace eval { TOKEN_ALL = 268, TOKEN_STRING = 269, TOKEN_HEXSTRING = 270, - TOKEN_CODE = 271 + TOKEN_INTEGER = 271 }; }; @@ -375,9 +375,9 @@ namespace isc { namespace eval { basic_symbol (typename Base::kind_type t, const location_type& l); - basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l); + basic_symbol (typename Base::kind_type t, const int v, const location_type& l); - basic_symbol (typename Base::kind_type t, const uint16_t v, const location_type& l); + basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l); /// Constructor for symbols with semantic value. @@ -504,7 +504,7 @@ namespace isc { namespace eval { static inline symbol_type - make_CODE (const uint16_t& v, const location_type& l); + make_INTEGER (const int& v, const location_type& l); /// Build a parser object. @@ -795,6 +795,10 @@ namespace isc { namespace eval { { switch (other.type_get ()) { + case 16: // "integer" + value.copy< int > (other.value); + break; + case 12: // "a number in a constant string" case 13: // "the all constant string" case 14: // "constant string" @@ -802,10 +806,6 @@ namespace isc { namespace eval { value.copy< std::string > (other.value); break; - case 16: // "option code" - value.copy< uint16_t > (other.value); - break; - default: break; } @@ -823,6 +823,10 @@ namespace isc { namespace eval { (void) v; switch (this->type_get ()) { + case 16: // "integer" + value.copy< int > (v); + break; + case 12: // "a number in a constant string" case 13: // "the all constant string" case 14: // "constant string" @@ -830,10 +834,6 @@ namespace isc { namespace eval { value.copy< std::string > (v); break; - case 16: // "option code" - value.copy< uint16_t > (v); - break; - default: break; } @@ -850,14 +850,14 @@ namespace isc { namespace eval { {} template - EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l) + EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const int v, const location_type& l) : Base (t) , value (v) , location (l) {} template - EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const uint16_t v, const location_type& l) + EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l) : Base (t) , value (v) , location (l) @@ -889,6 +889,10 @@ namespace isc { namespace eval { // Type destructor. switch (yytype) { + case 16: // "integer" + value.template destroy< int > (); + break; + case 12: // "a number in a constant string" case 13: // "the all constant string" case 14: // "constant string" @@ -896,10 +900,6 @@ namespace isc { namespace eval { value.template destroy< std::string > (); break; - case 16: // "option code" - value.template destroy< uint16_t > (); - break; - default: break; } @@ -923,6 +923,10 @@ namespace isc { namespace eval { super_type::move(s); switch (this->type_get ()) { + case 16: // "integer" + value.move< int > (s.value); + break; + case 12: // "a number in a constant string" case 13: // "the all constant string" case 14: // "constant string" @@ -930,10 +934,6 @@ namespace isc { namespace eval { value.move< std::string > (s.value); break; - case 16: // "option code" - value.move< uint16_t > (s.value); - break; - default: break; } @@ -1080,9 +1080,9 @@ namespace isc { namespace eval { } EvalParser::symbol_type - EvalParser::make_CODE (const uint16_t& v, const location_type& l) + EvalParser::make_INTEGER (const int& v, const location_type& l) { - return symbol_type (token::TOKEN_CODE, v, l); + return symbol_type (token::TOKEN_INTEGER, v, l); } diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index ecc1d48433..074d250072 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -55,7 +55,7 @@ using namespace isc::eval; %token ALL "the all constant string" %token STRING "constant string" %token HEXSTRING "constant hexstring" -%token CODE "option code" +%token INTEGER "integer" %printer { yyoutput << $$; } <*>; %% @@ -94,8 +94,15 @@ STRING { TokenPtr hex(new TokenHexString($1)); ctx.expression.push_back(hex); } -| OPTION "[" CODE "]" { - TokenPtr opt(new TokenOption($3)); +| OPTION "[" INTEGER "]" { + int n = $3; + if (n < 0 || n > 65535) { + std::ostringstream oss; + oss << "Option code has invalid value in " << n + << ". Allowed range: 0..65535"; + ctx.error(@3, oss.str()); + } + TokenPtr opt(new TokenOption(static_cast(n))); ctx.expression.push_back(opt); } | SUBSTRING "(" token "," token "," token ")" { @@ -128,8 +135,15 @@ STRING { TokenPtr hex(new TokenHexString($1)); ctx.expression.push_back(hex); } -| OPTION "[" CODE "]" { - TokenPtr opt(new TokenOption($3)); +| OPTION "[" INTEGER "]" { + int n = $3; + if (n < 0 || n > 65535) { + std::ostringstream oss; + oss << "Option code has invalid value in " << n + << ". Allowed range: 0..65535"; + ctx.error(@3, oss.str()); + } + TokenPtr opt(new TokenOption(static_cast(n))); ctx.expression.push_back(opt); } | SUBSTRING "(" string_expr "," start_expr "," length_expr ")" { diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index fc5697ed4f..fb6a72b7d2 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -259,9 +259,6 @@ TEST_F(EvalContextTest, scanErrors) { checkError("'\n'", ":1.1: Invalid character: '"); checkError("0x123h", ":1.6: Invalid character: h"); checkError("=", ":1.1: Invalid character: ="); - checkError("option[65536]", - ":1.8-12: Option code has invalid " - "value in 65536. Allowed range: 0..65535"); checkError("subtring", ":1.1: Invalid character: s"); checkError("untype: 'abc'", ":1.1: Invalid character: u"); checkError("untyped 'abc'", ":1.1: Invalid character: u"); @@ -274,10 +271,16 @@ TEST_F(EvalContextTest, scanParseErrors) { checkError("", ":1.1: syntax error, unexpected end of file"); checkError("untyped:", ":1.9: syntax error, unexpected end of file"); - checkError("0x", ":1.1: syntax error, unexpected option code"); + checkError("0x", ":1.1: syntax error, unexpected integer"); checkError("0abc", - ":1.1: syntax error, unexpected option code"); + ":1.1: syntax error, unexpected integer"); checkError("===", ":1.1-2: syntax error, unexpected =="); + checkError("option[-1]", + ":1.8-9: Option code has invalid " + "value in -1. Allowed range: 0..65535"); + checkError("option[65536]", + ":1.8-12: Option code has invalid " + "value in 65536. Allowed range: 0..65535"); checkError("option[123] < 'foo'", ":1.13: Invalid character: <"); } @@ -301,18 +304,18 @@ TEST_F(EvalContextTest, parseErrors) { checkError("option['ab'] == 'foo'", ":1.8-11: syntax error, " "unexpected constant string, " - "expecting option code"); + "expecting integer"); checkError("option[0xa] == 'ab'", ":1.8-10: syntax error, " "unexpected constant hexstring, " - "expecting option code"); + "expecting integer"); checkError("substring('foobar') == 'f'", ":1.19: syntax error, " "unexpected ), expecting \",\""); checkError("substring('foobar','3') == 'bar'", ":1.23: syntax error, unexpected ), expecting \",\""); checkError("substring('foobar',3,3) == 'bar'", - ":1.20: syntax error, unexpected option code, " + ":1.20: syntax error, unexpected integer, " "expecting a number in a constant string"); } -- 2.47.2