Fix array overruns in the S12Z disassembler.
authorNick Clifton <nickc@redhat.com>
Tue, 29 Oct 2019 09:17:39 +0000 (09:17 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 29 Oct 2019 09:17:39 +0000 (09:17 +0000)
* s12z-dis.c (opr_emit_disassembly): Check for illegal register
values.
(shift_size_table): Use a fixed size defined as S12Z_N_SIZES.
(print_insn_s12z):  Check for illegal size values.

opcodes/ChangeLog
opcodes/s12z-dis.c
opcodes/s12z-opc.c

index 5f5a6c869b1b1fece7ee768edd8496871bc3533b..d83b5bab853ee25c01267d7b9eea3defe4febee9 100644 (file)
@@ -1,3 +1,10 @@
+2019-10-29  Nick Clifton  <nickc@redhat.com>
+
+       * s12z-dis.c (opr_emit_disassembly): Check for illegal register
+       values.
+       (shift_size_table): Use a fixed size defined as S12Z_N_SIZES.
+       (print_insn_s12z):  Check for illegal size values.
+
 2019-10-28  Nick Clifton  <nickc@redhat.com>
 
        * csky-dis.c (csky_chars_to_number): Check for a negative
index 6086f1635da2dd61969f40d64f5ddb65c8acc354..5930ab4ef6698b42d2ffd2f5ccd90c8f9270d0e6 100644 (file)
 #include <assert.h>
 
 #include "opcode/s12z.h"
-
 #include "bfd.h"
 #include "dis-asm.h"
-
 #include "disassemble.h"
-
 #include "s12z-opc.h"
+#include "opintl.h"
 
 struct mem_read_abstraction
 {
@@ -255,7 +253,11 @@ opr_emit_disassembly (const struct operand *opr,
     case OPND_CL_REGISTER:
       {
         int r = ((struct register_operand*) opr)->reg;
-       (*info->fprintf_func) (info->stream, "%s", registers[r].name);
+
+       if (r < 0 || r >= S12Z_N_REGISTERS)
+         (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
+       else
+         (*info->fprintf_func) (info->stream, "%s", registers[r].name);
       }
       break;
     case OPND_CL_REGISTER_ALL16:
@@ -306,14 +308,25 @@ opr_emit_disassembly (const struct operand *opr,
            break;
          }
        if (mo->n_regs > 0)
-         (*info->fprintf_func) (info->stream, fmt,
-                                registers[mo->regs[0]].name);
+         {
+           int r = mo->regs[0];
+
+           if (r < 0 || r >= S12Z_N_REGISTERS)
+             (*info->fprintf_func) (info->stream, fmt, _("<illegal reg num>"));
+           else
+             (*info->fprintf_func) (info->stream, fmt, registers[r].name);
+         }
        used_reg = 1;
 
         if (mo->n_regs > used_reg)
           {
-            (*info->fprintf_func) (info->stream, ",%s",
-                                  registers[mo->regs[used_reg]].name);
+           int r = mo->regs[used_reg];
+
+           if (r < 0 || r >= S12Z_N_REGISTERS)
+             (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
+           else
+             (*info->fprintf_func) (info->stream, ",%s",
+                                    registers[r].name);
           }
 
        (*info->fprintf_func) (info->stream, "%c",
@@ -323,7 +336,9 @@ opr_emit_disassembly (const struct operand *opr,
     };
 }
 
-static const char shift_size_table[] = {
+#define S12Z_N_SIZES 4
+static const char shift_size_table[S12Z_N_SIZES] =
+{
   'b', 'w', 'p', 'l'
 };
 
@@ -357,6 +372,7 @@ print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
   if (osize == -1)
     {
       bool suffix = false;
+
       for (o = 0; o < n_operands; ++o)
        {
          if (operands[o] && operands[o]->osize != -1)
@@ -366,18 +382,27 @@ print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
                  (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
                  suffix = true;
                }
-             (*mra.info->fprintf_func) (mra.info->stream, "%c",
-                                    shift_size_table[operands[o]->osize]);
+
+             osize = operands[o]->osize;
+
+             if (osize < 0 || osize >= S12Z_N_SIZES)
+               (*mra.info->fprintf_func) (mra.info->stream, _("<bad>"));
+             else
+               (*mra.info->fprintf_func) (mra.info->stream, "%c",
+                                          shift_size_table[osize]);
+               
            }
        }
     }
   else
     {
-      (*mra.info->fprintf_func) (mra.info->stream, ".%c",
-                            shift_size_table[osize]);
+      if (osize < 0 || osize >= S12Z_N_SIZES)
+       (*mra.info->fprintf_func) (mra.info->stream, _(".<bad>"));
+      else
+       (*mra.info->fprintf_func) (mra.info->stream, ".%c",
+                                  shift_size_table[osize]);
     }
 
-
   /* Ship out the operands.  */
   for (o = 0; o < n_operands; ++o)
     {
index eef097dfd48667d1add51d9a0137a294d3d2bfe4..e7a3577ef7d5e70aaeaaf7268ea30d9f79a3e3bc 100644 (file)
@@ -2205,8 +2205,16 @@ exg_sex_discrim (struct mem_read_abstraction_base *mra, enum optr hint ATTRIBUTE
   struct operand *op0 = create_register_operand ((eb & 0xf0) >> 4);
   struct operand *op1 = create_register_operand (eb & 0xf);
 
-  const struct reg *r0 = registers + ((struct register_operand *) op0)->reg;
-  const struct reg *r1 = registers + ((struct register_operand *) op1)->reg;
+  int reg0 = ((struct register_operand *) op0)->reg;
+  if (reg0 < 0 || reg0 >= S12Z_N_REGISTERS)
+    return OP_INVALID;
+
+  int reg1 = ((struct register_operand *) op1)->reg;
+  if (reg1 < 0 || reg1 >= S12Z_N_REGISTERS)
+    return OP_INVALID;
+
+  const struct reg *r0 = registers + reg0;
+  const struct reg *r1 = registers + reg1;
 
   enum optr operator = (r0->bytes < r1->bytes) ? OP_sex : OP_exg;