Fix issue 2093: pfree() called with a NULL pointer (#2095) (#2104)
Fixed issue 2093 where pfree() was called with a NULL pointer.
The issue is due to some confusion with pfree(). There are 2
definitions for it, one that checks for a passed NULL and the
other which does not.
Created a function, pfree_if_not_null(), to check for NULL and
call pfree() if a NULL wasn't passed.
Modified the pfree references in the following files -
src/backend/commands/label_commands.c
src/backend/executor/cypher_merge.c
src/backend/executor/cypher_set.c
src/backend/executor/cypher_utils.c
src/backend/parser/ag_scanner.l
src/backend/parser/cypher_analyze.c
src/backend/parser/cypher_expr.c
src/backend/parser/cypher_gram.y
src/backend/parser/cypher_parse_agg.c
src/backend/utils/adt/age_global_graph.c
src/backend/utils/adt/age_graphid_ds.c
src/backend/utils/adt/age_session_info.c
src/backend/utils/adt/age_vle.c
src/backend/utils/adt/agtype.c
src/backend/utils/adt/agtype_gin.c
src/backend/utils/adt/agtype_raw.c
src/backend/utils/adt/agtype_util.c
src/backend/utils/load/ag_load_edges.c
src/backend/utils/load/ag_load_labels.c
src/include/utils/age_graphid_ds.h
src/include/utils/age_session_info.h
src/include/utils/agtype.h
Added regression tests for the original issue.
Resolved Conflicts:
src/backend/commands/label_commands.c
src/backend/parser/cypher_expr.c
src/backend/parser/cypher_parse_agg.c
src/backend/utils/adt/age_global_graph.c
src/backend/utils/adt/agtype.c
diff --git a/regress/expected/expr.out b/regress/expected/expr.out
index c3a6f23..2178608 100644
--- a/regress/expected/expr.out
+++ b/regress/expected/expr.out
@@ -8507,6 +8507,21 @@
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
--
SELECT * FROM drop_graph('issue_1124', true);
diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql
index 3f1661b..e92a542 100644
--- a/regress/sql/expr.sql
+++ b/regress/sql/expr.sql
@@ -3456,6 +3456,12 @@
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
--
SELECT * FROM drop_graph('issue_1124', true);
diff --git a/src/backend/commands/label_commands.c b/src/backend/commands/label_commands.c
index 9480ccc..5752372 100644
--- a/src/backend/commands/label_commands.c
+++ b/src/backend/commands/label_commands.c
@@ -94,8 +94,6 @@
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 6365db1..066c0d1 100644
--- a/src/backend/executor/cypher_merge.c
+++ b/src/backend/executor/cypher_merge.c
@@ -346,7 +346,7 @@
for (index = 0; index < length; index++)
{
- pfree(path_array[index]);
+ pfree_if_not_null(path_array[index]);
}
}
@@ -892,10 +892,10 @@
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 8c46c11..7af575b 100644
--- a/src/backend/executor/cypher_set.c
+++ b/src/backend/executor/cypher_set.c
@@ -594,7 +594,7 @@
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 098c111..4627f16 100644
--- a/src/backend/executor/cypher_utils.c
+++ b/src/backend/executor/cypher_utils.c
@@ -75,7 +75,7 @@
/* 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 7aabf3c..f7773d4 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 @@
{
if (size == 0)
{
- pfree(ptr);
+ pfree_if_not_null(ptr);
return NULL;
}
else
@@ -813,7 +814,7 @@
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_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 @@
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 a218895..9e1adb9 100644
--- a/src/backend/parser/cypher_analyze.c
+++ b/src/backend/parser/cypher_analyze.c
@@ -106,7 +106,7 @@
}
/* reset extra_node */
- pfree(extra_node);
+ pfree_if_not_null(extra_node);
extra_node = NULL;
}
}
@@ -275,7 +275,7 @@
((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 3c77c83..50417b1 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 @@
/* 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 8fdb71d..73b527c 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 @@
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 1f2c227..d1c3750 100644
--- a/src/backend/utils/adt/age_global_graph.c
+++ b/src/backend/utils/adt/age_global_graph.c
@@ -182,7 +182,7 @@
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 @@
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 @@
}
/* 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 @@
}
/* 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 @@
}
/* 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 @@
ggctx->edge_hashtable = NULL;
/* free the context */
- pfree(ggctx);
+ pfree_if_not_null(ggctx);
ggctx = NULL;
return true;
@@ -1225,7 +1225,7 @@
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 73be8dc..625a694 100644
--- a/src/backend/utils/adt/age_graphid_ds.c
+++ b/src/backend/utils/adt/age_graphid_ds.c
@@ -144,14 +144,14 @@
{
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 @@
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 @@
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 350273e..f224d40 100644
--- a/src/backend/utils/adt/age_session_info.c
+++ b/src/backend/utils/adt/age_session_info.c
@@ -125,12 +125,12 @@
{
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 8e3b4d3..1e7910c 100644
--- a/src/backend/utils/adt/age_vle.c
+++ b/src/backend/utils/adt/age_vle.c
@@ -313,7 +313,7 @@
EDGE_STATE_HTAB_INITIAL_SIZE,
&edge_state_ctl,
HASH_ELEM | HASH_FUNCTION);
- pfree(eshn);
+ pfree_if_not_null(eshn);
}
/*
@@ -400,14 +400,14 @@
/* 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 @@
}
/* 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 d908f3c..5b2dc40 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -178,6 +178,19 @@
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 @@
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 @@
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 @@
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 @@
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
agtv.val.numeric = DatumGetNumeric(numd);
- pfree(outputstr);
+ pfree_if_not_null(outputstr);
}
else
{
@@ -1818,8 +1831,8 @@
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 @@
if ((Pointer) (agt) != lfirst(lc))
{
- pfree(agt);
+ pfree_if_not_null(agt);
}
pfree_agtype_value(elem);
@@ -2471,7 +2484,7 @@
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 @@
/* 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 @@
/* 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 @@
/* 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 @@
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 @@
*/
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 @@
/* 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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
/* 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 @@
{
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 @@
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 3d7de21..07d9402 100644
--- a/src/backend/utils/adt/agtype_gin.c
+++ b/src/backend/utils/adt/agtype_gin.c
@@ -553,7 +553,7 @@
*/
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 e7270ef..d8bad3d 100644
--- a/src/backend/utils/adt/agtype_raw.c
+++ b/src/backend/utils/adt/agtype_raw.c
@@ -172,8 +172,8 @@
* 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 878f184..01a965c 100644
--- a/src/backend/utils/adt/agtype_util.c
+++ b/src/backend/utils/adt/agtype_util.c
@@ -433,14 +433,14 @@
{
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 @@
}
/* Not found */
- pfree(result);
+ pfree_if_not_null(result);
return NULL;
}
@@ -1217,7 +1217,7 @@
{
agtype_iterator *v = it->parent;
- pfree(it);
+ pfree_if_not_null(it);
return v;
}
@@ -1469,9 +1469,9 @@
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 @@
void pfree_agtype_value(agtype_value* value)
{
pfree_agtype_value_content(value);
- pfree(value);
+ pfree_if_not_null(value);
}
/*
@@ -2456,7 +2456,7 @@
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 @@
* 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 @@
{
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 @@
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 71683bf..30dc476 100644
--- a/src/backend/utils/load/ag_load_edges.c
+++ b/src/backend/utils/load/ag_load_edges.c
@@ -307,9 +307,9 @@
}
// 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 b38c7fc..9416781 100644
--- a/src/backend/utils/load/ag_load_labels.c
+++ b/src/backend/utils/load/ag_load_labels.c
@@ -458,11 +458,11 @@
}
/* 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 ea9dabd..a5bb527 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 ebf0035..5bd072f 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 0124dd7..fcf0657 100644
--- a/src/include/utils/agtype.h
+++ b/src/include/utils/agtype.h
@@ -555,6 +555,7 @@
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);