Fix a potential buffer overrun in the MMIX disassembler when processing a corrupt...
authorNick Clifton <nickc@redhat.com>
Tue, 3 Sep 2019 08:53:25 +0000 (09:53 +0100)
committerNick Clifton <nickc@redhat.com>
Tue, 3 Sep 2019 08:53:25 +0000 (09:53 +0100)
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
opcodes/mmix-dis.c

index bec2b59cc40d4d76eb17a52547bad8d873d90c14..87e3f74663d7b27641b88e613a83d8d5c513b26c 100644 (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.
index 80a58ed6eca5e4f324c32945ec120ce0d91da91c..93688d3cb7b14c074d6ec2e8dd5d5449fd64fab3 100644 (file)
 #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: