From e624e1fd13dcc754deebfd8a5be8f6fa578e17da Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Mon, 5 Oct 2026 12:46:19 +0900 Subject: [PATCH] Reject CR and LF characters in backup labels The label is written as one line of the backup_label file. A label with a newline added extra lines to the file, and recovery could read those as other fields, failing on them. Characters could also be injected to make recovery behave in inconsistent ways. Trying to use such characters in label names is now rejected, for both pg_backup_start() and BASE_BACKUP. As this is arguably a behavior change, no backpatch is done. I also seriously doubt that anybody is relying on the behavior of pushing some arbitrary data to backup_label files, and even if they do, it would be a very bad idea to contradict what the backend decides to generate. Reported-by: Shallow Author: Shihao Zhong Discussion: https://postgr.es/m/19730-85a6044c9e72774a@postgresql.org --- src/backend/access/transam/xlog.c | 5 +++++ src/test/recovery/t/020_archive_status.pl | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 9ec0be77ca0..25fe4f503b3 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -9995,6 +9995,11 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces, errmsg("backup label too long (max %d bytes)", MAXPGPATH))); + if (strpbrk(backupidstr, "\n\r")) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("backup label contains a newline or carriage return character"))); + strlcpy(state->name, backupidstr, sizeof(state->name)); /* diff --git a/src/test/recovery/t/020_archive_status.pl b/src/test/recovery/t/020_archive_status.pl index 5bb8aa9ec17..94d49751f7c 100644 --- a/src/test/recovery/t/020_archive_status.pl +++ b/src/test/recovery/t/020_archive_status.pl @@ -260,6 +260,19 @@ $cmdret = $primary->psql( stderr => \$stderr); is($cmdret, 3, "psql fails correctly"); like($stderr, qr/backup label too long/, "pg_backup_start fails gracefully"); + +# Newlines and carriage returns are not allowed in backup labels +foreach my $label ("E'one\\nbackup'", "E'one\\rbackup'") +{ + $primary->psql( + 'postgres', + "SELECT pg_backup_start($label)", + stderr => \$stderr); + like( + $stderr, + qr/backup label contains a newline or carriage return character/, + "pg_backup_start rejects label $label"); +} $primary->safe_psql('postgres', "SELECT pg_backup_start('onebackup'); SELECT pg_backup_stop();"); $primary->safe_psql('postgres', "SELECT pg_backup_start('twobackup')");