summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2019-09-03 09:53:25 +0100
committerNick Clifton <nickc@redhat.com>2019-09-03 09:53:25 +0100
commit1e4b5e7d354a41276cb8dfbaae79915e1730dbd8 (patch)
tree160ea2d4f2e38d86148b1b01d9c49569aefe31cc
parent6591bf0131d1d1c8c0e4de59ca2dd739dda86ddd (diff)
downloadbinutils-gdb-1e4b5e7d354a41276cb8dfbaae79915e1730dbd8.tar.gz
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.
-rw-r--r--opcodes/ChangeLog10
-rw-r--r--opcodes/mmix-dis.c93
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 <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.
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: