1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-09 13:09:39 +03:00

Make replace_relid() leave argument unmodified

There are a lot of situations when we share the same pointer to a Bitmapset
structure across different places.  In order to evade undesirable side effects
replace_relid() function should always return a copy.

Reported-by: Richard Guo
Discussion: https://postgr.es/m/CAMbWs4_wJthNtYBL%2BSsebpgF-5L2r5zFFk6xYbS0A78GKOTFHw%40mail.gmail.com
Reviewed-by: Richard Guo, Andres Freund, Ashutosh Bapat, Andrei Lepikhov
This commit is contained in:
Alexander Korotkov
2023-12-27 03:34:29 +02:00
parent 7d58f2342b
commit e0477837ce
3 changed files with 29 additions and 3 deletions

View File

@@ -1522,6 +1522,10 @@ replace_varno_walker(Node *node, ReplaceVarnoContext *ctx)
/*
* Substitute newId by oldId in relids.
*
* We must make a copy of the original Bitmapset before making any
* modifications, because the same pointer to it might be shared among
* different places.
*/
static Bitmapset *
replace_relid(Relids relids, int oldId, int newId)
@@ -1529,12 +1533,13 @@ replace_relid(Relids relids, int oldId, int newId)
if (oldId < 0)
return relids;
/* Delete relid without substitution. */
if (newId < 0)
/* Delete relid without substitution. */
return bms_del_member(relids, oldId);
return bms_del_member(bms_copy(relids), oldId);
/* Substitute newId for oldId. */
if (bms_is_member(oldId, relids))
return bms_add_member(bms_del_member(relids, oldId), newId);
return bms_add_member(bms_del_member(bms_copy(relids), oldId), newId);
return relids;
}