From 39de8e1567ff0631ab30ac010f6393a028ecdac4 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Fri, 14 Mar 2025 22:56:58 +0100 Subject: [PATCH v1] Fix guc_malloc calls to check for OOM and return false check_createrole_self_grant and check_synchronized_standby_slots were allocating memory on a LOG elevel without checking if the allocation succeeded or not, which would have led to a segfault if it didn't. The remaining calls were using the ERROR level and relied on erroring out rather than returnin false to let the GUC machinery handle it gracefully. Author: Daniel Gustafsson Reported-by: Nikita Bug: #18845 Discussion: https://postgr.es/m/18845-582c6e10247377ec@postgresql.org --- src/backend/access/transam/xlog.c | 4 +++- src/backend/commands/user.c | 2 ++ src/backend/replication/slot.c | 2 ++ src/backend/tcop/backend_startup.c | 4 +++- src/backend/tcop/postgres.c | 4 +++- src/backend/utils/error/elog.c | 8 ++++++-- 6 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 799fc739e18..0c4c5b9a368 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -4791,7 +4791,9 @@ check_wal_consistency_checking(char **newval, void **extra, GucSource source) list_free(elemlist); /* assign new value */ - *extra = guc_malloc(ERROR, (RM_MAX_ID + 1) * sizeof(bool)); + *extra = guc_malloc(LOG, (RM_MAX_ID + 1) * sizeof(bool)); + if (!*extra) + return false; memcpy(*extra, newwalconsistency, (RM_MAX_ID + 1) * sizeof(bool)); return true; } diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 8ae510c623b..0d638e29d00 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -2566,6 +2566,8 @@ check_createrole_self_grant(char **newval, void **extra, GucSource source) list_free(elemlist); result = (unsigned *) guc_malloc(LOG, sizeof(unsigned)); + if (!result) + return false; *result = options; *extra = result; diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 719e531eb90..646ba2a78fa 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -2730,6 +2730,8 @@ check_synchronized_standby_slots(char **newval, void **extra, GucSource source) /* GUC extra value must be guc_malloc'd, not palloc'd */ config = (SyncStandbySlotsConfigData *) guc_malloc(LOG, size); + if (!config) + return false; /* Transform the data into SyncStandbySlotsConfigData */ config->nslotnames = list_length(elemlist); diff --git a/src/backend/tcop/backend_startup.c b/src/backend/tcop/backend_startup.c index 27c0b3c2b04..a07c59ece01 100644 --- a/src/backend/tcop/backend_startup.c +++ b/src/backend/tcop/backend_startup.c @@ -1078,7 +1078,9 @@ check_log_connections(char **newval, void **extra, GucSource source) * We succeeded, so allocate `extra` and save the flags there for use by * assign_log_connections(). */ - *extra = guc_malloc(ERROR, sizeof(int)); + *extra = guc_malloc(LOG, sizeof(int)); + if (!*extra) + return false; *((int *) *extra) = flags; return true; diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 55ab2da299b..0950a7bd1a2 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3617,7 +3617,9 @@ check_restrict_nonsystem_relation_kind(char **newval, void **extra, GucSource so list_free(elemlist); /* Save the flags in *extra, for use by the assign function */ - *extra = guc_malloc(ERROR, sizeof(int)); + *extra = guc_malloc(LOG, sizeof(int)); + if (!*extra) + return false; *((int *) *extra) = flags; return true; diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 860bbd40d42..b891dab3bf6 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -2198,7 +2198,9 @@ check_backtrace_functions(char **newval, void **extra, GucSource source) * whitespace chars to save some memory, but it doesn't seem worth the * trouble. */ - someval = guc_malloc(ERROR, newvallen + 1 + 1); + someval = guc_malloc(LOG, newvallen + 1 + 1); + if (!someval) + return false; for (i = 0, j = 0; i < newvallen; i++) { if ((*newval)[i] == ',') @@ -2283,7 +2285,9 @@ check_log_destination(char **newval, void **extra, GucSource source) pfree(rawstring); list_free(elemlist); - myextra = (int *) guc_malloc(ERROR, sizeof(int)); + myextra = (int *) guc_malloc(LOG, sizeof(int)); + if (!myextra) + return false; *myextra = newlogdest; *extra = myextra; -- 2.39.3 (Apple Git-146)