Skip to content

Commit

Permalink
fix: DWARF memleaks (#3923)
Browse files Browse the repository at this point in the history
  • Loading branch information
imbillow authored Oct 14, 2023
1 parent 6df64db commit a974cbc
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 47 deletions.
18 changes: 13 additions & 5 deletions librz/analysis/dwarf_process.c
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,11 @@ static RZ_OWN RzType *type_parse_from_offset_internal(

RzType *copy = type ? rz_type_clone(type) : NULL;
if (copy && ht_up_insert(ctx->analysis->debug_info->type_by_offset, offset, copy)) {
RZ_LOG_DEBUG("Insert RzType [%s] into type_by_offset\n", rz_type_as_string(ctx->analysis->typedb, type));
#if RZ_BUILD_DEBUG
char *tstring = rz_type_as_string(ctx->analysis->typedb, type);
RZ_LOG_DEBUG("Insert RzType [%s] into type_by_offset\n", tstring);
free(tstring);
#endif
} else {
RZ_LOG_ERROR("Failed to insert RzType [0x%" PFMT64x "] into type_by_offset\n", offset);
rz_type_free(copy);
Expand Down Expand Up @@ -1022,8 +1026,8 @@ static RzType *type_parse_from_abstract_origin(Context *ctx, ut64 offset, char *
return NULL;
}
ut64 size = 0;
const char *name = NULL;
const char *linkname = NULL;
char *name = NULL;
char *linkname = NULL;
RzType *type = NULL;
const RzBinDwarfAttr *attr;
rz_vector_foreach(&die->attrs, attr) {
Expand All @@ -1042,12 +1046,15 @@ static RzType *type_parse_from_abstract_origin(Context *ctx, ut64 offset, char *
}
}
if (!type) {
return NULL;
goto beach;
}
const char *prefer_name = select_name(NULL, linkname, name, ctx->unit->language);
if (prefer_name && name_out) {
*name_out = rz_str_new(prefer_name);
}
beach:
free(name);
free(linkname);
return type;
}

Expand Down Expand Up @@ -1772,7 +1779,7 @@ RZ_API void rz_analysis_dwarf_process_info(const RzAnalysis *analysis, RzBinDWAR

static bool fixup_regoff_to_stackoff(RzAnalysis *a, RzAnalysisFunction *f,
RzAnalysisDwarfVariable *dw_var, const char *reg_name, RzAnalysisVar *var) {
if (!(dw_var->location->kind == RzBinDwarfLocationKind_REGISTER_OFFSET)) {
if (dw_var->location->kind != RzBinDwarfLocationKind_REGISTER_OFFSET) {
return false;
}
ut16 reg = dw_var->location->register_number;
Expand Down Expand Up @@ -1946,6 +1953,7 @@ static bool dwarf_integrate_function(void *user, const ut64 k, const void *value
if (callable) {
char *sig = rz_type_callable_as_string(analysis->typedb, callable);
rz_meta_set_string(analysis, RZ_META_TYPE_COMMENT, dw_fn->low_pc, sig);
free(sig);
}

if (dw_fn->prefer_name && !rz_str_startswith(dw_fn->prefer_name, "anonymous")) {
Expand Down
2 changes: 1 addition & 1 deletion librz/bin/dwarf/abbrev.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ static void htup_RzBinDwarfAbbrevTable_free(HtUPKv *kv) {

static void RzBinDwarfAbbrevs_fini(RzBinDwarfAbbrev *abbrevs) {
ht_up_free(abbrevs->tbl_by_offset);
rz_buf_free(abbrevs->reader->buffer);
RzBinEndianReader_free(abbrevs->reader);
}

static bool RzBinDwarfAbbrevs_init(RzBinDwarfAbbrev *abbrevs) {
Expand Down
2 changes: 1 addition & 1 deletion librz/bin/dwarf/addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ RZ_IPI void DebugAddr_free(RzBinDwarfAddr *self) {
if (!self) {
return;
}
rz_buf_free(self->reader->buffer);
RzBinEndianReader_free(self->reader);
free(self);
}

Expand Down
2 changes: 1 addition & 1 deletion librz/bin/dwarf/aranges.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ RZ_API void rz_bin_dwarf_aranges_free(RZ_OWN RZ_NULLABLE RzBinDwarfARanges *aran
return;
}
rz_list_free(aranges->list);
rz_buf_free(aranges->reader->buffer);
RzBinEndianReader_free(aranges->reader);
free(aranges);
}

Expand Down
3 changes: 3 additions & 0 deletions librz/bin/dwarf/attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ RZ_IPI void RzBinDwarfAttr_fini(RzBinDwarfAttr *attr) {
case RzBinDwarfAttr_Block:
RzBinDwarfBlock_fini(&attr->value.block);
break;
case RzBinDwarfAttr_String:
free(attr->value.string);
break;
default:
break;
};
Expand Down
15 changes: 9 additions & 6 deletions librz/bin/dwarf/endian_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,26 @@ RZ_IPI RzBuffer *get_section_buf(RzBinFile *binfile, RzBinSection *section) {
if (section->paddr >= binfile->size) {
return NULL;
}
RzBuffer *buffer = NULL;
ut64 len = RZ_MIN(section->size, binfile->size - section->paddr);
bool is_zlib_gnu = rz_str_startswith(section->name, ".zdebug");

ut8 *sh_buf = malloc(len);
if (!(sh_buf && (rz_buf_read_at(binfile->buf, section->paddr, sh_buf, len) == len))) {
goto err;
}

if (!(section->flags & SHF_COMPRESSED || is_zlib_gnu)) {
return rz_buf_new_slice(binfile->buf, section->paddr, len);
return rz_buf_new_with_pointers(sh_buf, len, true);
}

bool is_64bit = binfile->o->info->bits == 64;
ut64 Chdr_size = is_zlib_gnu ? sizeof(Chdr_GNU) : (is_64bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr));
if (len < Chdr_size) {
RZ_LOG_ERROR("corrupted compressed section header\n");
return NULL;
}
RzBuffer *buffer = NULL;
ut8 *sh_buf = malloc(len);
if (!(sh_buf && (rz_buf_read_at(binfile->buf, section->paddr, sh_buf, len) == len))) {
goto err;
}

bool bigendian = bf_bigendian(binfile);
ut32 ch_type = is_zlib_gnu ? ELFCOMPRESS_ZLIB
: rz_read_at_ble32(sh_buf, 0, bigendian);
Expand Down
1 change: 1 addition & 0 deletions librz/bin/dwarf/line.c
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,7 @@ RZ_API void rz_bin_dwarf_line_free(RZ_OWN RZ_NULLABLE RzBinDwarfLine *li) {
if (!li) {
return;
}
RzBinEndianReader_free(li->reader);
rz_list_free(li->units);
rz_bin_source_line_info_free(li->lines);
free(li);
Expand Down
2 changes: 2 additions & 0 deletions librz/bin/dwarf/loclists.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ RZ_API RZ_OWN RzBinDwarfLocLists *rz_bin_dwarf_loclists_new_from_file(RZ_BORROW
RzBinEndianReader *loclists = RzBinEndianReader_from_file(bf, ".debug_loclists");
RzBinEndianReader *loc = RzBinEndianReader_from_file(bf, ".debug_loc");
if (!(loclists || loc)) {
RzBinEndianReader_free(loclists);
RzBinEndianReader_free(loc);
return NULL;
}
return rz_bin_dwarf_loclists_new(loclists, loc);
Expand Down
65 changes: 33 additions & 32 deletions librz/bin/dwarf/op.c
Original file line number Diff line number Diff line change
Expand Up @@ -1269,18 +1269,17 @@ RZ_API bool rz_bin_dwarf_evaluation_evaluate(RZ_BORROW RZ_NONNULL RzBinDwarfEval
self->state.kind = EVALUATION_STATE_ERROR;
goto err;
}
Location *location = RZ_NEW0(RzBinDwarfLocation);
ERR_IF_FAIL(location);
RzBinDwarfPiece piece = {
.location = location,
.location = RZ_NEW0(RzBinDwarfLocation),
.has_size_in_bits = true,
.size_in_bits = operation.piece.size_in_bits,
.has_bit_offset = operation.piece.has_bit_offset,
.bit_offset = operation.piece.bit_offset,
};
ERR_IF_FAIL(piece.location);
OK_OR_ERR(RzBinDwarfLocation_move(&op_result.complete, piece.location) &&
rz_vector_push(&self->result, &piece),
rz_bin_dwarf_location_free(location));
rz_bin_dwarf_location_free(piece.location));
}
break;
}
Expand Down Expand Up @@ -1342,31 +1341,38 @@ RZ_API RZ_BORROW RzVector /*<RzBinDwarfPiece>*/ *rz_bin_dwarf_evaluation_result(
}

static bool RzBinDwarfEvaluationResult_to_loc(
RzBinDwarfEvaluation *eval, RzBinDwarfEvaluationResult *result, Location *loc) {
rz_return_val_if_fail(loc, false);
if (eval->state.kind == EVALUATION_STATE_COMPLETE && result->kind == EvaluationResult_COMPLETE) {
RzVector *pieces = rz_bin_dwarf_evaluation_result(eval);
if (!pieces || rz_vector_empty(pieces)) {
return false;
}
if (rz_vector_len(pieces) == 1) {
RzBinDwarfPiece *piece = rz_vector_index_ptr(pieces, 0);
OK_OR(RzBinDwarfLocation_move(piece->location, loc), return false);
} else {
loc->kind = RzBinDwarfLocationKind_COMPOSITE;
loc->composite = rz_vector_clone(pieces);
RzBinDwarfPiece *piece = NULL;
rz_vector_foreach(pieces, piece) {
piece->location = NULL;
}
}
RzBinDwarfEvaluation *eval, RzBinDwarfEvaluationResult *eval_result, Location *loc) {
rz_warn_if_fail(loc);
if (eval->state.kind != EVALUATION_STATE_COMPLETE || eval_result->kind != EvaluationResult_COMPLETE) {
loc->kind = RzBinDwarfLocationKind_EVALUATION_WAITING;
loc->eval_waiting.eval = eval;
loc->eval_waiting.result = eval_result;
return true;
}

loc->kind = RzBinDwarfLocationKind_EVALUATION_WAITING;
loc->eval_waiting.eval = eval;
loc->eval_waiting.result = result;
return true;
bool result = false;
RzVector *pieces = rz_bin_dwarf_evaluation_result(eval);
if (!pieces || rz_vector_empty(pieces)) {
goto beach;
}
if (rz_vector_len(pieces) == 1) {
RzBinDwarfPiece *piece = rz_vector_index_ptr(pieces, 0);
result = piece && RzBinDwarfLocation_move(piece->location, loc);
goto beach;
} else {
loc->kind = RzBinDwarfLocationKind_COMPOSITE;
loc->composite = rz_vector_clone(pieces);
RzBinDwarfPiece *piece = NULL;
rz_vector_foreach(pieces, piece) {
piece->location = NULL;
}
result = true;
goto beach;
}
beach:
rz_bin_dwarf_evaluation_free(eval);
RzBinDwarfEvaluationResult_free(eval_result);
return result;
}

/**
Expand All @@ -1391,20 +1397,15 @@ RZ_API RZ_OWN RzBinDwarfLocation *rz_bin_dwarf_location_from_block(
ERR_IF_FAIL(eval);
ERR_IF_FAIL(rz_bin_dwarf_evaluation_evaluate(eval, result) &&
RzBinDwarfEvaluationResult_to_loc(eval, result, loc));
ok:
return loc;
err:
if (eval && eval->state.kind == EVALUATION_STATE_DECODE_ERROR) {
loc->kind = RzBinDwarfLocationKind_DECODE_ERROR;
goto cleanup;
} else {
rz_bin_dwarf_location_free(loc);
loc = NULL;
}
cleanup:
rz_bin_dwarf_evaluation_free(eval);
RzBinDwarfEvaluationResult_free(result);
goto ok;
return loc;
}

static void Operation_dump(Operation *op, RzStrBuf *buf) {
Expand Down
4 changes: 4 additions & 0 deletions librz/bin/dwarf/rnglists.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ RZ_IPI void DebugRngLists_free(RzBinDwarfRngLists *self) {
return;
}

RzBinEndianReader_free(self->ranges);
RzBinEndianReader_free(self->rnglists);
ht_up_free(self->rnglist_by_offset);
free(self);
}
Expand Down Expand Up @@ -290,6 +292,8 @@ RZ_API RZ_OWN RzBinDwarfRngLists *rz_bin_dwarf_rnglists_new_from_file(
RzBinEndianReader *rnglists = RzBinEndianReader_from_file(bf, ".debug_rnglists");
RzBinEndianReader *ranges = RzBinEndianReader_from_file(bf, ".debug_ranges");
if (!(rnglists || ranges)) {
RzBinEndianReader_free(rnglists);
RzBinEndianReader_free(ranges);
return NULL;
}
return rz_bin_dwarf_rnglists_new(rnglists, ranges);
Expand Down
6 changes: 5 additions & 1 deletion librz/bin/dwarf/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ static void CU_fini(RzBinDwarfCompUnit *unit, void *user) {
return;
}
rz_vector_fini(&unit->dies);
free(unit->comp_dir);
free(unit->dwo_name);
free(unit->name);
free(unit->producer);
}

static inline ut64 CU_next(RzBinDwarfCompUnit *unit) {
Expand Down Expand Up @@ -309,11 +313,11 @@ static inline void info_free(RzBinDwarfInfo *info) {
if (!info) {
return;
}
RzBinEndianReader_free(info->reader);
rz_vector_fini(&info->units);
ht_up_free(info->offset_comp_dir);
ht_up_free(info->die_by_offset);
ht_up_free(info->unit_by_offset);
rz_buf_free(info->reader->buffer);
free(info);
}

Expand Down

0 comments on commit a974cbc

Please sign in to comment.