From 1e4b5e7d354a41276cb8dfbaae79915e1730dbd8 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 3 Sep 2019 09:53:25 +0100 Subject: [PATCH] Fix a potential buffer overrun in the MMIX disassembler when processing a corrupt input file. PR 24958 * mmix-dis.c (MAX_REG_NAME_LEN): Define. (MAX_SPEC_REG_NAME_LEN): Define. (struct mmix_dis_info): Use defined constants for array lengths. (get_reg_name): New function. (get_sprec_reg_name): New function. (print_insn_mmix): Use new functions. --- opcodes/ChangeLog | 10 +++++ opcodes/mmix-dis.c | 93 ++++++++++++++++++++++++++++------------------ 2 files changed, 66 insertions(+), 37 deletions(-) diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index bec2b59cc40..87e3f74663d 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,13 @@ +2019-09-03 Nick Clifton + + PR 24958 + * mmix-dis.c (MAX_REG_NAME_LEN): Define. + (MAX_SPEC_REG_NAME_LEN): Define. + (struct mmix_dis_info): Use defined constants for array lengths. + (get_reg_name): New function. + (get_sprec_reg_name): New function. + (print_insn_mmix): Use new functions. + 2019-08-27 Srinath Parvathaneni * arm-dis.c (mve_opcodes): Add entry for MVE_VMOV_VEC_TO_VEC. diff --git a/opcodes/mmix-dis.c b/opcodes/mmix-dis.c index 80a58ed6eca..93688d3cb7b 100644 --- a/opcodes/mmix-dis.c +++ b/opcodes/mmix-dis.c @@ -54,15 +54,17 @@ #define INSN_IMMEDIATE_BIT (IMM_OFFSET_BIT << 24) #define INSN_BACKWARD_OFFSET_BIT (1 << 24) +#define MAX_REG_NAME_LEN 256 +#define MAX_SPEC_REG_NAME_LEN 32 struct mmix_dis_info { - const char *reg_name[256]; - const char *spec_reg_name[32]; + const char *reg_name[MAX_REG_NAME_LEN]; + const char *spec_reg_name[MAX_SPEC_REG_NAME_LEN]; /* Waste a little memory so we don't have to allocate each separately. We could have an array with static contents for these, but on the other hand, we don't have to. */ - char basic_reg_name[256][sizeof ("$255")]; + char basic_reg_name[MAX_REG_NAME_LEN][sizeof ("$255")]; }; /* Initialize a target-specific array in INFO. */ @@ -111,7 +113,7 @@ initialize_mmix_dis_info (struct disassemble_info *info) for (i = 0; i < nsyms && syms[i] != NULL; i++) { if (syms[i]->section == reg_section - && syms[i]->value < 256 + && syms[i]->value < MAX_REG_NAME_LEN && minfop->reg_name[syms[i]->value] == NULL) minfop->reg_name[syms[i]->value] = syms[i]->name; } @@ -119,7 +121,7 @@ initialize_mmix_dis_info (struct disassemble_info *info) } /* Fill in the rest with the canonical names. */ - for (i = 0; i < 256; i++) + for (i = 0; i < MAX_REG_NAME_LEN; i++) if (minfop->reg_name[i] == NULL) { sprintf (minfop->basic_reg_name[i], "$%ld", i); @@ -238,6 +240,22 @@ get_opcode (unsigned long insn) return NULL; } +static inline const char * +get_reg_name (const struct mmix_dis_info * minfop, unsigned int x) +{ + if (x >= MAX_REG_NAME_LEN) + return _("*illegal*"); + return minfop->reg_name[x]; +} + +static inline const char * +get_spec_reg_name (const struct mmix_dis_info * minfop, unsigned int x) +{ + if (x >= MAX_SPEC_REG_NAME_LEN) + return _("*illegal*"); + return minfop->spec_reg_name[x]; +} + /* The main disassembly function. */ int @@ -333,15 +351,15 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info) case mmix_operands_regs: /* All registers: "$X,$Y,$Z". */ (*info->fprintf_func) (info->stream, "%s,%s,%s", - minfop->reg_name[x], - minfop->reg_name[y], - minfop->reg_name[z]); + get_reg_name (minfop, x), + get_reg_name (minfop, y), + get_reg_name (minfop, z)); break; case mmix_operands_reg_yz: /* Like SETH - "$X,YZ". */ (*info->fprintf_func) (info->stream, "%s,0x%x", - minfop->reg_name[x], y * 256 + z); + get_reg_name (minfop, x), y * 256 + z); break; case mmix_operands_regs_z_opt: @@ -350,12 +368,13 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info) /* The regular "$X,$Y,$Z|Z". */ if (insn & INSN_IMMEDIATE_BIT) (*info->fprintf_func) (info->stream, "%s,%s,%d", - minfop->reg_name[x], minfop->reg_name[y], z); + get_reg_name (minfop, x), + get_reg_name (minfop, y), z); else (*info->fprintf_func) (info->stream, "%s,%s,%s", - minfop->reg_name[x], - minfop->reg_name[y], - minfop->reg_name[z]); + get_reg_name (minfop, x), + get_reg_name (minfop, y), + get_reg_name (minfop, z)); break; case mmix_operands_jmp: @@ -378,23 +397,23 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info) { if (insn & INSN_IMMEDIATE_BIT) (*info->fprintf_func) (info->stream, "%s,%s,%d", - minfop->reg_name[x], + get_reg_name (minfop, x), ROUND_MODE (y), z); else (*info->fprintf_func) (info->stream, "%s,%s,%s", - minfop->reg_name[x], + get_reg_name (minfop, x), ROUND_MODE (y), - minfop->reg_name[z]); + get_reg_name (minfop, z)); } else { if (insn & INSN_IMMEDIATE_BIT) (*info->fprintf_func) (info->stream, "%s,%d", - minfop->reg_name[x], z); + get_reg_name (minfop, x), z); else (*info->fprintf_func) (info->stream, "%s,%s", - minfop->reg_name[x], - minfop->reg_name[z]); + get_reg_name (minfop, x), + get_reg_name (minfop, z)); } break; @@ -408,13 +427,13 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info) "$X,ROUND_MODE,$Z". */ if (y != 0) (*info->fprintf_func) (info->stream, "%s,%s,%s", - minfop->reg_name[x], + get_reg_name (minfop, x), ROUND_MODE (y), - minfop->reg_name[z]); + get_reg_name (minfop, z)); else (*info->fprintf_func) (info->stream, "%s,%s", - minfop->reg_name[x], - minfop->reg_name[z]); + get_reg_name (minfop, x), + get_reg_name (minfop, z)); break; case mmix_operands_sync: @@ -427,22 +446,22 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info) /* Like SYNCD - "X,$Y,$Z|Z". */ if (insn & INSN_IMMEDIATE_BIT) (*info->fprintf_func) (info->stream, "%d,%s,%d", - x, minfop->reg_name[y], z); + x, get_reg_name (minfop, y), z); else (*info->fprintf_func) (info->stream, "%d,%s,%s", - x, minfop->reg_name[y], - minfop->reg_name[z]); + x, get_reg_name (minfop, y), + get_reg_name (minfop, z)); break; case mmix_operands_neg: /* Like NEG and NEGU - "$X,Y,$Z|Z". */ if (insn & INSN_IMMEDIATE_BIT) (*info->fprintf_func) (info->stream, "%s,%d,%d", - minfop->reg_name[x], y, z); + get_reg_name (minfop, x), y, z); else (*info->fprintf_func) (info->stream, "%s,%d,%s", - minfop->reg_name[x], y, - minfop->reg_name[z]); + get_reg_name (minfop, x), y, + get_reg_name (minfop, z)); break; case mmix_operands_pushj: @@ -456,7 +475,7 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info) info->target = memaddr + offset; - (*info->fprintf_func) (info->stream, "%s,", minfop->reg_name[x]); + (*info->fprintf_func) (info->stream, "%s,", get_reg_name (minfop, x)); (*info->print_address_func) (memaddr + offset, info); } break; @@ -464,26 +483,26 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info) case mmix_operands_get: /* GET - "X,spec_reg". */ (*info->fprintf_func) (info->stream, "%s,%s", - minfop->reg_name[x], - minfop->spec_reg_name[z]); + get_reg_name (minfop, x), + get_spec_reg_name (minfop, z)); break; case mmix_operands_put: /* PUT - "spec_reg,$Z|Z". */ if (insn & INSN_IMMEDIATE_BIT) (*info->fprintf_func) (info->stream, "%s,%d", - minfop->spec_reg_name[x], z); + get_spec_reg_name (minfop, x), z); else (*info->fprintf_func) (info->stream, "%s,%s", - minfop->spec_reg_name[x], - minfop->reg_name[z]); + get_spec_reg_name (minfop, x), + get_reg_name (minfop, z)); break; case mmix_operands_set: /* Two registers, "$X,$Y". */ (*info->fprintf_func) (info->stream, "%s,%s", - minfop->reg_name[x], - minfop->reg_name[y]); + get_reg_name (minfop, x), + get_reg_name (minfop, y)); break; case mmix_operands_save: -- 2.30.2