v19-0004-Recheck-file-size-at-checksum-time.patch

application/octet-stream

Filename: v19-0004-Recheck-file-size-at-checksum-time.patch
Type: application/octet-stream
Part: 1
Message: Re: backup manifests

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v19-0004
Subject: Recheck file size at checksum time.
File+
src/bin/pg_validatebackup/pg_validatebackup.c 19 0
From 0da940ea2d3cc40a634ad92e21ee8e8e6de3cbe8 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Thu, 2 Apr 2020 14:49:30 -0400
Subject: [PATCH v19 4/4] Recheck file size at checksum time.

---
 src/bin/pg_validatebackup/pg_validatebackup.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/src/bin/pg_validatebackup/pg_validatebackup.c b/src/bin/pg_validatebackup/pg_validatebackup.c
index 5789b3f3a9..f274638500 100644
--- a/src/bin/pg_validatebackup/pg_validatebackup.c
+++ b/src/bin/pg_validatebackup/pg_validatebackup.c
@@ -714,6 +714,7 @@ validate_file_checksum(validator_context *context, manifest_file *m,
 	char	   *relpath = m->pathname;
 	int			fd;
 	int			rc;
+	size_t		bytes_read = 0;
 	uint8		buffer[READ_CHUNK_SIZE];
 	uint8		checksumbuf[PG_CHECKSUM_MAX_LENGTH];
 	int			checksumlen;
@@ -731,7 +732,10 @@ validate_file_checksum(validator_context *context, manifest_file *m,
 
 	/* Read the file chunk by chunk, updating the checksum as we go. */
 	while ((rc = read(fd, buffer, READ_CHUNK_SIZE)) > 0)
+	{
+		bytes_read += rc;
 		pg_checksum_update(&checksum_ctx, buffer, rc);
+	}
 	if (rc < 0)
 		report_backup_error(context, "could not read file \"%s\": %m",
 							relpath);
@@ -748,6 +752,21 @@ validate_file_checksum(validator_context *context, manifest_file *m,
 	if (rc < 0)
 		return;
 
+	/*
+	 * Double-check that we read the expected number of bytes from the file.
+	 * Normally, a file size mismatch would be caught in validate_backup_file
+	 * and this check would never be reached, but this provides additional
+	 * safety and clarity in the event of concurrent modifications or
+	 * filesystem misbehavior.
+	 */
+	if (bytes_read != m->size)
+	{
+		report_backup_error(context,
+							"file \"%s\" should contain %zu bytes, but read %zu bytes",
+							relpath, m->size, bytes_read);
+		return;
+	}
+
 	/* Get the final checksum. */
 	checksumlen = pg_checksum_final(&checksum_ctx, checksumbuf);
 
-- 
2.17.2 (Apple Git-113)