changeset 53651:e017d2f176d0

8214059: Undefined behaviour in ADLC Reviewed-by: shade, kbarrett Contributed-by: Simon Tooke <stooke@redhat.com>
author sgehwolf
date Mon, 26 Nov 2018 09:36:30 +0100
parents c93e62e7fa3c
children e62fe5079d64
files src/hotspot/share/adlc/adlparse.cpp src/hotspot/share/adlc/dfa.cpp src/hotspot/share/adlc/formssel.cpp
diffstat 3 files changed, 25 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/adlc/adlparse.cpp	Mon Nov 26 12:20:06 2018 -0400
+++ b/src/hotspot/share/adlc/adlparse.cpp	Mon Nov 26 09:36:30 2018 +0100
@@ -2870,7 +2870,8 @@
   const char* param = NULL;
   inst._parameters.reset();
   while ((param = inst._parameters.iter()) != NULL) {
-    OperandForm* opForm = (OperandForm*) inst._localNames[param];
+    OpClassForm* opForm = inst._localNames[param]->is_opclass();
+    assert(opForm != NULL, "sanity");
     encoding->add_parameter(opForm->_ident, param);
   }
 
@@ -3340,7 +3341,8 @@
   const char* param = NULL;
   inst._parameters.reset();
   while ((param = inst._parameters.iter()) != NULL) {
-    OperandForm* opForm = (OperandForm*) inst._localNames[param];
+    OpClassForm* opForm = inst._localNames[param]->is_opclass();
+    assert(opForm != NULL, "sanity");
     encoding->add_parameter(opForm->_ident, param);
   }
 
--- a/src/hotspot/share/adlc/dfa.cpp	Mon Nov 26 12:20:06 2018 -0400
+++ b/src/hotspot/share/adlc/dfa.cpp	Mon Nov 26 09:36:30 2018 +0100
@@ -759,19 +759,27 @@
 }
 
 int Expr::compute_min(const Expr *c1, const Expr *c2) {
-  int result = c1->_min_value + c2->_min_value;
-  assert( result >= 0, "Invalid cost computation");
+  int v1 = c1->_min_value;
+  int v2 = c2->_min_value;
+  assert(0 <= v2 && v2 <= Expr::Max, "sanity");
+  assert(v1 <= Expr::Max - v2, "Invalid cost computation");
 
-  return result;
+  return v1 + v2;
 }
 
+
 int Expr::compute_max(const Expr *c1, const Expr *c2) {
-  int result = c1->_max_value + c2->_max_value;
-  if( result < 0 ) {  // check for overflow
-    result = Expr::Max;
+  int v1 = c1->_max_value;
+  int v2 = c2->_max_value;
+
+  // Check for overflow without producing UB. If v2 is positive
+  // and not larger than Max, the subtraction cannot underflow.
+  assert(0 <= v2 && v2 <= Expr::Max, "sanity");
+  if (v1 > Expr::Max - v2) {
+    return Expr::Max;
   }
 
-  return result;
+  return v1 + v2;
 }
 
 void Expr::print() const {
--- a/src/hotspot/share/adlc/formssel.cpp	Mon Nov 26 12:20:06 2018 -0400
+++ b/src/hotspot/share/adlc/formssel.cpp	Mon Nov 26 09:36:30 2018 +0100
@@ -919,7 +919,8 @@
   const char *name;
   const char *kill_name = NULL;
   for (_parameters.reset(); (name = _parameters.iter()) != NULL;) {
-    OperandForm *opForm = (OperandForm*)_localNames[name];
+    OpClassForm *opForm = _localNames[name]->is_opclass();
+    assert(opForm != NULL, "sanity");
 
     Effect* e = NULL;
     {
@@ -936,7 +937,8 @@
       // complex so simply enforce the restriction during parse.
       if (kill_name != NULL &&
           e->isa(Component::TEMP) && !e->isa(Component::DEF)) {
-        OperandForm* kill = (OperandForm*)_localNames[kill_name];
+        OpClassForm* kill = _localNames[kill_name]->is_opclass();
+        assert(kill != NULL, "sanity");
         globalAD->syntax_err(_linenum, "%s: %s %s must be at the end of the argument list\n",
                              _ident, kill->_ident, kill_name);
       } else if (e->isa(Component::KILL) && !e->isa(Component::USE)) {
@@ -2350,7 +2352,8 @@
   // Add parameters that "do not appear in match rule".
   const char *name;
   for (_parameters.reset(); (name = _parameters.iter()) != NULL;) {
-    OperandForm *opForm = (OperandForm*)_localNames[name];
+    OpClassForm *opForm = _localNames[name]->is_opclass();
+    assert(opForm != NULL, "sanity");
 
     if ( _components.operand_position(name) == -1 ) {
       _components.insert(name, opForm->_ident, Component::INVALID, false);