I found a couple of places where a pgoff_t value, typically a signed 64-bit integer, is cast to a type with a smaller range. I noticed this specifically in error messages, so it's mostly cosmetic. Also, files with a size where this would matter are not expected in many places, but I suspect that the case in basebackup_server.c in the attached patch can actually happen.

The fix is to use the %lld print format and a cast to long long int, which is the style already in most places.

In passing, I also converted a few places that used %llu to print pgoff_t to also use %lld instead. This is mostly for consistency, but it also feels more robust in case a negative value ever sneaks in.
From abdb70a05f0d5b24511a5b915426fb4c1d7000d4 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Fri, 12 Jun 2026 08:53:24 +0200
Subject: [PATCH 1/2] Don't cast pgoff_t to possibly 32-bit types for output

pgoff_t is most likely a 64-bit integer, so casting it to a 32-bit
type for output could lose data.

In one case, the 32-bit size is baked into the protocol, so here we
just add an assertion and document this discrepancy.
---
 src/backend/backup/basebackup_server.c | 8 ++++----
 src/backend/backup/walsummary.c        | 4 ++--
 src/backend/replication/walsender.c    | 2 ++
 src/backend/storage/file/fd.c          | 4 ++--
 4 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/backend/backup/basebackup_server.c 
b/src/backend/backup/basebackup_server.c
index 0d44a148f01..3d44bf71d19 100644
--- a/src/backend/backup/basebackup_server.c
+++ b/src/backend/backup/basebackup_server.c
@@ -176,9 +176,9 @@ bbsink_server_archive_contents(bbsink *sink, size_t len)
                /* short write: complain appropriately */
                ereport(ERROR,
                                (errcode(ERRCODE_DISK_FULL),
-                                errmsg("could not write file \"%s\": wrote 
only %d of %zu bytes at offset %u",
+                                errmsg("could not write file \"%s\": wrote 
only %d of %zu bytes at offset %lld",
                                                FilePathName(mysink->file),
-                                               nbytes, len, (unsigned) 
mysink->filepos),
+                                               nbytes, len, (long long) 
mysink->filepos),
                                 errhint("Check free disk space.")));
        }
 
@@ -269,9 +269,9 @@ bbsink_server_manifest_contents(bbsink *sink, size_t len)
                /* short write: complain appropriately */
                ereport(ERROR,
                                (errcode(ERRCODE_DISK_FULL),
-                                errmsg("could not write file \"%s\": wrote 
only %d of %zu bytes at offset %u",
+                                errmsg("could not write file \"%s\": wrote 
only %d of %zu bytes at offset %lld",
                                                FilePathName(mysink->file),
-                                               nbytes, len, (unsigned) 
mysink->filepos),
+                                               nbytes, len, (long long) 
mysink->filepos),
                                 errhint("Check free disk space.")));
        }
 
diff --git a/src/backend/backup/walsummary.c b/src/backend/backup/walsummary.c
index 0cdc86af30b..48b7bd8c521 100644
--- a/src/backend/backup/walsummary.c
+++ b/src/backend/backup/walsummary.c
@@ -306,9 +306,9 @@ WriteWalSummary(void *wal_summary_io, void *data, int 
length)
        if (nbytes != length)
                ereport(ERROR,
                                (errcode_for_file_access(),
-                                errmsg("could not write file \"%s\": wrote 
only %d of %d bytes at offset %u",
+                                errmsg("could not write file \"%s\": wrote 
only %d of %d bytes at offset %lld",
                                                FilePathName(io->file), nbytes,
-                                               length, (unsigned) io->filepos),
+                                               length, (long long) 
io->filepos),
                                 errhint("Check free disk space.")));
 
        io->filepos += nbytes;
diff --git a/src/backend/replication/walsender.c 
b/src/backend/replication/walsender.c
index c931d9b4fa8..de8c9940877 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -661,6 +661,8 @@ SendTimeLineHistory(TimeLineHistoryCmd *cmd)
                                (errcode_for_file_access(),
                                 errmsg("could not seek to beginning of file 
\"%s\": %m", path)));
 
+       /* XXX might truncate histfilelen */
+       Assert(histfilelen <= UINT32_MAX);
        pq_sendint32(&buf, histfilelen);        /* col2 len */
 
        bytesleft = histfilelen;
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 4cf4717f764..b8a66b3b475 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -1521,8 +1521,8 @@ ReportTemporaryFileUsage(const char *path, pgoff_t size)
        {
                if ((size / 1024) >= log_temp_files)
                        ereport(LOG,
-                                       (errmsg("temporary file: path \"%s\", 
size %lu",
-                                                       path, (unsigned long) 
size)));
+                                       (errmsg("temporary file: path \"%s\", 
size %lld",
+                                                       path, (long long) 
size)));
        }
 }
 
-- 
2.54.0

From 51214bcaf25a3b647932ce93bdc0308e93543431 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Fri, 12 Jun 2026 10:12:08 +0200
Subject: [PATCH 2/2] Print off_t/pgoff_t consistently as %lld

This was the dominant style already, but some places used %llu
instead.  Since off_t/pgoff_t are signed types, using %lld seems a
better match, and it might handle obscure error conditions with
negative values better.
---
 src/bin/pg_combinebackup/reconstruct.c     | 10 +++++-----
 src/bin/pg_dump/pg_backup_tar.c            |  8 ++++----
 src/bin/pg_verifybackup/astreamer_verify.c |  4 ++--
 src/bin/pg_verifybackup/pg_verifybackup.c  |  6 +++---
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/src/bin/pg_combinebackup/reconstruct.c 
b/src/bin/pg_combinebackup/reconstruct.c
index 0541e6dacab..73b38236481 100644
--- a/src/bin/pg_combinebackup/reconstruct.c
+++ b/src/bin/pg_combinebackup/reconstruct.c
@@ -421,10 +421,10 @@ debug_reconstruction(int n_source, rfile **sources, bool 
dry_run)
                        if (fstat(s->fd, &sb) < 0)
                                pg_fatal("could not stat file \"%s\": %m", 
s->filename);
                        if (sb.st_size < s->highest_offset_read)
-                               pg_fatal("file \"%s\" is too short: expected 
%llu, found %llu",
+                               pg_fatal("file \"%s\" is too short: expected 
%lld, found %lld",
                                                 s->filename,
-                                                (unsigned long long) 
s->highest_offset_read,
-                                                (unsigned long long) 
sb.st_size);
+                                                (long long) 
s->highest_offset_read,
+                                                (long long) sb.st_size);
                }
        }
 }
@@ -785,7 +785,7 @@ read_block(const rfile *s, off_t off, uint8 *buffer)
                if (rb < 0)
                        pg_fatal("could not read from file \"%s\": %m", 
s->filename);
                else
-                       pg_fatal("could not read from file \"%s\", offset %llu: 
read %d of %d",
-                                        s->filename, (unsigned long long) off, 
rb, BLCKSZ);
+                       pg_fatal("could not read from file \"%s\", offset %lld: 
read %d of %d",
+                                        s->filename, (long long) off, rb, 
BLCKSZ);
        }
 }
diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c
index 55b1e4e85d0..1f5d55d0365 100644
--- a/src/bin/pg_dump/pg_backup_tar.c
+++ b/src/bin/pg_dump/pg_backup_tar.c
@@ -1169,12 +1169,12 @@ _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th)
 
        len = read_tar_number(&h[TAR_OFFSET_SIZE], 12);
 
-       pg_log_debug("TOC Entry %s at %llu (length %llu, checksum %d)",
-                                tag, (unsigned long long) hPos, (unsigned long 
long) len, sum);
+       pg_log_debug("TOC Entry %s at %lld (length %lld, checksum %d)",
+                                tag, (long long) hPos, (long long) len, sum);
 
        if (chk != sum)
-               pg_fatal("corrupt tar header found in %s (expected %d, computed 
%d) file position %llu",
-                                tag, sum, chk, (unsigned long long) 
ftello(ctx->tarFH));
+               pg_fatal("corrupt tar header found in %s (expected %d, computed 
%d) file position %lld",
+                                tag, sum, chk, (long long) ftello(ctx->tarFH));
 
        th->targetFile = pg_strdup(tag);
        th->fileLen = len;
diff --git a/src/bin/pg_verifybackup/astreamer_verify.c 
b/src/bin/pg_verifybackup/astreamer_verify.c
index 99bd69ce7c9..2578765b0ca 100644
--- a/src/bin/pg_verifybackup/astreamer_verify.c
+++ b/src/bin/pg_verifybackup/astreamer_verify.c
@@ -208,9 +208,9 @@ member_verify_header(astreamer *streamer, astreamer_member 
*member)
        if (m->size != member->size)
        {
                report_backup_error(mystreamer->context,
-                                                       "file \"%s\" has size 
%llu in archive \"%s\" but size %" PRIu64 " in the manifest",
+                                                       "file \"%s\" has size 
%lld in archive \"%s\" but size %" PRIu64 " in the manifest",
                                                        member->pathname,
-                                                       (unsigned long long) 
member->size,
+                                                       (long long) 
member->size,
                                                        
mystreamer->archive_name,
                                                        m->size);
                m->bad = true;
diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c 
b/src/bin/pg_verifybackup/pg_verifybackup.c
index bd4fe635c6f..5c63bea14c7 100644
--- a/src/bin/pg_verifybackup/pg_verifybackup.c
+++ b/src/bin/pg_verifybackup/pg_verifybackup.c
@@ -735,9 +735,9 @@ verify_plain_backup_file(verifier_context *context, char 
*relpath,
        if (m->size != sb.st_size)
        {
                report_backup_error(context,
-                                                       "\"%s\" has size %llu 
on disk but size %llu in the manifest",
-                                                       relpath, (unsigned long 
long) sb.st_size,
-                                                       (unsigned long long) 
m->size);
+                                                       "\"%s\" has size %lld 
on disk but size %" PRIu64 " in the manifest",
+                                                       relpath, (long long) 
sb.st_size,
+                                                       m->size);
                m->bad = true;
        }
 
-- 
2.54.0

Reply via email to