postgres.git / summary / log / commit / refs

commit    ff0c567cbfb7aeca479f5c087d17c85ffb5b2bf7
Author:   Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date:     Mon Jan 20 08:36:35 2020 +0000
First released in: 13.0, 9.5.21, 9.6.17, 10.12, 11.7, 12.2

    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


src/backend/access/brin/brin_inclusion.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c index 24c9a1f8f19..c0e114997b6 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(); [parent: 167fd022ff33]