diff --git a/regress/expected/expr.out b/regress/expected/expr.out index c3a6f23e1..217860859 100644 --- a/regress/expected/expr.out +++ b/regress/expected/expr.out @@ -8506,6 +8506,21 @@ SELECT agtype_to_int8(bool('neither')); ERROR: invalid input syntax for type boolean: "neither" LINE 1: SELECT agtype_to_int8(bool('neither')); ^ +-- +-- Issue 2093: Server crashes when executing SELECT agtype_hash_cmp(agtype_in('[null, null, null, null, null]')); +-- +SELECT agtype_access_operator(agtype_in('[null, null]')); + agtype_access_operator +------------------------ + +(1 row) + +SELECT agtype_hash_cmp(agtype_in('[null, null, null, null, null]')); + agtype_hash_cmp +----------------- + -505290721 +(1 row) + -- -- Cleanup -- diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql index 3f1661bc9..e92a542c1 100644 --- a/regress/sql/expr.sql +++ b/regress/sql/expr.sql @@ -3455,6 +3455,12 @@ SELECT agtype_to_int2(bool('neither')); SELECT agtype_to_int4(bool('neither')); SELECT agtype_to_int8(bool('neither')); +-- +-- Issue 2093: Server crashes when executing SELECT agtype_hash_cmp(agtype_in('[null, null, null, null, null]')); +-- +SELECT agtype_access_operator(agtype_in('[null, null]')); +SELECT agtype_hash_cmp(agtype_in('[null, null, null, null, null]')); + -- -- Cleanup -- diff --git a/src/backend/commands/label_commands.c b/src/backend/commands/label_commands.c index 9480ccc19..5752372aa 100644 --- a/src/backend/commands/label_commands.c +++ b/src/backend/commands/label_commands.c @@ -94,8 +94,6 @@ static void range_var_callback_for_remove_relation(const RangeVar *rel, Oid odl_rel_oid, void *arg); - - PG_FUNCTION_INFO_V1(create_vlabel); /* diff --git a/src/backend/executor/cypher_merge.c b/src/backend/executor/cypher_merge.c index 6365db137..066c0d139 100644 --- a/src/backend/executor/cypher_merge.c +++ b/src/backend/executor/cypher_merge.c @@ -346,7 +346,7 @@ static void free_path_entry_array(path_entry **path_array, int length) for (index = 0; index < length; index++) { - pfree(path_array[index]); + pfree_if_not_null(path_array[index]); } } @@ -892,10 +892,10 @@ static void end_cypher_merge(CustomScanState *node) free_path_entry_array(entry, path_length); /* free up the array container */ - pfree(entry); + pfree_if_not_null(entry); /* free up the created_path container */ - pfree(css->created_paths_list); + pfree_if_not_null(css->created_paths_list); css->created_paths_list = next; } diff --git a/src/backend/executor/cypher_set.c b/src/backend/executor/cypher_set.c index 8c46c115c..7af575b00 100644 --- a/src/backend/executor/cypher_set.c +++ b/src/backend/executor/cypher_set.c @@ -594,7 +594,7 @@ static void process_update_list(CustomScanState *node) lidx++; } /* free our lookup array */ - pfree(luindex); + pfree_if_not_null(luindex); } static TupleTableSlot *exec_cypher_set(CustomScanState *node) diff --git a/src/backend/executor/cypher_utils.c b/src/backend/executor/cypher_utils.c index 098c11187..4627f1625 100644 --- a/src/backend/executor/cypher_utils.c +++ b/src/backend/executor/cypher_utils.c @@ -75,7 +75,7 @@ uint32 datum_image_hash(Datum value, bool typByVal, int typLen) /* Only free memory if it's a copy made here. */ if ((Pointer) val != (Pointer) value) { - pfree(val); + pfree_if_not_null(val); } } else if (typLen == -2) diff --git a/src/backend/parser/ag_scanner.l b/src/backend/parser/ag_scanner.l index 7aabf3cf2..f7773d469 100644 --- a/src/backend/parser/ag_scanner.l +++ b/src/backend/parser/ag_scanner.l @@ -34,6 +34,7 @@ #include "mb/pg_wchar.h" #include "parser/ag_scanner.h" +#include "utils/agtype.h" } %option 8bit @@ -796,7 +797,7 @@ void *ag_yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner) { if (size == 0) { - pfree(ptr); + pfree_if_not_null(ptr); return NULL; } else @@ -813,7 +814,7 @@ void *ag_yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner) void ag_yyfree(void *ptr, yyscan_t yyscanner) { if (ptr) - pfree(ptr); + pfree_if_not_null(ptr); } static void strbuf_init(strbuf *sb, int capacity) @@ -826,7 +827,7 @@ static void strbuf_init(strbuf *sb, int capacity) static void strbuf_cleanup(strbuf *sb) { if (sb->buffer) - pfree(sb->buffer); + pfree_if_not_null(sb->buffer); } static void strbuf_append_buf(strbuf *sb, const char *b, const int len) @@ -1121,8 +1122,8 @@ static void _numstr_to_decimal(const char *numstr, const int base, strbuf *sb) strbuf_append_buf(sb, &buf[buf_i], NDIGITS_PER_REMAINDER - buf_i); } - pfree(remainders); - pfree(words); + pfree_if_not_null(remainders); + pfree_if_not_null(words); } static uint32 hexdigit_value(const char c) diff --git a/src/backend/parser/cypher_analyze.c b/src/backend/parser/cypher_analyze.c index a21889567..9e1adb917 100644 --- a/src/backend/parser/cypher_analyze.c +++ b/src/backend/parser/cypher_analyze.c @@ -106,7 +106,7 @@ static void post_parse_analyze(ParseState *pstate, Query *query) } /* reset extra_node */ - pfree(extra_node); + pfree_if_not_null(extra_node); extra_node = NULL; } } @@ -275,7 +275,7 @@ static void build_explain_query(Query *query, Node *explain_node) ((ExplainStmt *)explain_node)->options = NULL; /* we need to free query_node as it is no longer needed */ - pfree(query_node); + pfree_if_not_null(query_node); } static bool is_rte_cypher(RangeTblEntry *rte) diff --git a/src/backend/parser/cypher_gram.y b/src/backend/parser/cypher_gram.y index 3c77c8305..50417b1d0 100644 --- a/src/backend/parser/cypher_gram.y +++ b/src/backend/parser/cypher_gram.y @@ -26,6 +26,7 @@ #include "parser/cypher_gram.h" #include "parser/cypher_parse_node.h" #include "parser/scansup.h" +#include "utils/agtype.h" /* override the default action for locations */ #define YYLLOC_DEFAULT(current, rhs, n) \ @@ -2796,7 +2797,7 @@ static char *create_unique_name(char *prefix_name) /* if we created the prefix, we need to free it */ if (prefix_name == NULL || strlen(prefix_name) <= 0) { - pfree(prefix); + pfree_if_not_null(prefix); } return name; diff --git a/src/backend/parser/cypher_parse_agg.c b/src/backend/parser/cypher_parse_agg.c index 8fdb71d3e..73b527c7c 100644 --- a/src/backend/parser/cypher_parse_agg.c +++ b/src/backend/parser/cypher_parse_agg.c @@ -31,6 +31,7 @@ #include "parser/cypher_parse_agg.h" #include "parser/parsetree.h" #include "rewrite/rewriteManip.h" +#include "utils/agtype.h" typedef struct { @@ -846,7 +847,7 @@ static List * expand_grouping_sets(List *groupingSets, int limit) while (result_len-- > 0) result = lappend(result, *ptr++); - pfree(buf); + pfree_if_not_null(buf); } return result; diff --git a/src/backend/utils/adt/age_global_graph.c b/src/backend/utils/adt/age_global_graph.c index 1f2c22711..d1c3750ef 100644 --- a/src/backend/utils/adt/age_global_graph.c +++ b/src/backend/utils/adt/age_global_graph.c @@ -182,7 +182,7 @@ static void create_GRAPH_global_hashtables(GRAPH_global_context *ggctx) ggctx->vertex_hashtable = hash_create(vhn, VERTEX_HTAB_INITIAL_SIZE, &vertex_ctl, HASH_ELEM | HASH_FUNCTION); - pfree(vhn); + pfree_if_not_null(vhn); /* initialize the edge hashtable */ MemSet(&edge_ctl, 0, sizeof(edge_ctl)); @@ -191,7 +191,7 @@ static void create_GRAPH_global_hashtables(GRAPH_global_context *ggctx) edge_ctl.hash = tag_hash; ggctx->edge_hashtable = hash_create(ehn, EDGE_HTAB_INITIAL_SIZE, &edge_ctl, HASH_ELEM | HASH_FUNCTION); - pfree(ehn); + pfree_if_not_null(ehn); } /* helper function to get a List of all label names for the specified graph */ @@ -625,7 +625,7 @@ static bool free_specific_GRAPH_global_context(GRAPH_global_context *ggctx) } /* free the graph name */ - pfree(ggctx->graph_name); + pfree_if_not_null(ggctx->graph_name); ggctx->graph_name = NULL; ggctx->graph_oid = InvalidOid; @@ -657,7 +657,7 @@ static bool free_specific_GRAPH_global_context(GRAPH_global_context *ggctx) } /* free the vertex's datumCopy properties */ - pfree(DatumGetPointer(value->vertex_properties)); + pfree_if_not_null(DatumGetPointer(value->vertex_properties)); value->vertex_properties = 0; /* free the edge list associated with this vertex */ @@ -699,7 +699,7 @@ static bool free_specific_GRAPH_global_context(GRAPH_global_context *ggctx) } /* free the edge's datumCopy properties */ - pfree(DatumGetPointer(value->edge_properties)); + pfree_if_not_null(DatumGetPointer(value->edge_properties)); value->edge_properties = 0; /* move to the next edge */ @@ -722,7 +722,7 @@ static bool free_specific_GRAPH_global_context(GRAPH_global_context *ggctx) ggctx->edge_hashtable = NULL; /* free the context */ - pfree(ggctx); + pfree_if_not_null(ggctx); ggctx = NULL; return true; @@ -1225,7 +1225,7 @@ Datum age_vertex_stats(PG_FUNCTION_ARGS) ggctx = manage_GRAPH_global_contexts(graph_name, graph_oid); /* free the graph name */ - pfree(graph_name); + pfree_if_not_null(graph_name); /* get the id */ agtv_temp = GET_AGTYPE_VALUE_OBJECT_VALUE(agtv_vertex, "id"); diff --git a/src/backend/utils/adt/age_graphid_ds.c b/src/backend/utils/adt/age_graphid_ds.c index 73be8dc2e..625a6947c 100644 --- a/src/backend/utils/adt/age_graphid_ds.c +++ b/src/backend/utils/adt/age_graphid_ds.c @@ -144,14 +144,14 @@ void free_ListGraphId(ListGraphId *container) { next_node = curr_node->next; /* we can do this because this is just a list of ints */ - pfree(curr_node); + pfree_if_not_null(curr_node); container->size--; curr_node = next_node; } Assert(container->size == 0); /* free the container */ - pfree(container); + pfree_if_not_null(container); } /* helper function to create a new, empty, graphid stack */ @@ -188,7 +188,7 @@ void free_graphid_stack(ListGraphId *stack) GraphIdNode *next = stack->head->next; /* free the head element */ - pfree(stack->head); + pfree_if_not_null(stack->head); /* move the head to the next */ stack->head = next; } @@ -253,7 +253,7 @@ graphid pop_graphid_stack(ListGraphId *stack) stack->head = stack->head->next; stack->size--; /* free the element */ - pfree(node); + pfree_if_not_null(node); /* return the id */ return id; diff --git a/src/backend/utils/adt/age_session_info.c b/src/backend/utils/adt/age_session_info.c index 350273eb3..f224d4064 100644 --- a/src/backend/utils/adt/age_session_info.c +++ b/src/backend/utils/adt/age_session_info.c @@ -125,12 +125,12 @@ void reset_session_info(void) { if (session_info_graph_name != NULL) { - pfree(session_info_graph_name); + pfree_if_not_null(session_info_graph_name); } if (session_info_cypher_statement != NULL) { - pfree(session_info_cypher_statement); + pfree_if_not_null(session_info_cypher_statement); } } diff --git a/src/backend/utils/adt/age_vle.c b/src/backend/utils/adt/age_vle.c index 8e3b4d3c1..1e7910cc6 100644 --- a/src/backend/utils/adt/age_vle.c +++ b/src/backend/utils/adt/age_vle.c @@ -313,7 +313,7 @@ static void create_VLE_local_state_hashtable(VLE_local_context *vlelctx) EDGE_STATE_HTAB_INITIAL_SIZE, &edge_state_ctl, HASH_ELEM | HASH_FUNCTION); - pfree(eshn); + pfree_if_not_null(eshn); } /* @@ -400,14 +400,14 @@ static void free_VLE_local_context(VLE_local_context *vlelctx) /* free the stored graph name */ if (vlelctx->graph_name != NULL) { - pfree(vlelctx->graph_name); + pfree_if_not_null(vlelctx->graph_name); vlelctx->graph_name = NULL; } /* free the stored edge label name */ if (vlelctx->edge_label_name != NULL) { - pfree(vlelctx->edge_label_name); + pfree_if_not_null(vlelctx->edge_label_name); vlelctx->edge_label_name = NULL; } @@ -429,15 +429,15 @@ static void free_VLE_local_context(VLE_local_context *vlelctx) } /* free the containers */ - pfree(vlelctx->dfs_vertex_stack); - pfree(vlelctx->dfs_edge_stack); - pfree(vlelctx->dfs_path_stack); + pfree_if_not_null(vlelctx->dfs_vertex_stack); + pfree_if_not_null(vlelctx->dfs_edge_stack); + pfree_if_not_null(vlelctx->dfs_path_stack); vlelctx->dfs_vertex_stack = NULL; vlelctx->dfs_edge_stack = NULL; vlelctx->dfs_path_stack = NULL; /* and finally the context itself */ - pfree(vlelctx); + pfree_if_not_null(vlelctx); vlelctx = NULL; } diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c index d908f3ca3..5b2dc4042 100644 --- a/src/backend/utils/adt/agtype.c +++ b/src/backend/utils/adt/agtype.c @@ -178,6 +178,19 @@ static agtype_value* agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo); agtype_value *agtype_composite_to_agtype_value_binary(agtype *a); static agtype_value *tostring_helper(Datum arg, Oid type, char *msghdr); +/* + * Due to how pfree can be implemented, it may not check for a passed NULL. This + * wrapper does just that, it will only call pfree is the pointer passed is not + * NULL. + */ +void pfree_if_not_null(void *ptr) +{ + if (ptr != NULL) + { + pfree(ptr); + } +} + /* global storage of OID for agtype and _agtype */ static Oid g_AGTYPEOID = InvalidOid; static Oid g_AGTYPEARRAYOID = InvalidOid; @@ -295,7 +308,7 @@ Datum agtype_recv(PG_FUNCTION_ARGS) result = agtype_from_cstring(str, nbytes); PG_FREE_IF_COPY(buf, 0); - pfree(str); + pfree_if_not_null(str); return result; } @@ -320,8 +333,8 @@ Datum agtype_send(PG_FUNCTION_ARGS) pq_begintypsend(&buf); pq_sendint8(&buf, version); pq_sendtext(&buf, agtype_text->data, agtype_text->len); - pfree(agtype_text->data); - pfree(agtype_text); + pfree_if_not_null(agtype_text->data); + pfree_if_not_null(agtype_text); PG_FREE_IF_COPY(agt, 0); @@ -1543,7 +1556,7 @@ static void datum_to_agtype(Datum val, bool is_null, agtype_in_state *result, intd = DirectFunctionCall1(int8in, CStringGetDatum(outputstr)); agtv.type = AGTV_INTEGER; agtv.val.int_value = DatumGetInt64(intd); - pfree(outputstr); + pfree_if_not_null(outputstr); } break; case AGT_TYPE_FLOAT: @@ -1588,7 +1601,7 @@ static void datum_to_agtype(Datum val, bool is_null, agtype_in_state *result, ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1)); agtv.val.numeric = DatumGetNumeric(numd); - pfree(outputstr); + pfree_if_not_null(outputstr); } else { @@ -1818,8 +1831,8 @@ static void array_to_agtype_internal(Datum array, agtype_in_state *result) array_dim_to_agtype(result, 0, ndim, dim, elements, nulls, &count, tcategory, outfuncoid); - pfree(elements); - pfree(nulls); + pfree_if_not_null(elements); + pfree_if_not_null(nulls); } /* @@ -2218,7 +2231,7 @@ Datum make_path(List *path) if ((Pointer) (agt) != lfirst(lc)) { - pfree(agt); + pfree_if_not_null(agt); } pfree_agtype_value(elem); @@ -2471,7 +2484,7 @@ static agtype_value* agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo) result.res = push_agtype_value(&result.parse_state, WAGT_KEY, agtv); /* free the agtype_value from tostring_helper */ - pfree(agtv); + pfree_if_not_null(agtv); } else { @@ -2833,7 +2846,7 @@ Datum agtype_to_int8(PG_FUNCTION_ARGS) /* free the container, if it was used */ if (container) { - pfree(container); + pfree_if_not_null(container); } PG_FREE_IF_COPY(arg_agt, 0); @@ -2954,7 +2967,7 @@ Datum agtype_to_int4(PG_FUNCTION_ARGS) /* free the container, if it was used */ if (container) { - pfree(container); + pfree_if_not_null(container); } PG_FREE_IF_COPY(arg_agt, 0); @@ -3076,7 +3089,7 @@ Datum agtype_to_int2(PG_FUNCTION_ARGS) /* free the container, if it was used */ if (container) { - pfree(container); + pfree_if_not_null(container); } PG_FREE_IF_COPY(arg_agt, 0); @@ -3226,7 +3239,7 @@ Datum agtype_to_json(PG_FUNCTION_ARGS) result = DirectFunctionCall1(json_in, CStringGetDatum(json_str)); PG_FREE_IF_COPY(agt, 0); - pfree(json_str); + pfree_if_not_null(json_str); PG_RETURN_DATUM(result); } @@ -4000,9 +4013,9 @@ Datum agtype_access_operator(PG_FUNCTION_ARGS) */ if (args == NULL || nargs == 0 || nulls[0] == true) { - pfree(args); - pfree(types); - pfree(nulls); + pfree_if_not_null(args); + pfree_if_not_null(types); + pfree_if_not_null(nulls); PG_RETURN_NULL(); } @@ -4013,9 +4026,9 @@ Datum agtype_access_operator(PG_FUNCTION_ARGS) /* if we have a NULL, return NULL */ if (nulls[i] == true) { - pfree(args); - pfree(types); - pfree(nulls); + pfree_if_not_null(args); + pfree_if_not_null(types); + pfree_if_not_null(nulls); PG_RETURN_NULL(); } } @@ -4134,9 +4147,9 @@ Datum agtype_access_operator(PG_FUNCTION_ARGS) container = NULL; } - pfree(args); - pfree(types); - pfree(nulls); + pfree_if_not_null(args); + pfree_if_not_null(types); + pfree_if_not_null(nulls); /* serialize and return the result */ result = agtype_value_to_agtype(container_value); @@ -4611,8 +4624,8 @@ Datum agtype_string_match_contains(PG_FUNCTION_ARGS) { result = true; } - pfree(l); - pfree(r); + pfree_if_not_null(l); + pfree_if_not_null(r); } pfree_agtype_value(lhs_value); pfree_agtype_value(rhs_value); @@ -4668,7 +4681,7 @@ Datum agtype_hash_cmp(PG_FUNCTION_ARGS) seed = LEFT_ROTATE(seed, 1); } - pfree(r); + pfree_if_not_null(r); PG_FREE_IF_COPY(agt, 0); PG_RETURN_INT32(hash); @@ -4774,7 +4787,7 @@ Datum agtype_typecast_numeric(PG_FUNCTION_ARGS) ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1)); /* free the string */ - pfree(string); + pfree_if_not_null(string); string = NULL; break; /* what was given doesn't cast to a numeric */ @@ -4862,7 +4875,7 @@ Datum agtype_typecast_int(PG_FUNCTION_ARGS) d = DirectFunctionCall1(int8in, CStringGetDatum(string)); /* free the string */ - pfree(string); + pfree_if_not_null(string); string = NULL; break; /* what was given doesn't cast to an int */ @@ -4999,7 +5012,7 @@ Datum agtype_typecast_float(PG_FUNCTION_ARGS) d = DirectFunctionCall1(float8in, CStringGetDatum(string)); /* free the string */ - pfree(string); + pfree_if_not_null(string); string = NULL; break; /* what was given doesn't cast to a float */ @@ -7082,7 +7095,7 @@ Datum age_tostring(PG_FUNCTION_ARGS) /* convert to agtype and free the agtype_value */ agt = agtype_value_to_agtype(agtv); - pfree(agtv); + pfree_if_not_null(agtv); PG_RETURN_POINTER(agt); } @@ -10285,9 +10298,9 @@ agtype *get_one_agtype_from_variadic_args(FunctionCallInfo fcinfo, /* if null, return null */ if (nulls[0]) { - pfree(args); - pfree(nulls); - pfree(types); + pfree_if_not_null(args); + pfree_if_not_null(nulls); + pfree_if_not_null(types); return NULL; } @@ -10308,9 +10321,9 @@ agtype *get_one_agtype_from_variadic_args(FunctionCallInfo fcinfo, { PG_FREE_IF_COPY(agtype_result, variadic_offset); - pfree(args); - pfree(nulls); - pfree(types); + pfree_if_not_null(args); + pfree_if_not_null(nulls); + pfree_if_not_null(types); return NULL; } } @@ -10334,9 +10347,9 @@ agtype *get_one_agtype_from_variadic_args(FunctionCallInfo fcinfo, pfree_agtype_in_state(&state); } - pfree(args); - pfree(nulls); - pfree(types); + pfree_if_not_null(args); + pfree_if_not_null(nulls); + pfree_if_not_null(types); return agtype_result; } diff --git a/src/backend/utils/adt/agtype_gin.c b/src/backend/utils/adt/agtype_gin.c index 3d7de2194..07d9402bb 100644 --- a/src/backend/utils/adt/agtype_gin.c +++ b/src/backend/utils/adt/agtype_gin.c @@ -553,7 +553,7 @@ static Datum make_scalar_key(const agtype_value *scalarVal, bool is_key) */ cstr = numeric_normalize(scalarVal->val.numeric); item = make_text_key(AGT_GIN_FLAG_NUM, cstr, strlen(cstr)); - pfree(cstr); + pfree_if_not_null(cstr); break; case AGTV_STRING: item = make_text_key(is_key ? AGT_GIN_FLAG_KEY : AGT_GIN_FLAG_STR, diff --git a/src/backend/utils/adt/agtype_raw.c b/src/backend/utils/adt/agtype_raw.c index e7270ef84..d8bad3d24 100644 --- a/src/backend/utils/adt/agtype_raw.c +++ b/src/backend/utils/adt/agtype_raw.c @@ -172,8 +172,8 @@ void pfree_agtype_build_state(agtype_build_state *bstate) * bstate->buffer->data is not pfree'd because this pointer * is returned by the `build_agtype` function. */ - pfree(bstate->buffer); - pfree(bstate); + pfree_if_not_null(bstate->buffer); + pfree_if_not_null(bstate); } void write_string(agtype_build_state *bstate, char *str) diff --git a/src/backend/utils/adt/agtype_util.c b/src/backend/utils/adt/agtype_util.c index 878f1844a..01a965cdd 100644 --- a/src/backend/utils/adt/agtype_util.c +++ b/src/backend/utils/adt/agtype_util.c @@ -433,14 +433,14 @@ int compare_agtype_containers_orderability(agtype_container *a, { agtype_iterator *i = ita->parent; - pfree(ita); + pfree_if_not_null(ita); ita = i; } while (itb != NULL) { agtype_iterator *i = itb->parent; - pfree(itb); + pfree_if_not_null(itb); itb = i; } @@ -557,7 +557,7 @@ agtype_value *find_agtype_value_from_container(agtype_container *container, } /* Not found */ - pfree(result); + pfree_if_not_null(result); return NULL; } @@ -1217,7 +1217,7 @@ static agtype_iterator *free_and_get_parent(agtype_iterator *it) { agtype_iterator *v = it->parent; - pfree(it); + pfree_if_not_null(it); return v; } @@ -1469,9 +1469,9 @@ bool agtype_deep_contains(agtype_iterator **val, contains = agtype_deep_contains(&nestval, &nest_contained, false); if (nestval) - pfree(nestval); + pfree_if_not_null(nestval); if (nest_contained) - pfree(nest_contained); + pfree_if_not_null(nest_contained); if (contains) break; } @@ -2438,7 +2438,7 @@ char *agtype_value_type_to_string(enum agtype_value_type type) void pfree_agtype_value(agtype_value* value) { pfree_agtype_value_content(value); - pfree(value); + pfree_if_not_null(value); } /* @@ -2456,7 +2456,7 @@ void pfree_agtype_value_content(agtype_value* value) switch (value->type) { case AGTV_NUMERIC: - pfree(value->val.numeric); + pfree_if_not_null(value->val.numeric); break; case AGTV_STRING: @@ -2464,7 +2464,7 @@ void pfree_agtype_value_content(agtype_value* value) * The char pointer (val.string.val) is not free'd because * it is not allocated by an agtype helper function. */ - pfree(value->val.string.val); + pfree_if_not_null(value->val.string.val); break; case AGTV_ARRAY: @@ -2473,7 +2473,7 @@ void pfree_agtype_value_content(agtype_value* value) { pfree_agtype_value_content(&value->val.array.elems[i]); } - pfree(value->val.array.elems); + pfree_if_not_null(value->val.array.elems); break; case AGTV_OBJECT: @@ -2484,11 +2484,11 @@ void pfree_agtype_value_content(agtype_value* value) 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); + pfree_if_not_null(value->val.object.pairs); break; case AGTV_BINARY: - pfree(value->val.binary.data); + pfree_if_not_null(value->val.binary.data); break; case AGTV_NULL: diff --git a/src/backend/utils/load/ag_load_edges.c b/src/backend/utils/load/ag_load_edges.c index 71683bf4c..30dc4761d 100644 --- a/src/backend/utils/load/ag_load_edges.c +++ b/src/backend/utils/load/ag_load_edges.c @@ -307,9 +307,9 @@ void finish_edge_batch_insert(batch_insert_state **batch_state, } // Clean up batch state - pfree((*batch_state)->slots); - pfree(*batch_state); + pfree_if_not_null((*batch_state)->slots); + pfree_if_not_null(*batch_state); *batch_state = NULL; table_close(relation, AccessShareLock); -} \ No newline at end of file +} diff --git a/src/backend/utils/load/ag_load_labels.c b/src/backend/utils/load/ag_load_labels.c index b38c7fca9..94167812a 100644 --- a/src/backend/utils/load/ag_load_labels.c +++ b/src/backend/utils/load/ag_load_labels.c @@ -458,11 +458,11 @@ static void finish_vertex_batch_insert(batch_insert_state **batch_state, } /* Clean up batch state */ - pfree((*batch_state)->slots); - pfree((*batch_state)->temp_id_slots); - pfree(*batch_state); + pfree_if_not_null((*batch_state)->slots); + pfree_if_not_null((*batch_state)->temp_id_slots); + pfree_if_not_null(*batch_state); *batch_state = NULL; table_close(relation, AccessShareLock); table_close(temp_table_relation, AccessShareLock); -} \ No newline at end of file +} diff --git a/src/include/utils/age_graphid_ds.h b/src/include/utils/age_graphid_ds.h index ea9dabdc3..a5bb5273f 100644 --- a/src/include/utils/age_graphid_ds.h +++ b/src/include/utils/age_graphid_ds.h @@ -21,6 +21,7 @@ #define AG_AGE_GRAPHID_DS_H #include "utils/graphid.h" +#include "utils/agtype.h" #define IS_GRAPHID_STACK_EMPTY(stack) \ get_stack_size(stack) == 0 diff --git a/src/include/utils/age_session_info.h b/src/include/utils/age_session_info.h index ebf0035ab..5bd072fb6 100644 --- a/src/include/utils/age_session_info.h +++ b/src/include/utils/age_session_info.h @@ -20,6 +20,8 @@ #ifndef AGE_SESSION_INFO_H #define AGE_SESSION_INFO_H +#include "utils/agtype.h" + bool is_session_info_prepared(void); char *get_session_info_graph_name(void); char *get_session_info_cypher_statement(void); diff --git a/src/include/utils/agtype.h b/src/include/utils/agtype.h index 0124dd72b..fcf0657f4 100644 --- a/src/include/utils/agtype.h +++ b/src/include/utils/agtype.h @@ -555,6 +555,7 @@ agtype_iterator *get_next_list_element(agtype_iterator *it, void pfree_agtype_value(agtype_value* value); void pfree_agtype_value_content(agtype_value* value); void pfree_agtype_in_state(agtype_in_state* value); +void pfree_if_not_null(void *ptr); agtype_value *agtype_value_from_cstring(char *str, int len); /* Oid accessors for AGTYPE */ Oid get_AGTYPEOID(void);