From 7ba8c9eb441befd6c3a076e89dbc2897444afcac Mon Sep 17 00:00:00 2001 From: Sami Imseih Date: Thu, 2 Jul 2026 16:15:05 -0500 Subject: [PATCH v1 1/1] Add validations for required callbacks during pgstat_register_kind() pgstat_register_kind() did not validate that required callbacks were set, which could lead to NULL pointer dereferences. For fixed-amount kinds, init_shmem_cb, reset_all_cb, and snapshot_cb are called unconditionally. A missing callback crashes the server at startup or during recovery. For variable-numbered kinds, flush_pending_cb is called unconditionally when flushing pending entries. If pending_size is set but flush_pending_cb is NULL, the server crashes when that callback is run. Add validation checks at registration time for custom kinds. Also, add asserts at the call sites for init_shmem_cb and reset_all_cb to also catch issues in built-in kinds during development. The assert already exists for snapshot_cb. --- src/backend/utils/activity/pgstat.c | 17 +++++++++++++++++ src/backend/utils/activity/pgstat_shmem.c | 1 + 2 files changed, 18 insertions(+) diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c index c4fa14f138f..021a7131532 100644 --- a/src/backend/utils/activity/pgstat.c +++ b/src/backend/utils/activity/pgstat.c @@ -908,7 +908,10 @@ pgstat_reset_of_kind(PgStat_Kind kind) TimestampTz ts = GetCurrentTimestamp(); if (kind_info->fixed_amount) + { + Assert(kind_info->reset_all_cb != NULL); kind_info->reset_all_cb(ts); + } else pgstat_reset_entries_of_kind(kind, ts); } @@ -1533,11 +1536,24 @@ pgstat_register_kind(PgStat_Kind kind, const PgStat_KindInfo *kind_info) ereport(ERROR, (errmsg("custom cumulative statistics property is invalid"), errhint("Custom cumulative statistics require a shared memory size for fixed-numbered objects."))); + if (kind_info->init_shmem_cb == NULL || + kind_info->reset_all_cb == NULL || + kind_info->snapshot_cb == NULL) + ereport(ERROR, + (errmsg("custom cumulative statistics property is invalid"), + errhint("Custom cumulative statistics require init_shmem_cb, reset_all_cb, and snapshot_cb callbacks for fixed-numbered objects."))); if (kind_info->track_entry_count) ereport(ERROR, (errmsg("custom cumulative statistics property is invalid"), errhint("Custom cumulative statistics cannot use entry count tracking for fixed-numbered objects."))); } + else + { + if (kind_info->pending_size > 0 && kind_info->flush_pending_cb == NULL) + ereport(ERROR, + (errmsg("custom cumulative statistics property is invalid"), + errhint("Custom cumulative statistics require a flush_pending_cb callback when pending_size is set."))); + } /* * If pgstat_kind_custom_infos is not available yet, allocate it. @@ -2132,6 +2148,7 @@ pgstat_reset_after_failure(void) if (!kind_info || !kind_info->fixed_amount) continue; + Assert(kind_info->reset_all_cb != NULL); kind_info->reset_all_cb(ts); } diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c index 5ea3f1973f9..d00dbb90f16 100644 --- a/src/backend/utils/activity/pgstat_shmem.c +++ b/src/backend/utils/activity/pgstat_shmem.c @@ -247,6 +247,7 @@ StatsShmemInit(void *arg) ptr = ctl->custom_data[idx]; } + Assert(kind_info->init_shmem_cb != NULL); kind_info->init_shmem_cb(ptr); } } -- 2.50.1 (Apple Git-155)