From 5103274ffc537711574f9611cb64c51fa9a65546 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 4 Nov 2019 12:02:20 +0000 Subject: [PATCH] Fix potential array overruns when disassembling corrupt v850 binaries. * v850-dis.c (get_v850_sreg_name): New function. Returns the name of a v850 system register. Move the v850_sreg_names array into this function. (get_v850_reg_name): Likewise for ordinary register names. (get_v850_vreg_name): Likewise for vector register names. (get_v850_cc_name): Likewise for condition codes. * get_v850_float_cc_name): Likewise for floating point condition codes. (get_v850_cacheop_name): Likewise for cache-ops. (get_v850_prefop_name): Likewise for pref-ops. (disassemble): Use the new accessor functions. --- opcodes/ChangeLog | 14 ++++ opcodes/v850-dis.c | 175 +++++++++++++++++++++++++++++---------------- 2 files changed, 129 insertions(+), 60 deletions(-) diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index d88aee324c2..19f52ffad7b 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,17 @@ +2019-11-04 Nick Clifton + + * v850-dis.c (get_v850_sreg_name): New function. Returns the name + of a v850 system register. Move the v850_sreg_names array into + this function. + (get_v850_reg_name): Likewise for ordinary register names. + (get_v850_vreg_name): Likewise for vector register names. + (get_v850_cc_name): Likewise for condition codes. + * get_v850_float_cc_name): Likewise for floating point condition + codes. + (get_v850_cacheop_name): Likewise for cache-ops. + (get_v850_prefop_name): Likewise for pref-ops. + (disassemble): Use the new accessor functions. + 2019-10-30 Delia Burduv * aarch64-opc.c (print_immediate_offset_address): Don't print the diff --git a/opcodes/v850-dis.c b/opcodes/v850-dis.c index 84cf2d39a6e..f8b5d1c93f2 100644 --- a/opcodes/v850-dis.c +++ b/opcodes/v850-dis.c @@ -25,53 +25,7 @@ #include "opcode/v850.h" #include "disassemble.h" #include "opintl.h" - -static const char *const v850_reg_names[] = -{ - "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" -}; - -static const char *const v850_sreg_names[] = -{ - "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid", - "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0", - "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau", - "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u", - "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l", - "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l", - "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u", - "fewr", "dbwr", "bsel" -}; - -static const char *const v850_cc_names[] = -{ - "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", - "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" -}; - -static const char *const v850_float_cc_names[] = -{ - "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt", - "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt" -}; - - -static const char *const v850_vreg_names[] = -{ - "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9", - "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18", - "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27", - "vr28", "vr29", "vr30", "vr31" -}; - -static const char *const v850_cacheop_names[] = -{ - "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd", - "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd" -}; +#include "libiberty.h" static const int v850_cacheop_codes[] = { @@ -79,9 +33,6 @@ static const int v850_cacheop_codes[] = 0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1 }; -static const char *const v850_prefop_names[] = -{ "prefi", "prefd" }; - static const int v850_prefop_codes[] = { 0x00, 0x04, -1}; @@ -217,6 +168,110 @@ get_operand_value (const struct v850_operand *operand, return value; } +static const char * +get_v850_sreg_name (unsigned int reg) +{ + static const char *const v850_sreg_names[] = + { + "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid", + "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0", + "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau", + "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u", + "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l", + "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l", + "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u", + "fewr", "dbwr", "bsel" + }; + + if (reg < ARRAY_SIZE (v850_sreg_names)) + return v850_sreg_names[reg]; + return _(""); +} + +static const char * +get_v850_reg_name (unsigned int reg) +{ + static const char *const v850_reg_names[] = + { + "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" + }; + + if (reg < ARRAY_SIZE (v850_reg_names)) + return v850_reg_names[reg]; + return _(""); +} + +static const char * +get_v850_vreg_name (unsigned int reg) +{ + static const char *const v850_vreg_names[] = + { + "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9", + "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18", + "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27", + "vr28", "vr29", "vr30", "vr31" + }; + + if (reg < ARRAY_SIZE (v850_vreg_names)) + return v850_vreg_names[reg]; + return _(""); +} + +static const char * +get_v850_cc_name (unsigned int reg) +{ + static const char *const v850_cc_names[] = + { + "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", + "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" + }; + + if (reg < ARRAY_SIZE (v850_cc_names)) + return v850_cc_names[reg]; + return _(""); +} + +static const char * +get_v850_float_cc_name (unsigned int reg) +{ + static const char *const v850_float_cc_names[] = + { + "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt", + "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt" + }; + + if (reg < ARRAY_SIZE (v850_float_cc_names)) + return v850_float_cc_names[reg]; + return _(""); +} + +static const char * +get_v850_cacheop_name (unsigned int reg) +{ + static const char *const v850_cacheop_names[] = + { + "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd", + "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd" + }; + + if (reg < ARRAY_SIZE (v850_cacheop_names)) + return v850_cacheop_names[reg]; + return _(""); +} + +static const char * +get_v850_prefop_name (unsigned int reg) +{ + static const char *const v850_prefop_names[] = + { "prefi", "prefd" }; + + if (reg < ARRAY_SIZE (v850_prefop_names)) + return v850_prefop_names[reg]; + return _(""); +} static int disassemble (bfd_vma memaddr, @@ -425,16 +480,16 @@ disassemble (bfd_vma memaddr, switch (flag) { case V850_OPERAND_REG: - info->fprintf_func (info->stream, "%s", v850_reg_names[value]); + info->fprintf_func (info->stream, "%s", get_v850_reg_name (value)); break; case (V850_OPERAND_REG|V850_REG_EVEN): - info->fprintf_func (info->stream, "%s", v850_reg_names[value * 2]); + info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2)); break; case V850_OPERAND_EP: info->fprintf_func (info->stream, "ep"); break; case V850_OPERAND_SRG: - info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); + info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value)); break; case V850E_OPERAND_REG_LIST: { @@ -496,7 +551,7 @@ disassemble (bfd_vma memaddr, else shown_one = 1; - info->fprintf_func (info->stream, "%s", v850_reg_names[first]); + info->fprintf_func (info->stream, "%s", get_v850_reg_name (first)); for (bit++; bit < 32; bit++) if ((mask & (1 << bit)) == 0) @@ -506,7 +561,7 @@ disassemble (bfd_vma memaddr, if (last > first + 1) { - info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]); + info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1)); } } } @@ -520,11 +575,11 @@ disassemble (bfd_vma memaddr, break; case V850_OPERAND_CC: - info->fprintf_func (info->stream, "%s", v850_cc_names[value]); + info->fprintf_func (info->stream, "%s", get_v850_cc_name (value)); break; case V850_OPERAND_FLOAT_CC: - info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); + info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value)); break; case V850_OPERAND_CACHEOP: @@ -536,7 +591,7 @@ disassemble (bfd_vma memaddr, if (value == v850_cacheop_codes[idx]) { info->fprintf_func (info->stream, "%s", - v850_cacheop_names[idx]); + get_v850_cacheop_name (idx)); goto MATCH_CACHEOP_CODE; } } @@ -554,7 +609,7 @@ disassemble (bfd_vma memaddr, if (value == v850_prefop_codes[idx]) { info->fprintf_func (info->stream, "%s", - v850_prefop_names[idx]); + get_v850_prefop_name (idx)); goto MATCH_PREFOP_CODE; } } @@ -564,7 +619,7 @@ disassemble (bfd_vma memaddr, break; case V850_OPERAND_VREG: - info->fprintf_func (info->stream, "%s", v850_vreg_names[value]); + info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value)); break; default: -- 2.30.2