This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Memory leak in binutils
- From: Alan Modra <amodra at gmail dot com>
- To: Philippe Antoine <p dot antoine at catenacyber dot fr>
- Cc: binutils at sourceware dot org, John Darrington <john at darrington dot wattle dot id dot au>
- Date: Sun, 8 Dec 2019 22:12:58 +1030
- Subject: Re: Memory leak in binutils
- References: <CAFaNJY-4B4HX-prU8Xh-0WiFQfQLy=2uMu0o8uxUEMB0_mZSCA@mail.gmail.com> <20191205062822.GO28726@bubble.grove.modra.org> <C07E8136-A11D-4A2D-9735-FEB028248760@catenacyber.fr> <20191206002314.GB32672@bubble.grove.modra.org> <04B576AA-37FA-4083-B197-CB6B092919BC@catenacyber.fr>
On Fri, Dec 06, 2019 at 08:56:14AM +0100, Philippe Antoine wrote:
> ==1==ERROR: LeakSanitizer: detected memory leaks
> Direct leak of 12 byte(s) in 1 object(s) allocated from:
> #0 0x49759d in malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
> #1 0x6c558d in create_register_operand_with_size /src/binutils-gdb/opcodes/s12z-opc.c:285:33
> #2 0x6c229b in exg_sex_discrim /src/binutils-gdb/opcodes/s12z-opc.c:2206:25
> #3 0x6bce95 in decode_operation /src/binutils-gdb/opcodes/s12z-opc.c:2663:10
> #4 0x6bcc81 in decode_s12z /src/binutils-gdb/opcodes/s12z-opc.c:2699:17
> #5 0x6baf08 in print_insn_s12z /src/binutils-gdb/opcodes/s12z-dis.c:365:5
> #6 0x4ca15d in LLVMFuzzerTestOneInput /src/binutils-gdb/fuzz/fuzz_disassemble.c:71:13
Easily fixed like so.
* s12z-opc.c (exg_sex_discrim): Don't leak memory on invalid
registers.
diff --git a/opcodes/s12z-opc.c b/opcodes/s12z-opc.c
index e7a3577ef7..475c9eb5f1 100644
--- a/opcodes/s12z-opc.c
+++ b/opcodes/s12z-opc.c
@@ -2195,32 +2195,32 @@ loop_prim_n_bytes (struct mem_read_abstraction_base *mra)
static enum optr
-exg_sex_discrim (struct mem_read_abstraction_base *mra, enum optr hint ATTRIBUTE_UNUSED)
+exg_sex_discrim (struct mem_read_abstraction_base *mra,
+ enum optr hint ATTRIBUTE_UNUSED)
{
uint8_t eb;
int status = mra->read (mra, 0, 1, &eb);
+ enum optr operator = OP_INVALID;
if (status < 0)
- return OP_INVALID;
+ return operator;
struct operand *op0 = create_register_operand ((eb & 0xf0) >> 4);
struct operand *op1 = create_register_operand (eb & 0xf);
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;
+ if (reg0 >= 0 && reg0 < S12Z_N_REGISTERS
+ && reg1 >= 0 && reg1 < S12Z_N_REGISTERS)
+ {
+ const struct reg *r0 = registers + reg0;
+ const struct reg *r1 = registers + reg1;
- enum optr operator = (r0->bytes < r1->bytes) ? OP_sex : OP_exg;
+ operator = r0->bytes < r1->bytes ? OP_sex : OP_exg;
+ }
free (op0);
free (op1);
-
+
return operator;
}
--
Alan Modra
Australia Development Lab, IBM