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>
* 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_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: