diff --git a/librz/arch/isa/8051/8051_il.c b/librz/arch/isa/8051/8051_il.c index d678fd7d121..cccf828689f 100644 --- a/librz/arch/isa/8051/8051_il.c +++ b/librz/arch/isa/8051/8051_il.c @@ -559,7 +559,7 @@ RZ_IPI RzILOpEffect *rz_8051_il_op(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL c } RzILOpEffect *eff = i_op_dispatch(op); - free(op); + rz_8051_op_free(op); return eff; } diff --git a/librz/arch/isa/8051/8051_il.h b/librz/arch/isa/8051/8051_il.h index dfb72e9d63b..3c747e08260 100644 --- a/librz/arch/isa/8051/8051_il.h +++ b/librz/arch/isa/8051/8051_il.h @@ -194,6 +194,7 @@ typedef struct i8051_op_t { } I8051Op; RZ_IPI I8051Op *rz_8051_op_parse(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL const ut8 *buf, int len, ut64 pc); +RZ_IPI void rz_8051_op_free(I8051Op *op); RZ_IPI RzILOpEffect *rz_8051_il_op(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL const ut8 *buf, int len, ut64 pc); RZ_IPI RzAnalysisILConfig *rz_8051_il_config(RZ_NONNULL RzAnalysis *analysis); diff --git a/librz/arch/isa/8051/8051_parse.c b/librz/arch/isa/8051/8051_parse.c index c54384a5934..997651f4f80 100644 --- a/librz/arch/isa/8051/8051_parse.c +++ b/librz/arch/isa/8051/8051_parse.c @@ -191,6 +191,30 @@ static bool addressing_pattern2(I8051Op *op, const ut8 *buf) { return true; } +static void addressing_free(I8051OpAddressing *a) { + if (!a) { + return; + } + // Indirect addressing owns the nested addressing it points at. + if (a->mode == I8051_ADDRESSING_INDIRECT) { + addressing_free(a->d.indirect); + } + free(a); +} + +RZ_IPI void rz_8051_op_free(I8051Op *op) { + if (!op) { + return; + } + if (op->argv) { + for (size_t i = 0; i < op->argc; i++) { + addressing_free(op->argv[i]); + } + free(op->argv); + } + free(op); +} + RZ_IPI I8051Op *rz_8051_op_parse(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL const ut8 *buf, int len, ut64 pc) { rz_return_val_if_fail(analysis && buf && len > 0, NULL); I8051Op *op = RZ_NEW0(I8051Op); diff --git a/librz/arch/isa/sh/sh_il.c b/librz/arch/isa/sh/sh_il.c index ddcb90c0197..4c55bc017f8 100644 --- a/librz/arch/isa/sh/sh_il.c +++ b/librz/arch/isa/sh/sh_il.c @@ -476,7 +476,7 @@ static RzILOpEffect *sh_il_set_param_pc_ctx(SHParam param, RZ_OWN RzILOpPure *va if (!ret) { SHParamHelper ret_h = sh_il_get_param(param, scaling); - RZ_FREE(ret_h.pure); + rz_il_op_pure_free(ret_h.pure); RzILOpPure *eff_addr = sh_il_get_effective_addr(param, scaling); ret = STOREW(eff_addr, val); pre = ret_h.pre; diff --git a/librz/arch/pdb_process.c b/librz/arch/pdb_process.c index 1f1c219ecdf..3db0812f5b9 100644 --- a/librz/arch/pdb_process.c +++ b/librz/arch/pdb_process.c @@ -18,7 +18,7 @@ static void arglist_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbT static RzType *mfunction_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name); static RzType *onemethod_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info); static RzType *member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name, ut64 *bitfield_width); -static RzType *nest_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *t, char *name); +static RzType *nest_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *t); static RzType *union_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type); static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info); static RzType *class_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type); @@ -328,7 +328,7 @@ static RzTypeIdentifierKind iKind_from_bKind(RzBaseTypeKind k) { return RZ_TYPE_IDENTIFIER_KIND_UNSPECIFIED; } -static RzType *nest_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) { +static RzType *nest_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info) { rz_return_val_if_fail(type_info && stream && typedb, NULL); Tpi_LF_NestType *lf_nest = type_info->data; RzPdbTpiType *utpi = rz_bin_pdb_get_type_by_index(stream, lf_nest->index); @@ -342,12 +342,9 @@ static RzType *nest_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbT return type_new_identify(bt->name, iKind_from_bKind(bt->kind)); } } - - RzType *utype = pdb_type_parse(typedb, stream, utpi, NULL); - if (!utype) { - return NULL; - } - return rz_type_clone(utype); + // pdb_type_parse() already returns an owned type, so return it directly + // instead of cloning and leaking the original. + return pdb_type_parse(typedb, stream, utpi, NULL); } /** @@ -384,7 +381,7 @@ static RzTypeStructMember *class_member_parse( } case TpiKind_NESTTYPE: { name = rz_bin_pdb_get_type_name(t); - type = nest_parse(typedb, stream, t, rz_str_dup(name)); + type = nest_parse(typedb, stream, t); break; } case TpiKind_VBCLASS: @@ -572,7 +569,7 @@ static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStr } case TpiKind_NESTTYPE: { name = rz_bin_pdb_get_type_name(type_info); - type = nest_parse(typedb, stream, type_info, rz_str_dup(name)); + type = nest_parse(typedb, stream, type_info); break; } default: @@ -861,7 +858,11 @@ RZ_API void rz_type_db_pdb_load(const RzTypeDB *typedb, const RzPdb *pdb) { RzPdbTpiType *type; rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) { if (type && is_parsable_type(type)) { - rz_type_db_pdb_parse(typedb, stream, type); + // rz_type_db_pdb_parse() returns an owned clone of the parsed type. + // The base type itself is saved into the typedb during parsing, so + // this returned clone is not needed here and must be freed, otherwise + // one type tree leaks for every parsable type in the PDB. + rz_type_free(rz_type_db_pdb_parse(typedb, stream, type)); } } } diff --git a/librz/bin/pdb/gdata.c b/librz/bin/pdb/gdata.c index 17c0a6f9af4..84f0bf37b17 100644 --- a/librz/bin/pdb/gdata.c +++ b/librz/bin/pdb/gdata.c @@ -21,7 +21,9 @@ RZ_IPI bool gdata_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream) { PDBSymbolIter iter = { 0 }; PDBSymbolTable_iter(syms, &iter); - if (!PDBSymbolIter_collect(&iter, &s->global_symbols)) { + bool collected = PDBSymbolIter_collect(&iter, &s->global_symbols); + rz_buf_free(iter.b); + if (!collected) { goto err; } free(syms); diff --git a/librz/bin/pdb/symbol.c b/librz/bin/pdb/symbol.c index ee802f01ce8..c1d2ea677fc 100644 --- a/librz/bin/pdb/symbol.c +++ b/librz/bin/pdb/symbol.c @@ -128,8 +128,10 @@ RZ_IPI PDBSymbol *PDBSymbolTable_symbol_by_index(PDBSymbolTable *symbol_table, P map_err(symbol); map_err(PDBSymbolIter_next(&iter, symbol)); + rz_buf_free(iter.b); return symbol; err: + rz_buf_free(iter.b); free(symbol); return NULL; } diff --git a/librz/core/cmd/cmd_debug.c b/librz/core/cmd/cmd_debug.c index 1edd6e3a772..29b01e8a1b8 100644 --- a/librz/core/cmd/cmd_debug.c +++ b/librz/core/cmd/cmd_debug.c @@ -864,6 +864,14 @@ static bool get_bin_info(RzCore *core, const char *file, ut64 baseaddr, return false; } rz_core_bin_print(core, bf, action, filter, state, NULL); + // rz_bin_object_new() registers bf->sdb under core->bin->sdb ("cur" and + // "fd.") and takes an extra reference. Restoring the previous binfile + // below only updates bin->cur, so drop every reference to this temporary sdb + // here, otherwise it dangles in core->bin->sdb and is double-freed on teardown. + while (sdb_ns_unset(core->bin->sdb, NULL, bf->sdb)) { + ; + } + sdb_free(bf->sdb); rz_bin_file_delete(core->bin, bf); rz_bin_file_set_obj(obf, obf->o); rz_bin_set_cur_binfile(core->bin, obf);