From bbf9a0b5eef3599a1c6a7a3bea40da9f2c37df83 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 28 Oct 2019 16:15:34 +0000 Subject: [PATCH] Fix buffer overrun in TIC30 disassembler. * tic30-dis.c (OPERAND_BUFFER_LEN): Define. Use as length of operand buffer. Set value to 15 not 13. (get_register_operand): Use OPERAND_BUFFER_LEN. (get_indirect_operand): Likewise. (print_two_operand): Likewise. (print_three_operand): Likewise. (print_oar_insn): Likewise. --- opcodes/ChangeLog | 10 ++++++++++ opcodes/tic30-dis.c | 24 +++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index fe0f2402d7c..8489b407882 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,13 @@ +2019-10-28 Nick Clifton + + * tic30-dis.c (OPERAND_BUFFER_LEN): Define. Use as length of + operand buffer. Set value to 15 not 13. + (get_register_operand): Use OPERAND_BUFFER_LEN. + (get_indirect_operand): Likewise. + (print_two_operand): Likewise. + (print_three_operand): Likewise. + (print_oar_insn): Likewise. + 2019-10-28 Nick Clifton * ns32k-dis.c (bit_extract): Add sanitiy check of parameters. diff --git a/opcodes/tic30-dis.c b/opcodes/tic30-dis.c index 668c519df87..a28be8307f8 100644 --- a/opcodes/tic30-dis.c +++ b/opcodes/tic30-dis.c @@ -188,6 +188,8 @@ get_tic30_instruction (unsigned long insn_word, struct instruction *insn) return 1; } +#define OPERAND_BUFFER_LEN 15 + static int get_register_operand (unsigned char fragment, char *buffer) { @@ -199,7 +201,8 @@ get_register_operand (unsigned char fragment, char *buffer) { if ((fragment & 0x1F) == current_reg->opcode) { - strcpy (buffer, current_reg->name); + strncpy (buffer, current_reg->name, OPERAND_BUFFER_LEN); + buffer[OPERAND_BUFFER_LEN - 1] = 0; return 1; } } @@ -250,18 +253,25 @@ get_indirect_operand (unsigned short fragment, int bufcnt; len = strlen (current_ind->syntax); + for (i = 0, bufcnt = 0; i < len; i++, bufcnt++) { buffer[bufcnt] = current_ind->syntax[i]; + if (bufcnt > 0 + && bufcnt < OPERAND_BUFFER_LEN - 1 && buffer[bufcnt - 1] == 'a' && buffer[bufcnt] == 'r') buffer[++bufcnt] = arnum + '0'; - if (buffer[bufcnt] == '(' + + if (bufcnt < OPERAND_BUFFER_LEN - 1 + && buffer[bufcnt] == '(' && current_ind->displacement == DISP_REQUIRED) { - sprintf (&buffer[bufcnt + 1], "%u", disp); - bufcnt += strlen (&buffer[bufcnt + 1]); + snprintf (buffer + (bufcnt + 1), + OPERAND_BUFFER_LEN - (bufcnt + 1), + "%u", disp); + bufcnt += strlen (buffer + (bufcnt + 1)); } } buffer[bufcnt + 1] = '\0'; @@ -342,7 +352,7 @@ print_two_operand (disassemble_info *info, struct instruction *insn) { char name[12]; - char operand[2][13] = + char operand[2][OPERAND_BUFFER_LEN] = { {0}, {0} @@ -429,7 +439,7 @@ print_three_operand (disassemble_info *info, unsigned long insn_word, struct instruction *insn) { - char operand[3][13] = + char operand[3][OPERAND_BUFFER_LEN] = { {0}, {0}, @@ -475,7 +485,7 @@ print_par_insn (disassemble_info *info, { size_t i, len; char *name1, *name2; - char operand[2][3][13] = + char operand[2][3][OPERAND_BUFFER_LEN] = { { {0}, -- 2.30.2