re PR middle-end/84831 (Invalid memory read in parse_output_constraint)
authorJakub Jelinek <jakub@redhat.com>
Tue, 13 Mar 2018 08:12:07 +0000 (09:12 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 13 Mar 2018 08:12:07 +0000 (09:12 +0100)
PR middle-end/84831
* stmt.c (parse_output_constraint): If the CONSTRAINT_LEN (*p, p)
characters starting at p contain '\0' character, don't look beyond
that.

From-SVN: r258478

gcc/ChangeLog
gcc/stmt.c

index 20dbd41d9e33f354576694db9a0307c54f12bb4b..077dcef3f203a6bc86759ab41e60475b6b5fab2a 100644 (file)
@@ -1,5 +1,10 @@
 2018-03-13  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/84831
+       * stmt.c (parse_output_constraint): If the CONSTRAINT_LEN (*p, p)
+       characters starting at p contain '\0' character, don't look beyond
+       that.
+
        PR target/84827
        * config/i386/i386.md (round<mode>2): For 387 fancy math, disable
        pattern if -ftrapping-math -fno-fp-int-builtin-inexact.
index 457fe7f6f7886ccd15254c08e7b7c8a6fa115e61..9493dccf734b9e668231ce47ca0978d4b84f22e1 100644 (file)
@@ -247,62 +247,68 @@ parse_output_constraint (const char **constraint_p, int operand_num,
     }
 
   /* Loop through the constraint string.  */
-  for (p = constraint + 1; *p; p += CONSTRAINT_LEN (*p, p))
-    switch (*p)
-      {
-      case '+':
-      case '=':
-       error ("operand constraint contains incorrectly positioned "
-              "%<+%> or %<=%>");
-       return false;
+  for (p = constraint + 1; *p; )
+    {
+      switch (*p)
+       {
+       case '+':
+       case '=':
+         error ("operand constraint contains incorrectly positioned "
+                "%<+%> or %<=%>");
+         return false;
+
+       case '%':
+         if (operand_num + 1 == ninputs + noutputs)
+           {
+             error ("%<%%%> constraint used with last operand");
+             return false;
+           }
+         break;
 
-      case '%':
-       if (operand_num + 1 == ninputs + noutputs)
-         {
-           error ("%<%%%> constraint used with last operand");
-           return false;
-         }
-       break;
+       case '?':  case '!':  case '*':  case '&':  case '#':
+       case '$':  case '^':
+       case 'E':  case 'F':  case 'G':  case 'H':
+       case 's':  case 'i':  case 'n':
+       case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
+       case 'N':  case 'O':  case 'P':  case ',':
+         break;
 
-      case '?':  case '!':  case '*':  case '&':  case '#':
-      case '$':  case '^':
-      case 'E':  case 'F':  case 'G':  case 'H':
-      case 's':  case 'i':  case 'n':
-      case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
-      case 'N':  case 'O':  case 'P':  case ',':
-       break;
+       case '0':  case '1':  case '2':  case '3':  case '4':
+       case '5':  case '6':  case '7':  case '8':  case '9':
+       case '[':
+         error ("matching constraint not valid in output operand");
+         return false;
 
-      case '0':  case '1':  case '2':  case '3':  case '4':
-      case '5':  case '6':  case '7':  case '8':  case '9':
-      case '[':
-       error ("matching constraint not valid in output operand");
-       return false;
+       case '<':  case '>':
+         /* ??? Before flow, auto inc/dec insns are not supposed to exist,
+            excepting those that expand_call created.  So match memory
+            and hope.  */
+         *allows_mem = true;
+         break;
 
-      case '<':  case '>':
-       /* ??? Before flow, auto inc/dec insns are not supposed to exist,
-          excepting those that expand_call created.  So match memory
-          and hope.  */
-       *allows_mem = true;
-       break;
+       case 'g':  case 'X':
+         *allows_reg = true;
+         *allows_mem = true;
+         break;
 
-      case 'g':  case 'X':
-       *allows_reg = true;
-       *allows_mem = true;
-       break;
+       default:
+         if (!ISALPHA (*p))
+           break;
+         enum constraint_num cn = lookup_constraint (p);
+         if (reg_class_for_constraint (cn) != NO_REGS
+             || insn_extra_address_constraint (cn))
+           *allows_reg = true;
+         else if (insn_extra_memory_constraint (cn))
+           *allows_mem = true;
+         else
+           insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem);
+         break;
+       }
 
-      default:
-       if (!ISALPHA (*p))
+      for (size_t len = CONSTRAINT_LEN (*p, p); len; len--, p++)
+       if (*p == '\0')
          break;
-       enum constraint_num cn = lookup_constraint (p);
-       if (reg_class_for_constraint (cn) != NO_REGS
-           || insn_extra_address_constraint (cn))
-         *allows_reg = true;
-       else if (insn_extra_memory_constraint (cn))
-         *allows_mem = true;
-       else
-         insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem);
-       break;
-      }
+    }
 
   return true;
 }