From 743bea6fdc27b88a83fda1de44ba7a0bd02dceb2 Mon Sep 17 00:00:00 2001 From: Diego Fronza Date: Mon, 21 Feb 2022 11:19:05 -0300 Subject: [PATCH] PG-350: Fix bucket time overflow. To check if a bucket has expired, a comparison of the time elapsed since last bucket change was being done in get_next_wbucket() function using the following line: while ((current_usec - current_bucket_usec) > (PGSM_BUCKET_TIME * 1000 * 1000)) The problem is that the expression compares a uint64 (current_usec) with a int32 (PGSM_BUCKET_TIME), if a given user configures a value for pgsm_bucket_time GUC (let's call it T) that could overflow int32 range in the expression T*1000*1000 > 2**31-1, then the result would be a negative integer cast to (uint64), resulting in a large uint64 value that would evaluate the expression as false, thus never updating bucket number. When querying pg_stat_monitor view, for every entry it's verified if the entry has not yet expired by calling IsBucketValid(bucket_number). Using the entry's bucket number the function calculates if the time since the bucket started, using shared global variable pgss->bucket_start_time[bucket_id], is still valid. Since pgss->bucket_start_time is not properly initialized in get_next_wbucket(), the function IsBucketValid() will always return false, thus not listing any entries in the view. --- pg_stat_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pg_stat_monitor.c b/pg_stat_monitor.c index f8ceab3..a685a2d 100644 --- a/pg_stat_monitor.c +++ b/pg_stat_monitor.c @@ -2126,7 +2126,7 @@ get_next_wbucket(pgssSharedState *pgss) * definitely make the while condition to fail, we can stop the loop as another * thread has already updated prev_bucket_usec. */ - while ((current_usec - current_bucket_usec) > (PGSM_BUCKET_TIME * 1000 * 1000)) + while ((current_usec - current_bucket_usec) > ((uint64)PGSM_BUCKET_TIME * 1000LU * 1000LU)) { if (pg_atomic_compare_exchange_u64(&pgss->prev_bucket_usec, ¤t_bucket_usec, current_usec)) {