Fix memory leaks in arch and core (#6590)

Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
This commit is contained in:
NOT XVilka 2026-07-04 13:36:06 +08:00 committed by GitHub
parent 6249c2e5f2
commit 84b2f31035
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 52 additions and 14 deletions

View file

@ -559,7 +559,7 @@ RZ_IPI RzILOpEffect *rz_8051_il_op(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL c
} }
RzILOpEffect *eff = i_op_dispatch(op); RzILOpEffect *eff = i_op_dispatch(op);
free(op); rz_8051_op_free(op);
return eff; return eff;
} }

View file

@ -194,6 +194,7 @@ typedef struct i8051_op_t {
} I8051Op; } I8051Op;
RZ_IPI I8051Op *rz_8051_op_parse(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL const ut8 *buf, int len, ut64 pc); 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 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); RZ_IPI RzAnalysisILConfig *rz_8051_il_config(RZ_NONNULL RzAnalysis *analysis);

View file

@ -191,6 +191,30 @@ static bool addressing_pattern2(I8051Op *op, const ut8 *buf) {
return true; 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_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); rz_return_val_if_fail(analysis && buf && len > 0, NULL);
I8051Op *op = RZ_NEW0(I8051Op); I8051Op *op = RZ_NEW0(I8051Op);

View file

@ -476,7 +476,7 @@ static RzILOpEffect *sh_il_set_param_pc_ctx(SHParam param, RZ_OWN RzILOpPure *va
if (!ret) { if (!ret) {
SHParamHelper ret_h = sh_il_get_param(param, scaling); 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); RzILOpPure *eff_addr = sh_il_get_effective_addr(param, scaling);
ret = STOREW(eff_addr, val); ret = STOREW(eff_addr, val);
pre = ret_h.pre; pre = ret_h.pre;

View file

@ -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 *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 *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 *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 RzType *union_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info); static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info);
static RzType *class_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type); 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; 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); rz_return_val_if_fail(type_info && stream && typedb, NULL);
Tpi_LF_NestType *lf_nest = type_info->data; Tpi_LF_NestType *lf_nest = type_info->data;
RzPdbTpiType *utpi = rz_bin_pdb_get_type_by_index(stream, lf_nest->index); 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)); return type_new_identify(bt->name, iKind_from_bKind(bt->kind));
} }
} }
// pdb_type_parse() already returns an owned type, so return it directly
RzType *utype = pdb_type_parse(typedb, stream, utpi, NULL); // instead of cloning and leaking the original.
if (!utype) { return pdb_type_parse(typedb, stream, utpi, NULL);
return NULL;
}
return rz_type_clone(utype);
} }
/** /**
@ -384,7 +381,7 @@ static RzTypeStructMember *class_member_parse(
} }
case TpiKind_NESTTYPE: { case TpiKind_NESTTYPE: {
name = rz_bin_pdb_get_type_name(t); 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; break;
} }
case TpiKind_VBCLASS: case TpiKind_VBCLASS:
@ -572,7 +569,7 @@ static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStr
} }
case TpiKind_NESTTYPE: { case TpiKind_NESTTYPE: {
name = rz_bin_pdb_get_type_name(type_info); 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; break;
} }
default: default:
@ -861,7 +858,11 @@ RZ_API void rz_type_db_pdb_load(const RzTypeDB *typedb, const RzPdb *pdb) {
RzPdbTpiType *type; RzPdbTpiType *type;
rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) { rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) {
if (type && is_parsable_type(type)) { 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));
} }
} }
} }

View file

@ -21,7 +21,9 @@ RZ_IPI bool gdata_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream) {
PDBSymbolIter iter = { 0 }; PDBSymbolIter iter = { 0 };
PDBSymbolTable_iter(syms, &iter); 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; goto err;
} }
free(syms); free(syms);

View file

@ -128,8 +128,10 @@ RZ_IPI PDBSymbol *PDBSymbolTable_symbol_by_index(PDBSymbolTable *symbol_table, P
map_err(symbol); map_err(symbol);
map_err(PDBSymbolIter_next(&iter, symbol)); map_err(PDBSymbolIter_next(&iter, symbol));
rz_buf_free(iter.b);
return symbol; return symbol;
err: err:
rz_buf_free(iter.b);
free(symbol); free(symbol);
return NULL; return NULL;
} }

View file

@ -864,6 +864,14 @@ static bool get_bin_info(RzCore *core, const char *file, ut64 baseaddr,
return false; return false;
} }
rz_core_bin_print(core, bf, action, filter, state, NULL); rz_core_bin_print(core, bf, action, filter, state, NULL);
// rz_bin_object_new() registers bf->sdb under core->bin->sdb ("cur" and
// "fd.<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_delete(core->bin, bf);
rz_bin_file_set_obj(obf, obf->o); rz_bin_file_set_obj(obf, obf->o);
rz_bin_set_cur_binfile(core->bin, obf); rz_bin_set_cur_binfile(core->bin, obf);