Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Fix crash in BRIN inclusion op functions, due to missing datum copy.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 20 Jan 2020 08:36:35 +0000 (10:36 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 20 Jan 2020 08:36:47 +0000 (10:36 +0200)
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
src/backend/access/brin/brin_inclusion.c

index 6ce355c6a9723e47c62ae4368d29a0e47c53bc7c..e063f40b371a5e7c960f3beee6a2621d30c5c791 100644 (file)
@@ -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();