Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix memory leak issues with age_load #1144

Merged
merged 1 commit into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions src/backend/utils/adt/agtype_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -2304,3 +2304,84 @@ char *agtype_value_type_to_string(enum agtype_value_type type)

return NULL;
}

/*
* Deallocates the passed agtype_value recursively.
*/
void pfree_agtype_value(agtype_value* value)
{
pfree_agtype_value_content(value);
pfree(value);
}

/*
* Helper function that recursively deallocates the contents
* of the passed agtype_value only. It does not deallocate
* `value` itself.
*/
void pfree_agtype_value_content(agtype_value* value)
{
int i;

// guards against stack overflow due to deeply nested agtype_value
check_stack_depth();

switch (value->type)
{
case AGTV_NUMERIC:
pfree(value->val.numeric);
break;

case AGTV_STRING:
/*
* The char pointer (val.string.val) is not free'd because
* it is not allocated by an agtype helper function.
*/
break;

case AGTV_ARRAY:
case AGTV_PATH:
for (i = 0; i < value->val.array.num_elems; i++)
{
pfree_agtype_value_content(&value->val.array.elems[i]);
}
pfree(value->val.array.elems);
break;

case AGTV_OBJECT:
case AGTV_VERTEX:
case AGTV_EDGE:
for (i = 0; i < value->val.object.num_pairs; i++)
{
pfree_agtype_value_content(&value->val.object.pairs[i].key);
pfree_agtype_value_content(&value->val.object.pairs[i].value);
}
pfree(value->val.object.pairs);
break;

case AGTV_BINARY:
pfree(value->val.binary.data);
break;

case AGTV_NULL:
case AGTV_INTEGER:
case AGTV_FLOAT:
case AGTV_BOOL:
/*
* These are deallocated by the calling function.
*/
break;

default:
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unknown agtype")));
break;
}
}

void pfree_agtype_in_state(agtype_in_state* value)
{
pfree_agtype_value(value->res);
free(value->parse_state);
}
2 changes: 2 additions & 0 deletions src/backend/utils/load/ag_load_edges.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ void edge_row_cb(int delim __attribute__((unused)), void *data)
insert_edge_simple(cr->graph_oid, cr->object_name,
object_graph_id, start_vertex_graph_id,
end_vertex_graph_id, props);

pfree(props);
}

for (i = 0; i < n_fields; ++i)
Expand Down
1 change: 1 addition & 0 deletions src/backend/utils/load/ag_load_labels.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ void vertex_row_cb(int delim __attribute__((unused)), void *data)
n_fields, label_id_int);
insert_vertex_simple(cr->graph_oid, cr->object_name,
object_graph_id, props);
pfree(props);
}


Expand Down
52 changes: 42 additions & 10 deletions src/backend/utils/load/age_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

agtype *create_empty_agtype(void)
{
agtype* out;
agtype_in_state result;

memset(&result, 0, sizeof(agtype_in_state));
Expand All @@ -47,12 +48,18 @@ agtype *create_empty_agtype(void)
NULL);
result.res = push_agtype_value(&result.parse_state, WAGT_END_OBJECT, NULL);

return agtype_value_to_agtype(result.res);
out = agtype_value_to_agtype(result.res);
pfree_agtype_in_state(&result);

return out;
}

agtype *create_agtype_from_list(char **header, char **fields, size_t fields_len,
int64 vertex_id)
{
agtype* out;
agtype_value* key_agtype;
agtype_value* value_agtype;
agtype_in_state result;
int i;

Expand All @@ -61,33 +68,50 @@ agtype *create_agtype_from_list(char **header, char **fields, size_t fields_len,
result.res = push_agtype_value(&result.parse_state, WAGT_BEGIN_OBJECT,
NULL);

key_agtype = string_to_agtype_value("__id__");
result.res = push_agtype_value(&result.parse_state,
WAGT_KEY,
string_to_agtype_value("__id__"));
key_agtype);

value_agtype = integer_to_agtype_value(vertex_id);
result.res = push_agtype_value(&result.parse_state,
WAGT_VALUE,
integer_to_agtype_value(vertex_id));
value_agtype);

pfree_agtype_value(key_agtype);
pfree_agtype_value(value_agtype);

for (i = 0; i<fields_len; i++)
{
key_agtype = string_to_agtype_value(header[i]);
result.res = push_agtype_value(&result.parse_state,
WAGT_KEY,
string_to_agtype_value(header[i]));
key_agtype);

value_agtype = string_to_agtype_value(fields[i]);
result.res = push_agtype_value(&result.parse_state,
WAGT_VALUE,
string_to_agtype_value(fields[i]));
value_agtype);

pfree_agtype_value(key_agtype);
pfree_agtype_value(value_agtype);
}

result.res = push_agtype_value(&result.parse_state,
WAGT_END_OBJECT, NULL);

return agtype_value_to_agtype(result.res);
out = agtype_value_to_agtype(result.res);
pfree_agtype_in_state(&result);

return out;
}

agtype* create_agtype_from_list_i(char **header, char **fields,
size_t fields_len, size_t start_index)
{

agtype* out;
agtype_value* key_agtype;
agtype_value* value_agtype;
agtype_in_state result;
size_t i;

Expand All @@ -103,18 +127,26 @@ agtype* create_agtype_from_list_i(char **header, char **fields,

for (i = start_index; i < fields_len; i++)
{
key_agtype = string_to_agtype_value(header[i]);
result.res = push_agtype_value(&result.parse_state,
WAGT_KEY,
string_to_agtype_value(header[i]));
key_agtype);
value_agtype = string_to_agtype_value(fields[i]);
result.res = push_agtype_value(&result.parse_state,
WAGT_VALUE,
string_to_agtype_value(fields[i]));
value_agtype);

pfree_agtype_value(key_agtype);
pfree_agtype_value(value_agtype);
}

result.res = push_agtype_value(&result.parse_state,
WAGT_END_OBJECT, NULL);

return agtype_value_to_agtype(result.res);
out = agtype_value_to_agtype(result.res);
pfree_agtype_in_state(&result);

return out;
}

void insert_edge_simple(Oid graph_oid, char *label_name, graphid edge_id,
Expand Down
3 changes: 3 additions & 0 deletions src/include/utils/agtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,9 @@ agtype_value *string_to_agtype_value(char *s);
agtype_value *integer_to_agtype_value(int64 int_value);
void add_agtype(Datum val, bool is_null, agtype_in_state *result, Oid val_type,
bool key_scalar);
void pfree_agtype_value(agtype_value* value);
void pfree_agtype_value_content(agtype_value* value);
void pfree_agtype_in_state(agtype_in_state* value);

/* Oid accessors for AGTYPE */
Oid get_AGTYPEOID(void);
Expand Down