From 295352adb54faf36fd730922ada032a4bbaaa941 Mon Sep 17 00:00:00 2001 From: Mikhail Kot Date: Tue, 2 Sep 2025 21:02:04 +0100 Subject: [PATCH] fix sshashent access segfault when it's half initialized due to OOM --- src/backend/utils/activity/pgstat_database.c | 3 +++ src/backend/utils/activity/pgstat_function.c | 3 +++ src/backend/utils/activity/pgstat_relation.c | 3 +++ src/backend/utils/activity/pgstat_shmem.c | 13 ++++++++++--- src/backend/utils/activity/pgstat_subscription.c | 3 +++ 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/backend/utils/activity/pgstat_database.c b/src/backend/utils/activity/pgstat_database.c index b31f20d41bc..71e897d684b 100644 --- a/src/backend/utils/activity/pgstat_database.c +++ b/src/backend/utils/activity/pgstat_database.c @@ -430,6 +430,9 @@ pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) PgStatShared_Database *sharedent; PgStat_StatDBEntry *pendingent; + if (!entry_ref) + return false; + pendingent = (PgStat_StatDBEntry *) entry_ref->pending; sharedent = (PgStatShared_Database *) entry_ref->shared_stats; diff --git a/src/backend/utils/activity/pgstat_function.c b/src/backend/utils/activity/pgstat_function.c index 6214f93d36e..02916b80cb2 100644 --- a/src/backend/utils/activity/pgstat_function.c +++ b/src/backend/utils/activity/pgstat_function.c @@ -195,6 +195,9 @@ pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) PgStat_FunctionCounts *localent; PgStatShared_Function *shfuncent; + if (!entry_ref) + return false; + localent = (PgStat_FunctionCounts *) entry_ref->pending; shfuncent = (PgStatShared_Function *) entry_ref->shared_stats; diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c index 69df741cbf6..20dfa137ba6 100644 --- a/src/backend/utils/activity/pgstat_relation.c +++ b/src/backend/utils/activity/pgstat_relation.c @@ -821,6 +821,9 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) PgStat_StatTabEntry *tabentry; /* table entry of shared stats */ PgStat_StatDBEntry *dbentry; /* pending database entry */ + if (!entry_ref) + return false; + dboid = entry_ref->shared_entry->key.dboid; lstats = (PgStat_TableStatus *) entry_ref->pending; shtabstats = (PgStatShared_Relation *) entry_ref->shared_stats; diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c index 62de3474453..76b12b0b1b4 100644 --- a/src/backend/utils/activity/pgstat_shmem.c +++ b/src/backend/utils/activity/pgstat_shmem.c @@ -311,7 +311,12 @@ pgstat_init_entry(PgStat_Kind kind, pg_atomic_init_u32(&shhashent->generation, 0); shhashent->dropped = false; - chunk = dsa_allocate0(pgStatLocal.dsa, pgstat_get_kind_info(kind)->shared_size); + chunk = dsa_allocate_extended(pgStatLocal.dsa, + pgstat_get_kind_info(kind)->shared_size, + DSA_ALLOC_ZERO | DSA_ALLOC_NO_OOM); + if (!chunk) + return NULL; + shheader = dsa_get_address(pgStatLocal.dsa, chunk); shheader->magic = 0xdeadbeef; @@ -508,7 +513,9 @@ pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create, shhashent = dshash_find_or_insert(pgStatLocal.shared_hash, &key, &shfound); if (!shfound) { - shheader = pgstat_init_entry(kind, shhashent); + if ((shheader = pgstat_init_entry(kind, shhashent)) == NULL) + return NULL; + pgstat_acquire_entry_ref(entry_ref, shhashent, shheader); if (created_entry != NULL) @@ -699,7 +706,7 @@ pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, uint64 objid, entry_ref = pgstat_get_entry_ref(kind, dboid, objid, true, NULL); /* lock the shared entry to protect the content, skip if failed */ - if (!pgstat_lock_entry(entry_ref, nowait)) + if (!entry_ref || !pgstat_lock_entry(entry_ref, nowait)) return NULL; return entry_ref; diff --git a/src/backend/utils/activity/pgstat_subscription.c b/src/backend/utils/activity/pgstat_subscription.c index f9a1c831a07..209a37607e4 100644 --- a/src/backend/utils/activity/pgstat_subscription.c +++ b/src/backend/utils/activity/pgstat_subscription.c @@ -105,6 +105,9 @@ pgstat_subscription_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) PgStat_BackendSubEntry *localent; PgStatShared_Subscription *shsubent; + if (!entry_ref) + return false; + localent = (PgStat_BackendSubEntry *) entry_ref->pending; shsubent = (PgStatShared_Subscription *) entry_ref->shared_stats; -- 2.47.2