From 66a66a17f489a4ffc614a31855e8d6f516e24640 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 29 Oct 2019 09:17:39 +0000 Subject: [PATCH] Fix array overruns in the S12Z disassembler. * s12z-dis.c (opr_emit_disassembly): Check for illegal register values. (shift_size_table): Use a fixed size defined as S12Z_N_SIZES. (print_insn_s12z): Check for illegal size values. --- opcodes/ChangeLog | 7 ++++++ opcodes/s12z-dis.c | 53 ++++++++++++++++++++++++++++++++++------------ opcodes/s12z-opc.c | 12 +++++++++-- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 5f5a6c869b..d83b5bab85 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,10 @@ +2019-10-29 Nick Clifton + + * s12z-dis.c (opr_emit_disassembly): Check for illegal register + values. + (shift_size_table): Use a fixed size defined as S12Z_N_SIZES. + (print_insn_s12z): Check for illegal size values. + 2019-10-28 Nick Clifton * csky-dis.c (csky_chars_to_number): Check for a negative diff --git a/opcodes/s12z-dis.c b/opcodes/s12z-dis.c index 6086f1635d..5930ab4ef6 100644 --- a/opcodes/s12z-dis.c +++ b/opcodes/s12z-dis.c @@ -25,13 +25,11 @@ #include #include "opcode/s12z.h" - #include "bfd.h" #include "dis-asm.h" - #include "disassemble.h" - #include "s12z-opc.h" +#include "opintl.h" struct mem_read_abstraction { @@ -255,7 +253,11 @@ opr_emit_disassembly (const struct operand *opr, case OPND_CL_REGISTER: { int r = ((struct register_operand*) opr)->reg; - (*info->fprintf_func) (info->stream, "%s", registers[r].name); + + if (r < 0 || r >= S12Z_N_REGISTERS) + (*info->fprintf_func) (info->stream, _("")); + else + (*info->fprintf_func) (info->stream, "%s", registers[r].name); } break; case OPND_CL_REGISTER_ALL16: @@ -306,14 +308,25 @@ opr_emit_disassembly (const struct operand *opr, break; } if (mo->n_regs > 0) - (*info->fprintf_func) (info->stream, fmt, - registers[mo->regs[0]].name); + { + int r = mo->regs[0]; + + if (r < 0 || r >= S12Z_N_REGISTERS) + (*info->fprintf_func) (info->stream, fmt, _("")); + else + (*info->fprintf_func) (info->stream, fmt, registers[r].name); + } used_reg = 1; if (mo->n_regs > used_reg) { - (*info->fprintf_func) (info->stream, ",%s", - registers[mo->regs[used_reg]].name); + int r = mo->regs[used_reg]; + + if (r < 0 || r >= S12Z_N_REGISTERS) + (*info->fprintf_func) (info->stream, _("")); + else + (*info->fprintf_func) (info->stream, ",%s", + registers[r].name); } (*info->fprintf_func) (info->stream, "%c", @@ -323,7 +336,9 @@ opr_emit_disassembly (const struct operand *opr, }; } -static const char shift_size_table[] = { +#define S12Z_N_SIZES 4 +static const char shift_size_table[S12Z_N_SIZES] = +{ 'b', 'w', 'p', 'l' }; @@ -357,6 +372,7 @@ print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info) if (osize == -1) { bool suffix = false; + for (o = 0; o < n_operands; ++o) { if (operands[o] && operands[o]->osize != -1) @@ -366,18 +382,27 @@ print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info) (*mra.info->fprintf_func) (mra.info->stream, "%c", '.'); suffix = true; } - (*mra.info->fprintf_func) (mra.info->stream, "%c", - shift_size_table[operands[o]->osize]); + + osize = operands[o]->osize; + + if (osize < 0 || osize >= S12Z_N_SIZES) + (*mra.info->fprintf_func) (mra.info->stream, _("")); + else + (*mra.info->fprintf_func) (mra.info->stream, "%c", + shift_size_table[osize]); + } } } else { - (*mra.info->fprintf_func) (mra.info->stream, ".%c", - shift_size_table[osize]); + if (osize < 0 || osize >= S12Z_N_SIZES) + (*mra.info->fprintf_func) (mra.info->stream, _(".")); + else + (*mra.info->fprintf_func) (mra.info->stream, ".%c", + shift_size_table[osize]); } - /* Ship out the operands. */ for (o = 0; o < n_operands; ++o) { diff --git a/opcodes/s12z-opc.c b/opcodes/s12z-opc.c index eef097dfd4..e7a3577ef7 100644 --- a/opcodes/s12z-opc.c +++ b/opcodes/s12z-opc.c @@ -2205,8 +2205,16 @@ exg_sex_discrim (struct mem_read_abstraction_base *mra, enum optr hint ATTRIBUTE struct operand *op0 = create_register_operand ((eb & 0xf0) >> 4); struct operand *op1 = create_register_operand (eb & 0xf); - const struct reg *r0 = registers + ((struct register_operand *) op0)->reg; - const struct reg *r1 = registers + ((struct register_operand *) op1)->reg; + int reg0 = ((struct register_operand *) op0)->reg; + if (reg0 < 0 || reg0 >= S12Z_N_REGISTERS) + return OP_INVALID; + + int reg1 = ((struct register_operand *) op1)->reg; + if (reg1 < 0 || reg1 >= S12Z_N_REGISTERS) + return OP_INVALID; + + const struct reg *r0 = registers + reg0; + const struct reg *r1 = registers + reg1; enum optr operator = (r0->bytes < r1->bytes) ? OP_sex : OP_exg; -- 2.34.1