aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-12-18 15:46:44 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2020-12-18 15:46:44 -0500
commit53d4f5fef04653fc495ae385a9c2f78c77e5c7d9 (patch)
tree9f482b546fd9ee18acf39932b3ada3d86d8a23fa
parent2e0fedf0362cc964c4dae42258455b6391051e70 (diff)
downloadpostgresql-53d4f5fef04653fc495ae385a9c2f78c77e5c7d9.tar.gz
postgresql-53d4f5fef04653fc495ae385a9c2f78c77e5c7d9.zip
Avoid memcpy() with same source and destination during relmapper init.
A narrow reading of the C standard says that memcpy(x,x,n) is undefined, although it's hard to envision an implementation that would really misbehave. However, analysis tools such as valgrind might whine about this; accordingly, let's band-aid relmapper.c to not do it. See also 5b630501e, d3f4e8a8a, ad7b48ea0, and other similar fixes. Apparently, none of those folk tried valgrinding initdb? This has been like this for long enough that I'm surprised it hasn't been reported before. Back-patch, just in case anybody wants to use a back branch on a platform that complains about this; we back-patched those earlier fixes too. Discussion: https://postgr.es/m/161790.1608310142@sss.pgh.pa.us
-rw-r--r--src/backend/utils/cache/relmapper.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/src/backend/utils/cache/relmapper.c b/src/backend/utils/cache/relmapper.c
index 671fbb0ed5c..73e45eb4846 100644
--- a/src/backend/utils/cache/relmapper.c
+++ b/src/backend/utils/cache/relmapper.c
@@ -928,8 +928,15 @@ write_relmap_file(bool shared, RelMapFile *newmap,
}
}
- /* Success, update permanent copy */
- memcpy(realmap, newmap, sizeof(RelMapFile));
+ /*
+ * Success, update permanent copy. During bootstrap, we might be working
+ * on the permanent copy itself, in which case skip the memcpy() to avoid
+ * invoking nominally-undefined behavior.
+ */
+ if (realmap != newmap)
+ memcpy(realmap, newmap, sizeof(RelMapFile));
+ else
+ Assert(!send_sinval); /* must be bootstrapping */
/* Critical section done */
if (write_wal)