re PR middle-end/84831 (Invalid memory read in parse_output_constraint)

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
This commit is contained in:
Jakub Jelinek 2018-03-13 09:12:07 +01:00 committed by Jakub Jelinek
parent ee6e130378
commit cd471b26ca
2 changed files with 64 additions and 53 deletions

View 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.

View 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 '?': 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 '<': 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;
default:
if (!ISALPHA (*p))
case '%':
if (operand_num + 1 == ninputs + noutputs)
{
error ("%<%%%> constraint used with last operand");
return false;
}
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))
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 '<': 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;
else
insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem);
break;
}
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;
}
for (size_t len = CONSTRAINT_LEN (*p, p); len; len--, p++)
if (*p == '\0')
break;
}
return true;
}