Fix memleaks in librz/type/* (#1364)

* Fix memleaks in librz/type/*
* Use `goto fail` pattern

Co-authored-by: Paul I <pelijah@users.noreply.github.com>
This commit is contained in:
Anton Kochkov 2021-07-28 16:17:53 +08:00 committed by GitHub
parent 56841703e1
commit d5bac21207
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 44 deletions

View file

@ -372,7 +372,9 @@ RZ_API RZ_OWN RzType *rz_type_parse_string_single(RzTypeParser *parser, const ch
ts_tree_delete(tree);
ts_parser_delete(tsparser);
free(patched_code);
return tpair ? tpair->type : NULL;
RzType *ret = tpair ? tpair->type : NULL;
free(tpair);
return ret;
}
/**

View file

@ -197,9 +197,14 @@ int parse_sole_type_name(CParserState *state, TSNode node, const char *text, Par
// Do allow forward-looking definitions we just add the type into the forward hashtable
if (c_parser_forward_definition_store(state, real_type)) {
parser_debug(state, "Added forward definition of type: \"%s\"\n", real_type);
rz_type_base_type_free((*tpair)->btype);
(*tpair)->btype = NULL;
free(real_type);
return 0;
}
rz_type_free((*tpair)->type);
rz_type_base_type_free((*tpair)->btype);
RZ_FREE(*tpair);
free(real_type);
return -1;
}
@ -298,8 +303,9 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
node_malformed_error(state, node, text, "struct");
return -1;
}
int result = 0;
// Name is optional, in abstract definitions or as the member of nested types
const char *name = NULL;
char *name = NULL;
TSNode struct_name = ts_node_child_by_field_name(node, "name", 4);
if (ts_node_is_null(struct_name)) {
parser_debug(state, "Anonymous struct\n");
@ -328,19 +334,21 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
parser_debug(state, "Structure \"%s\" was forward-defined before\n", name);
if (!(*tpair = c_parser_new_structure_naked_type(state, name))) {
parser_error(state, "Cannot create \"%s\" naked structure type in the context\n", name);
return -1;
result = -1;
goto rexit;
}
return 0;
goto rexit;
}
// We still could create the "forward looking struct declaration"
// The parser then can augment the definition
if (!(*tpair = c_parser_new_structure_forward_definition(state, name))) {
parser_error(state, "Cannot create \"%s\" forward structure definition in the context\n", name);
return -1;
result = -1;
goto rexit;
}
return 0;
goto rexit;
} else {
return 0;
goto rexit;
}
}
@ -356,7 +364,8 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
ParserTypePair *struct_pair = c_parser_new_structure_type(state, name, body_child_count);
if (!struct_pair) {
parser_error(state, "Error forming RzType and RzBaseType pair out of struct: \"%s\"\n", name);
return -1;
result = -1;
goto rexit;
}
int i;
for (i = 0; i < body_child_count; i++) {
@ -370,7 +379,8 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
TSNode first_leaf = ts_node_named_child(child, 0);
if (ts_node_is_null(first_leaf)) {
node_malformed_error(state, child, text, "field_declaration");
return -1;
result = -1;
goto rexit;
}
const char *leaf_type = ts_node_type(first_leaf);
// If we have type qualifier in this position it is related to
@ -389,7 +399,8 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
if (strcmp(node_type, "field_declaration")) {
parser_error(state, "ERROR: Struct field AST should contain (field_declaration) node!\n");
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
// Every field node should have at least type and declarator:
@ -398,7 +409,8 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
if (ts_node_is_null(field_type) || ts_node_is_null(field_declarator)) {
parser_error(state, "ERROR: Struct field AST shoudl contain type and declarator items");
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
// Every field can be:
// - atomic: "int a;" or "char b[20]"
@ -424,29 +436,34 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
if (strcmp(ts_node_type(field_type), "primitive_type")) {
parser_error(state, "ERROR: Struct bitfield cannot contain non-primitive bitfield!\n");
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
const char *real_type = ts_node_sub_string(field_type, text);
if (!real_type) {
parser_error(state, "ERROR: Struct bitfield type should not be NULL!\n");
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
const char *real_identifier = ts_node_sub_string(field_declarator, text);
if (!real_identifier) {
parser_error(state, "ERROR: Struct bitfield identifier should not be NULL!\n");
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
if (ts_node_named_child_count(bitfield_clause) != 1) {
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
TSNode field_bits = ts_node_named_child(bitfield_clause, 0);
if (ts_node_is_null(field_bits)) {
parser_error(state, "ERROR: Struct bitfield bits AST node should not be NULL!\n");
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
const char *bits_str = ts_node_sub_string(field_bits, text);
int bits = rz_num_get(NULL, bits_str);
@ -455,14 +472,16 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
if (parse_type_node_single(state, field_type, text, &membtpair, is_const)) {
parser_error(state, "ERROR: parsing bitfield struct member identifier\n");
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
// Then we augment resulting type field with the data from parsed declarator
char *membname = NULL;
if (parse_type_declarator_node(state, field_declarator, text, &membtpair, &membname)) {
parser_error(state, "ERROR: parsing bitfield struct member declarator\n");
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
// Add a struct member
RzVector *members = &struct_pair->btype->struct_data.members;
@ -475,7 +494,8 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
void *element = rz_vector_push(members, &memb); // returns null if no space available
if (!element) {
parser_error(state, "Error appending bitfield struct member to the base type\n");
return -1;
result = -1;
goto rexit;
}
} else {
// 2nd case, normal structure
@ -485,13 +505,15 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
if (!real_type) {
parser_error(state, "ERROR: Struct field type should not be NULL!\n");
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
char *real_identifier = ts_node_sub_string(field_declarator, text);
if (!real_identifier) {
parser_error(state, "ERROR: Struct declarator should not be NULL!\n");
node_malformed_error(state, child, text, "struct field");
return -1;
result = -1;
goto rexit;
}
parser_debug(state, "field type: %s field_declarator: %s\n", real_type, real_identifier);
ParserTypePair *membtpair = NULL;
@ -501,7 +523,8 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
node_malformed_error(state, child, text, "struct field");
free(real_identifier);
free(real_type);
return -1;
result = -1;
goto rexit;
}
// Then we augment resulting type field with the data from parsed declarator
char *membname = NULL;
@ -510,7 +533,8 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
node_malformed_error(state, child, text, "struct field");
free(real_identifier);
free(real_type);
return -1;
result = -1;
goto rexit;
}
// Add a struct member
RzVector *members = &struct_pair->btype->struct_data.members;
@ -525,7 +549,8 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
parser_error(state, "Error appending struct member to the base type\n");
free(real_identifier);
free(real_type);
return -1;
result = -1;
goto rexit;
}
parser_debug(state, "Appended member \"%s\" into struct \"%s\"\n", membname, name);
free(real_identifier);
@ -541,7 +566,9 @@ int parse_struct_node(CParserState *state, TSNode node, const char *text, Parser
}
}
*tpair = struct_pair;
return 0;
rexit:
free(name);
return result;
}
// Parses the union definitions - concrete or an abstract ones
@ -817,8 +844,9 @@ int parse_enum_node(CParserState *state, TSNode node, const char *text, ParserTy
node_malformed_error(state, node, text, "enum");
return -1;
}
int result = 0;
// Name is optional, in abstract definitions or as the member of nested types
const char *name = NULL;
char *name = NULL;
TSNode enum_name = ts_node_child_by_field_name(node, "name", 4);
if (ts_node_is_null(enum_name)) {
parser_debug(state, "Anonymous enum\n");
@ -847,19 +875,21 @@ int parse_enum_node(CParserState *state, TSNode node, const char *text, ParserTy
parser_debug(state, "Enum \"%s\" was forward-defined before\n", name);
if (!(*tpair = c_parser_new_enum_naked_type(state, name))) {
parser_error(state, "Cannot create \"%s\" naked enum type in the context\n", name);
return -1;
result = -1;
goto rexit;
}
return 0;
goto rexit;
}
// We still could create the "forward looking enum declaration"
// The parser then can augment the definition
if (!(*tpair = c_parser_new_enum_forward_definition(state, name))) {
parser_error(state, "Cannot create \"%s\" forward enum definition in the context\n", name);
return -1;
result = -1;
goto rexit;
}
return 0;
goto rexit;
} else {
return 0;
goto rexit;
}
}
@ -870,7 +900,8 @@ int parse_enum_node(CParserState *state, TSNode node, const char *text, ParserTy
ParserTypePair *enum_pair = c_parser_new_enum_type(state, name, body_child_count);
if (!enum_pair) {
parser_error(state, "Error forming RzType and RzBaseType pair out of enum\n");
return -1;
result = -1;
goto rexit;
}
// Then we process all enumeration cases and add one by one
int i;
@ -882,14 +913,16 @@ int parse_enum_node(CParserState *state, TSNode node, const char *text, ParserTy
if (strcmp(node_type, "enumerator")) {
parser_error(state, "ERROR: Enum member AST should contain (enumerator) node!\n");
node_malformed_error(state, child, text, "enum field");
return -1;
result = -1;
goto rexit;
}
// Every member node should have at least 1 child!
int member_child_count = ts_node_named_child_count(child);
if (member_child_count < 1 || member_child_count > 2) {
parser_error(state, "ERROR: enum member AST cannot contain less than 1 or more than 2 items");
node_malformed_error(state, child, text, "enum field");
return -1;
result = -1;
goto rexit;
}
// Every member can be:
// - empty
@ -910,7 +943,8 @@ int parse_enum_node(CParserState *state, TSNode node, const char *text, ParserTy
if (ts_node_is_null(member_identifier)) {
parser_error(state, "ERROR: Enum case identifier should not be NULL!\n");
node_malformed_error(state, child, text, "enum case");
return -1;
result = -1;
goto rexit;
}
char *real_identifier = ts_node_sub_string(member_identifier, text);
parser_debug(state, "enum member: %s\n", real_identifier);
@ -922,7 +956,8 @@ int parse_enum_node(CParserState *state, TSNode node, const char *text, ParserTy
if (ts_node_is_null(member_identifier) || ts_node_is_null(member_value)) {
parser_error(state, "ERROR: Enum case identifier and value should not be NULL!\n");
node_malformed_error(state, child, text, "enum case");
return -1;
result = -1;
goto rexit;
}
char *real_identifier = ts_node_sub_string(member_identifier, text);
char *real_value = ts_node_sub_string(member_value, text);
@ -939,7 +974,8 @@ int parse_enum_node(CParserState *state, TSNode node, const char *text, ParserTy
if (!element) {
parser_error(state, "Error appending enum case to the base type\n");
free(cas.name);
return -1;
result = -1;
goto rexit;
}
}
}
@ -952,7 +988,9 @@ int parse_enum_node(CParserState *state, TSNode node, const char *text, ParserTy
}
}
*tpair = enum_pair;
return 0;
rexit:
free(name);
return result;
}
// Parsing typedefs - these are ALWAYS concrete due to the syntax specifics

View file

@ -67,11 +67,12 @@ static RzCallable *get_callable_type(RzTypeDB *typedb, Sdb *sdb, const char *nam
if (!values) {
goto error;
}
char arg_name[32];
char *argument_name;
char *argument_type = sdb_anext(values, &argument_name);
if (!argument_name) {
// Autoname unnamed arguments
argument_name = rz_str_newf("arg%d", i);
argument_name = rz_strf(arg_name, "arg%d", i);
}
char *error_msg = NULL;
RzType *ttype = parse_type_string_cached(typedb->parser, type_str_cache, argument_type, &error_msg, cache_newly_added);
@ -80,9 +81,10 @@ static RzCallable *get_callable_type(RzTypeDB *typedb, Sdb *sdb, const char *nam
free(values);
goto error;
}
ht_pp_insert(type_str_cache, argument_type, ttype);
RzCallableArg *arg = RZ_NEW0(RzCallableArg);
if (!arg) {
free(values);
rz_type_free(ttype);
goto error;
}
arg->name = strdup(argument_name);
@ -91,6 +93,7 @@ static RzCallable *get_callable_type(RzTypeDB *typedb, Sdb *sdb, const char *nam
void *element = rz_pvector_push(callable->args, arg); // returns null if no space available
if (!element) {
rz_type_callable_arg_free(arg);
goto error;
}
}

View file

@ -77,12 +77,12 @@ static TypeFormatPair *get_enum_type(Sdb *sdb, const char *sname) {
free(members);
RzStrBuf key;
const char *format = sdb_get(sdb, rz_strbuf_initf(&key, "type.%s", sname), 0);
char *format = sdb_get(sdb, rz_strbuf_initf(&key, "type.%s", sname), 0);
rz_strbuf_fini(&key);
TypeFormatPair *tpair = RZ_NEW0(TypeFormatPair);
tpair->type = base_type;
tpair->format = format ? strdup(format) : NULL;
tpair->format = format;
return tpair;
@ -252,6 +252,7 @@ static TypeFormatPair *get_typedef_type(RzTypeDB *typedb, Sdb *sdb, const char *
if (!ttype || error_msg) {
goto error;
}
free(type);
base_type->type = ttype;
if (!base_type->type) {
@ -259,16 +260,17 @@ static TypeFormatPair *get_typedef_type(RzTypeDB *typedb, Sdb *sdb, const char *
}
RzStrBuf key;
const char *format = sdb_get(sdb, rz_strbuf_initf(&key, "type.%s", sname), 0);
char *format = sdb_get(sdb, rz_strbuf_initf(&key, "type.%s", sname), 0);
rz_strbuf_fini(&key);
TypeFormatPair *tpair = RZ_NEW0(TypeFormatPair);
tpair->type = base_type;
tpair->format = format ? strdup(format) : NULL;
tpair->format = format;
return tpair;
error:
free(type);
rz_type_base_type_free(base_type);
return NULL;
}