Mon, 11 Feb 2019 17:00:04 +0100
8214059: Undefined behaviour in ADLC
Reviewed-by: shade, kbarrett
Contributed-by: Simon Tooke <stooke@redhat.com>
1.1 --- a/src/share/vm/adlc/adlparse.cpp Wed Feb 06 11:41:51 2019 +0100 1.2 +++ b/src/share/vm/adlc/adlparse.cpp Mon Feb 11 17:00:04 2019 +0100 1.3 @@ -2868,7 +2868,8 @@ 1.4 const char* param = NULL; 1.5 inst._parameters.reset(); 1.6 while ((param = inst._parameters.iter()) != NULL) { 1.7 - OperandForm* opForm = (OperandForm*) inst._localNames[param]; 1.8 + OpClassForm* opForm = inst._localNames[param]->is_opclass(); 1.9 + assert(opForm != NULL, "sanity"); 1.10 encoding->add_parameter(opForm->_ident, param); 1.11 } 1.12 1.13 @@ -3338,7 +3339,8 @@ 1.14 const char* param = NULL; 1.15 inst._parameters.reset(); 1.16 while ((param = inst._parameters.iter()) != NULL) { 1.17 - OperandForm* opForm = (OperandForm*) inst._localNames[param]; 1.18 + OpClassForm* opForm = inst._localNames[param]->is_opclass(); 1.19 + assert(opForm != NULL, "sanity"); 1.20 encoding->add_parameter(opForm->_ident, param); 1.21 } 1.22
2.1 --- a/src/share/vm/adlc/dfa.cpp Wed Feb 06 11:41:51 2019 +0100 2.2 +++ b/src/share/vm/adlc/dfa.cpp Mon Feb 11 17:00:04 2019 +0100 2.3 @@ -757,19 +757,27 @@ 2.4 } 2.5 2.6 int Expr::compute_min(const Expr *c1, const Expr *c2) { 2.7 - int result = c1->_min_value + c2->_min_value; 2.8 - assert( result >= 0, "Invalid cost computation"); 2.9 + int v1 = c1->_min_value; 2.10 + int v2 = c2->_min_value; 2.11 + assert(0 <= v2 && v2 <= Expr::Max, "sanity"); 2.12 + assert(v1 <= Expr::Max - v2, "Invalid cost computation"); 2.13 2.14 - return result; 2.15 + return v1 + v2; 2.16 } 2.17 2.18 + 2.19 int Expr::compute_max(const Expr *c1, const Expr *c2) { 2.20 - int result = c1->_max_value + c2->_max_value; 2.21 - if( result < 0 ) { // check for overflow 2.22 - result = Expr::Max; 2.23 + int v1 = c1->_max_value; 2.24 + int v2 = c2->_max_value; 2.25 + 2.26 + // Check for overflow without producing UB. If v2 is positive 2.27 + // and not larger than Max, the subtraction cannot underflow. 2.28 + assert(0 <= v2 && v2 <= Expr::Max, "sanity"); 2.29 + if (v1 > Expr::Max - v2) { 2.30 + return Expr::Max; 2.31 } 2.32 2.33 - return result; 2.34 + return v1 + v2; 2.35 } 2.36 2.37 void Expr::print() const {
3.1 --- a/src/share/vm/adlc/formssel.cpp Wed Feb 06 11:41:51 2019 +0100 3.2 +++ b/src/share/vm/adlc/formssel.cpp Mon Feb 11 17:00:04 2019 +0100 3.3 @@ -921,7 +921,8 @@ 3.4 const char *name; 3.5 const char *kill_name = NULL; 3.6 for (_parameters.reset(); (name = _parameters.iter()) != NULL;) { 3.7 - OperandForm *opForm = (OperandForm*)_localNames[name]; 3.8 + OpClassForm *opForm = _localNames[name]->is_opclass(); 3.9 + assert(opForm != NULL, "sanity"); 3.10 3.11 Effect* e = NULL; 3.12 { 3.13 @@ -938,7 +939,8 @@ 3.14 // complex so simply enforce the restriction during parse. 3.15 if (kill_name != NULL && 3.16 e->isa(Component::TEMP) && !e->isa(Component::DEF)) { 3.17 - OperandForm* kill = (OperandForm*)_localNames[kill_name]; 3.18 + OpClassForm* kill = _localNames[kill_name]->is_opclass(); 3.19 + assert(kill != NULL, "sanity"); 3.20 globalAD->syntax_err(_linenum, "%s: %s %s must be at the end of the argument list\n", 3.21 _ident, kill->_ident, kill_name); 3.22 } else if (e->isa(Component::KILL) && !e->isa(Component::USE)) { 3.23 @@ -2339,7 +2341,8 @@ 3.24 // Add parameters that "do not appear in match rule". 3.25 const char *name; 3.26 for (_parameters.reset(); (name = _parameters.iter()) != NULL;) { 3.27 - OperandForm *opForm = (OperandForm*)_localNames[name]; 3.28 + OpClassForm *opForm = _localNames[name]->is_opclass(); 3.29 + assert(opForm != NULL, "sanity"); 3.30 3.31 if ( _components.operand_position(name) == -1 ) { 3.32 _components.insert(name, opForm->_ident, Component::INVALID, false);