aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2020-01-20 10:36:35 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2020-01-20 10:36:47 +0200
commitda7abcf0f475bfacc064210d15be9e6e31e873f9 (patch)
tree26e426feb50c014cf0f63fc21ad997b351466642
parentd8e877b869cb5dc33a8d96218115fc12e66b73d4 (diff)
downloadpostgresql-da7abcf0f475bfacc064210d15be9e6e31e873f9.tar.gz
postgresql-da7abcf0f475bfacc064210d15be9e6e31e873f9.zip
Fix crash in BRIN inclusion op functions, due to missing datum copy.
The BRIN add_value() and union() functions need to make a longer-lived copy of the argument, if they want to store it in the BrinValues struct also passed as argument. The functions for the "inclusion operator classes" used with box, range and inet types didn't take into account that the union helper function might return its argument as is, without making a copy. Check for that case, and make a copy if necessary. That case arises at least with the range_union() function, when one of the arguments is an 'empty' range: CREATE TABLE brintest (n numrange); CREATE INDEX brinidx ON brintest USING brin (n); INSERT INTO brintest VALUES ('empty'); INSERT INTO brintest VALUES (numrange(0, 2^1000::numeric)); INSERT INTO brintest VALUES ('(-1, 0)'); SELECT brin_desummarize_range('brinidx', 0); SELECT brin_summarize_range('brinidx', 0); Backpatch down to 9.5, where BRIN was introduced. Discussion: https://www.postgresql.org/message-id/e6e1d6eb-0a67-36aa-e779-bcca59167c14%40iki.fi Reviewed-by: Emre Hasegeli, Tom Lane, Alvaro Herrera
-rw-r--r--src/backend/access/brin/brin_inclusion.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 6ce355c6a97..e063f40b371 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -235,8 +235,14 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
Assert(finfo != NULL);
result = FunctionCall2Coll(finfo, colloid,
column->bv_values[INCLUSION_UNION], newval);
- if (!attr->attbyval)
+ if (!attr->attbyval &&
+ DatumGetPointer(result) != DatumGetPointer(column->bv_values[INCLUSION_UNION]))
+ {
pfree(DatumGetPointer(column->bv_values[INCLUSION_UNION]));
+
+ if (result == newval)
+ result = datumCopy(result, attr->attbyval, attr->attlen);
+ }
column->bv_values[INCLUSION_UNION] = result;
PG_RETURN_BOOL(true);
@@ -574,8 +580,14 @@ brin_inclusion_union(PG_FUNCTION_ARGS)
result = FunctionCall2Coll(finfo, colloid,
col_a->bv_values[INCLUSION_UNION],
col_b->bv_values[INCLUSION_UNION]);
- if (!attr->attbyval)
+ if (!attr->attbyval &&
+ DatumGetPointer(result) != DatumGetPointer(col_a->bv_values[INCLUSION_UNION]))
+ {
pfree(DatumGetPointer(col_a->bv_values[INCLUSION_UNION]));
+
+ if (result == col_b->bv_values[INCLUSION_UNION])
+ result = datumCopy(result, attr->attbyval, attr->attlen);
+ }
col_a->bv_values[INCLUSION_UNION] = result;
PG_RETURN_VOID();