diff options
author | Alexander Korotkov <akorotkov@postgresql.org> | 2023-12-27 03:34:29 +0200 |
---|---|---|
committer | Alexander Korotkov <akorotkov@postgresql.org> | 2023-12-27 03:57:57 +0200 |
commit | e0477837ce49d73c9f21a5e00143b741ce6e1f89 (patch) | |
tree | e1029bfebccd8160cdfe381d292ba2dfbbc0aae0 /src/backend/optimizer/plan/analyzejoins.c | |
parent | 7d58f2342bd3d2f0474207b63a3a548c29e20a9e (diff) | |
download | postgresql-e0477837ce49d73c9f21a5e00143b741ce6e1f89.tar.gz postgresql-e0477837ce49d73c9f21a5e00143b741ce6e1f89.zip |
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
Diffstat (limited to 'src/backend/optimizer/plan/analyzejoins.c')
-rw-r--r-- | src/backend/optimizer/plan/analyzejoins.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index 6c02fe89085..80739451b7c 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -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; } |