From ed6f7a0586f79179d12365c258531c726b2cf556 Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Sat, 2 Aug 2025 16:15:37 +0900 Subject: [PATCH v1] pg_dump: Fix incorrect parsing of object types in pg_dump --filter. Previously, pg_dump --filter could misinterpret invalid object types in the filter file as valid ones. For example, the invalid object type "table-data" (likely a typo for the valid "table_data") could be mistakenly recognized as "table", causing pg_dump to succeed when it should have failed. This happened because pg_dump identified tokens as sequences of ASCII alphabetic characters, treating non-alphabetic characters (like hyphens) as token boundaries. As a result, "table-data" was parsed as "table". To fix this, pg_dump --filter now treats tokens as strings of non-space characters separated by spaces or line endings, ensuring invalid types like "table-data" are correctly rejected. Back-patch to v17, where the --filter option was introduced. --- src/bin/pg_dump/filter.c | 26 ++++++++++++--------- src/bin/pg_dump/t/005_pg_dump_filterfile.pl | 14 +++++++---- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/bin/pg_dump/filter.c b/src/bin/pg_dump/filter.c index 7214d514137..71b4bd9a73a 100644 --- a/src/bin/pg_dump/filter.c +++ b/src/bin/pg_dump/filter.c @@ -169,31 +169,35 @@ pg_log_filter_error(FilterStateData *fstate, const char *fmt,...) } /* - * filter_get_keyword - read the next filter keyword from buffer + * filter_get_token - read the next filter token from buffer * - * Search for keywords (limited to ascii alphabetic characters) in - * the passed in line buffer. Returns NULL when the buffer is empty or the first - * char is not alpha. The char '_' is allowed, except as the first character. + * Search for tokens (strings of non-space characters bounded by + * space characters or end of line) in the passed in line buffer. + * Returns NULL when the buffer is empty or no token exists. * The length of the found keyword is returned in the size parameter. */ static const char * -filter_get_keyword(const char **line, int *size) +filter_get_token(const char **line, int *size) { const char *ptr = *line; const char *result = NULL; - /* Set returned length preemptively in case no keyword is found */ + /* Set returned length preemptively in case no token is found */ *size = 0; - /* Skip initial whitespace */ + /* Skip initial space characters */ while (isspace((unsigned char) *ptr)) ptr++; - if (isalpha((unsigned char) *ptr)) + /* + * Grab one token that's the string of non-space characters bounded by + * space characters or end of line. + */ + if (*ptr != '\0' && !isspace((unsigned char) *ptr)) { result = ptr++; - while (isalpha((unsigned char) *ptr) || *ptr == '_') + while (*ptr != '\0' && !isspace((unsigned char) *ptr)) ptr++; *size = ptr - result; @@ -414,7 +418,7 @@ filter_read_item(FilterStateData *fstate, * First we expect sequence of two keywords, {include|exclude} * followed by the object type to operate on. */ - keyword = filter_get_keyword(&str, &size); + keyword = filter_get_token(&str, &size); if (!keyword) { pg_log_filter_error(fstate, @@ -433,7 +437,7 @@ filter_read_item(FilterStateData *fstate, fstate->exit_nicely(1); } - keyword = filter_get_keyword(&str, &size); + keyword = filter_get_token(&str, &size); if (!keyword) { pg_log_filter_error(fstate, _("missing filter object type")); diff --git a/src/bin/pg_dump/t/005_pg_dump_filterfile.pl b/src/bin/pg_dump/t/005_pg_dump_filterfile.pl index f05e8a20e05..d788406add4 100644 --- a/src/bin/pg_dump/t/005_pg_dump_filterfile.pl +++ b/src/bin/pg_dump/t/005_pg_dump_filterfile.pl @@ -418,10 +418,16 @@ command_fails_like( qr/invalid filter command/, "invalid syntax: incorrect filter command"); -# Test invalid object type +# Test invalid object type. +# +# This test also verifies that tokens are correctly recognized as sequences of +# non-space characters separated by spaces or line endings. If the parser +# incorrectly treats non-space delimiters (like hyphens) as token boundaries, +# "table-data" might be misread as the valid object type "table". To catch such +# issues, "table-data" is used here as an intentionally invalid object type. open $inputfile, '>', "$tempdir/inputfile.txt" or die "unable to open filterfile for writing"; -print $inputfile "include xxx"; +print $inputfile "exclude table-data one"; close $inputfile; command_fails_like( @@ -432,8 +438,8 @@ command_fails_like( '--filter' => "$tempdir/inputfile.txt", 'postgres' ], - qr/unsupported filter object type: "xxx"/, - "invalid syntax: invalid object type specified, should be table, schema, foreign_data or data" + qr/unsupported filter object type: "table-data"/, + "invalid syntax: invalid object type specified" ); # Test missing object identifier pattern -- 2.50.1