From dab26bf4e7c8b48e0c5ffbef1c5400807b78072c Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 28 Jun 2016 09:21:04 +0100 Subject: [AArch64] Make register indices be full 64-bit values aarch64_opnd_info used bitfields to hold vector element indices, but values were stored into those bitfields before their ranges had been checked. This meant large invalid indices could be silently truncated to smaller valid indices. The two obvious fixes were to do the range checking earlier or use a full 64-bit field for the index. I went for the latter for two reasons: - Doing the range checking in operand_general_constraint_met_p seems structurally cleaner than doing it while parsing. - The bitfields didn't really buy us anything. The imm field of the union is already 128 bits, so we can use a full int64_t index without growing the structure. The patch also adds missing range checks for the elements in a register list index. include/ * opcode/aarch64.h (aarch64_opnd_info): Change index fields to int64_t. opcodes/ * aarch64-opc.c (operand_general_constraint_met_p): Check the range of ldst_elemlist operands. (print_register_list): Use PRIi64 to print the index. (aarch64_print_operand): Likewise. gas/ * testsuite/gas/aarch64/diagnostic.s, testsuite/gas/aarch64/diagnostic.l: Add tests for out-of-range indices. --- opcodes/ChangeLog | 7 +++++++ opcodes/aarch64-opc.c | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'opcodes') diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index fd59786..69d3298 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,10 @@ +2016-06-28 Richard Sandiford + + * aarch64-opc.c (operand_general_constraint_met_p): Check the + range of ldst_elemlist operands. + (print_register_list): Use PRIi64 to print the index. + (aarch64_print_operand): Likewise. + 2016-06-25 Trevor Saunders * mcore-opc.h: Remove sentinal. diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c index d9a31e8..322b991 100644 --- a/opcodes/aarch64-opc.c +++ b/opcodes/aarch64-opc.c @@ -1521,6 +1521,16 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, break; case AARCH64_OPND_CLASS_SIMD_REGLIST: + if (type == AARCH64_OPND_LEt) + { + /* Get the upper bound for the element index. */ + num = 16 / aarch64_get_qualifier_esize (qualifier) - 1; + if (!value_in_range_p (opnd->reglist.index, 0, num)) + { + set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, num); + return 0; + } + } /* The opcode dependent area stores the number of elements in each structure to be loaded/stored. */ num = get_opcode_dependent_value (opcode); @@ -2256,7 +2266,7 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd) /* Prepare the index if any. */ if (opnd->reglist.has_index) - snprintf (tb, 8, "[%d]", opnd->reglist.index); + snprintf (tb, 8, "[%" PRIi64 "]", opnd->reglist.index); else tb[0] = '\0'; @@ -2479,7 +2489,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, case AARCH64_OPND_Ed: case AARCH64_OPND_En: case AARCH64_OPND_Em: - snprintf (buf, size, "v%d.%s[%d]", opnd->reglane.regno, + snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno, aarch64_get_qualifier_name (opnd->qualifier), opnd->reglane.index); break; -- cgit v1.1