librz/bin/pdb: fix memory leaks of PDB callable convention strings and orphaned callables (#6468)
Leak A - calling-convention string leaked Leak B - orphaned callables on duplicate names Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
This commit is contained in:
parent
fb99604963
commit
940292aaae
3 changed files with 38 additions and 11 deletions
|
|
@ -185,7 +185,21 @@ static RzType *procedure_parse(
|
|||
if (arglist) {
|
||||
arglist_parse(typedb, stream, arglist, typ->callable->args);
|
||||
}
|
||||
rz_type_func_save((RzTypeDB *)typedb, callable);
|
||||
if (!rz_type_func_save((RzTypeDB *)typedb, callable)) {
|
||||
// A callable with this name is already registered. PDB type graphs
|
||||
// frequently reference the same procedure type more than once, and
|
||||
// unnamed procedures get a deterministic name derived from their TPI
|
||||
// offset, so duplicates are expected. rz_type_func_save() does not take
|
||||
// ownership on failure, so reuse the already-stored callable and free
|
||||
// this one; otherwise it (and its whole subtree) would be leaked.
|
||||
RzCallable *existing = rz_type_func_get((RzTypeDB *)typedb, callable->name);
|
||||
rz_type_callable_free(callable);
|
||||
typ->callable = existing;
|
||||
if (!existing) {
|
||||
rz_type_free(typ);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return typ;
|
||||
}
|
||||
|
||||
|
|
@ -221,7 +235,18 @@ static RzType *mfunction_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, R
|
|||
if (arglist) {
|
||||
arglist_parse(typedb, stream, arglist, type->callable->args);
|
||||
}
|
||||
rz_type_func_save((RzTypeDB *)typedb, callable);
|
||||
if (!rz_type_func_save((RzTypeDB *)typedb, callable)) {
|
||||
// See procedure_parse(): rz_type_func_save() does not take ownership when
|
||||
// a callable of the same name already exists, so free this duplicate and
|
||||
// reuse the stored one to avoid leaking it together with its subtree.
|
||||
RzCallable *existing = rz_type_func_get((RzTypeDB *)typedb, callable->name);
|
||||
rz_type_callable_free(callable);
|
||||
type->callable = existing;
|
||||
if (!existing) {
|
||||
rz_type_free(type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,27 +34,29 @@ int tpi_type_node_cmp(const void *incoming, const RBNode *in_tree, void *user) {
|
|||
*
|
||||
* \param idx
|
||||
*/
|
||||
RZ_API RZ_OWN char *rz_bin_pdb_calling_convention_as_string(RZ_NONNULL RzPdbTpiCallingConvention idx) {
|
||||
RZ_API RZ_BORROW const char *rz_bin_pdb_calling_convention_as_string(RZ_NONNULL RzPdbTpiCallingConvention idx) {
|
||||
// The returned string is a static literal and must not be freed by the
|
||||
// caller. RzCallable.cc (where these are stored) is a borrowed pointer.
|
||||
switch (idx) {
|
||||
case NEAR_C:
|
||||
case FAR_C:
|
||||
return rz_str_dup("__cdecl");
|
||||
return "__cdecl";
|
||||
case NEAR_PASCAL:
|
||||
case FAR_PASCAL:
|
||||
return rz_str_dup("__pascal");
|
||||
return "__pascal";
|
||||
case NEAR_FAST:
|
||||
case FAR_FAST:
|
||||
return rz_str_dup("__fastcall");
|
||||
return "__fastcall";
|
||||
case NEAR_STD:
|
||||
case FAR_STD:
|
||||
return rz_str_dup("__stdcall");
|
||||
return "__stdcall";
|
||||
case NEAR_SYS:
|
||||
case FAR_SYS:
|
||||
return rz_str_dup("__syscall");
|
||||
return "__syscall";
|
||||
case THISCALL:
|
||||
return rz_str_dup("__thiscall");
|
||||
return "__thiscall";
|
||||
case NEAR_VEC:
|
||||
return rz_str_dup("__vectorcall");
|
||||
return "__vectorcall";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,7 +376,7 @@ RZ_API bool rz_pdb_all_symbols_foreach(
|
|||
|
||||
// TPI
|
||||
RZ_API RZ_BORROW RzPdbTpiType *rz_bin_pdb_get_type_by_index(RZ_NONNULL RzPdbTpiStream *stream, ut32 index);
|
||||
RZ_API RZ_OWN char *rz_bin_pdb_calling_convention_as_string(RZ_NONNULL RzPdbTpiCallingConvention idx);
|
||||
RZ_API RZ_BORROW const char *rz_bin_pdb_calling_convention_as_string(RZ_NONNULL RzPdbTpiCallingConvention idx);
|
||||
RZ_API bool rz_bin_pdb_type_is_fwdref(RZ_NONNULL RzPdbTpiType *t);
|
||||
RZ_API RZ_BORROW RzPVector /*<RzPdbTpiType *>*/ *rz_bin_pdb_get_type_members(RZ_NONNULL RzPdbTpiStream *stream, RzPdbTpiType *t);
|
||||
RZ_API RZ_BORROW char *rz_bin_pdb_get_type_name(RZ_NONNULL RzPdbTpiType *type);
|
||||
|
|
|
|||
Loading…
Reference in a new issue