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.
This commit is contained in:
Nick Clifton
2019-09-03 09:53:25 +01:00
parent 6591bf0131
commit 1e4b5e7d35
2 changed files with 66 additions and 37 deletions

View File

@ -1,3 +1,13 @@
2019-09-03 Nick Clifton <nickc@redhat.com>
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 <srinath.parvathaneni@arm.com> 2019-08-27 Srinath Parvathaneni <srinath.parvathaneni@arm.com>
* arm-dis.c (mve_opcodes): Add entry for MVE_VMOV_VEC_TO_VEC. * arm-dis.c (mve_opcodes): Add entry for MVE_VMOV_VEC_TO_VEC.

View File

@ -54,15 +54,17 @@
#define INSN_IMMEDIATE_BIT (IMM_OFFSET_BIT << 24) #define INSN_IMMEDIATE_BIT (IMM_OFFSET_BIT << 24)
#define INSN_BACKWARD_OFFSET_BIT (1 << 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 struct mmix_dis_info
{ {
const char *reg_name[256]; const char *reg_name[MAX_REG_NAME_LEN];
const char *spec_reg_name[32]; const char *spec_reg_name[MAX_SPEC_REG_NAME_LEN];
/* Waste a little memory so we don't have to allocate each separately. /* 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 We could have an array with static contents for these, but on the
other hand, we don't have to. */ 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. */ /* 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++) for (i = 0; i < nsyms && syms[i] != NULL; i++)
{ {
if (syms[i]->section == reg_section 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] == NULL)
minfop->reg_name[syms[i]->value] = syms[i]->name; 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. */ /* 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) if (minfop->reg_name[i] == NULL)
{ {
sprintf (minfop->basic_reg_name[i], "$%ld", i); sprintf (minfop->basic_reg_name[i], "$%ld", i);
@ -238,6 +240,22 @@ get_opcode (unsigned long insn)
return NULL; 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. */ /* The main disassembly function. */
int int
@ -333,15 +351,15 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info)
case mmix_operands_regs: case mmix_operands_regs:
/* All registers: "$X,$Y,$Z". */ /* All registers: "$X,$Y,$Z". */
(*info->fprintf_func) (info->stream, "%s,%s,%s", (*info->fprintf_func) (info->stream, "%s,%s,%s",
minfop->reg_name[x], get_reg_name (minfop, x),
minfop->reg_name[y], get_reg_name (minfop, y),
minfop->reg_name[z]); get_reg_name (minfop, z));
break; break;
case mmix_operands_reg_yz: case mmix_operands_reg_yz:
/* Like SETH - "$X,YZ". */ /* Like SETH - "$X,YZ". */
(*info->fprintf_func) (info->stream, "%s,0x%x", (*info->fprintf_func) (info->stream, "%s,0x%x",
minfop->reg_name[x], y * 256 + z); get_reg_name (minfop, x), y * 256 + z);
break; break;
case mmix_operands_regs_z_opt: 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". */ /* The regular "$X,$Y,$Z|Z". */
if (insn & INSN_IMMEDIATE_BIT) if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%s,%s,%d", (*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 else
(*info->fprintf_func) (info->stream, "%s,%s,%s", (*info->fprintf_func) (info->stream, "%s,%s,%s",
minfop->reg_name[x], get_reg_name (minfop, x),
minfop->reg_name[y], get_reg_name (minfop, y),
minfop->reg_name[z]); get_reg_name (minfop, z));
break; break;
case mmix_operands_jmp: case mmix_operands_jmp:
@ -378,23 +397,23 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info)
{ {
if (insn & INSN_IMMEDIATE_BIT) if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%s,%s,%d", (*info->fprintf_func) (info->stream, "%s,%s,%d",
minfop->reg_name[x], get_reg_name (minfop, x),
ROUND_MODE (y), z); ROUND_MODE (y), z);
else else
(*info->fprintf_func) (info->stream, "%s,%s,%s", (*info->fprintf_func) (info->stream, "%s,%s,%s",
minfop->reg_name[x], get_reg_name (minfop, x),
ROUND_MODE (y), ROUND_MODE (y),
minfop->reg_name[z]); get_reg_name (minfop, z));
} }
else else
{ {
if (insn & INSN_IMMEDIATE_BIT) if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%s,%d", (*info->fprintf_func) (info->stream, "%s,%d",
minfop->reg_name[x], z); get_reg_name (minfop, x), z);
else else
(*info->fprintf_func) (info->stream, "%s,%s", (*info->fprintf_func) (info->stream, "%s,%s",
minfop->reg_name[x], get_reg_name (minfop, x),
minfop->reg_name[z]); get_reg_name (minfop, z));
} }
break; break;
@ -408,13 +427,13 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info)
"$X,ROUND_MODE,$Z". */ "$X,ROUND_MODE,$Z". */
if (y != 0) if (y != 0)
(*info->fprintf_func) (info->stream, "%s,%s,%s", (*info->fprintf_func) (info->stream, "%s,%s,%s",
minfop->reg_name[x], get_reg_name (minfop, x),
ROUND_MODE (y), ROUND_MODE (y),
minfop->reg_name[z]); get_reg_name (minfop, z));
else else
(*info->fprintf_func) (info->stream, "%s,%s", (*info->fprintf_func) (info->stream, "%s,%s",
minfop->reg_name[x], get_reg_name (minfop, x),
minfop->reg_name[z]); get_reg_name (minfop, z));
break; break;
case mmix_operands_sync: case mmix_operands_sync:
@ -427,22 +446,22 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info)
/* Like SYNCD - "X,$Y,$Z|Z". */ /* Like SYNCD - "X,$Y,$Z|Z". */
if (insn & INSN_IMMEDIATE_BIT) if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%d,%s,%d", (*info->fprintf_func) (info->stream, "%d,%s,%d",
x, minfop->reg_name[y], z); x, get_reg_name (minfop, y), z);
else else
(*info->fprintf_func) (info->stream, "%d,%s,%s", (*info->fprintf_func) (info->stream, "%d,%s,%s",
x, minfop->reg_name[y], x, get_reg_name (minfop, y),
minfop->reg_name[z]); get_reg_name (minfop, z));
break; break;
case mmix_operands_neg: case mmix_operands_neg:
/* Like NEG and NEGU - "$X,Y,$Z|Z". */ /* Like NEG and NEGU - "$X,Y,$Z|Z". */
if (insn & INSN_IMMEDIATE_BIT) if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%s,%d,%d", (*info->fprintf_func) (info->stream, "%s,%d,%d",
minfop->reg_name[x], y, z); get_reg_name (minfop, x), y, z);
else else
(*info->fprintf_func) (info->stream, "%s,%d,%s", (*info->fprintf_func) (info->stream, "%s,%d,%s",
minfop->reg_name[x], y, get_reg_name (minfop, x), y,
minfop->reg_name[z]); get_reg_name (minfop, z));
break; break;
case mmix_operands_pushj: case mmix_operands_pushj:
@ -456,7 +475,7 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info)
info->target = memaddr + offset; 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); (*info->print_address_func) (memaddr + offset, info);
} }
break; break;
@ -464,26 +483,26 @@ print_insn_mmix (bfd_vma memaddr, struct disassemble_info *info)
case mmix_operands_get: case mmix_operands_get:
/* GET - "X,spec_reg". */ /* GET - "X,spec_reg". */
(*info->fprintf_func) (info->stream, "%s,%s", (*info->fprintf_func) (info->stream, "%s,%s",
minfop->reg_name[x], get_reg_name (minfop, x),
minfop->spec_reg_name[z]); get_spec_reg_name (minfop, z));
break; break;
case mmix_operands_put: case mmix_operands_put:
/* PUT - "spec_reg,$Z|Z". */ /* PUT - "spec_reg,$Z|Z". */
if (insn & INSN_IMMEDIATE_BIT) if (insn & INSN_IMMEDIATE_BIT)
(*info->fprintf_func) (info->stream, "%s,%d", (*info->fprintf_func) (info->stream, "%s,%d",
minfop->spec_reg_name[x], z); get_spec_reg_name (minfop, x), z);
else else
(*info->fprintf_func) (info->stream, "%s,%s", (*info->fprintf_func) (info->stream, "%s,%s",
minfop->spec_reg_name[x], get_spec_reg_name (minfop, x),
minfop->reg_name[z]); get_reg_name (minfop, z));
break; break;
case mmix_operands_set: case mmix_operands_set:
/* Two registers, "$X,$Y". */ /* Two registers, "$X,$Y". */
(*info->fprintf_func) (info->stream, "%s,%s", (*info->fprintf_func) (info->stream, "%s,%s",
minfop->reg_name[x], get_reg_name (minfop, x),
minfop->reg_name[y]); get_reg_name (minfop, y));
break; break;
case mmix_operands_save: case mmix_operands_save: