From eaf271a14944df7df87601827f5f5e4909e38c33 Mon Sep 17 00:00:00 2001 From: "Chao Li (Evan)" Date: Wed, 20 May 2026 08:49:15 +0800 Subject: [PATCH v2] Avoid leaking system path from pg_available_extensions The documentation says that when extension_control_path is set to an empty string, the default '$system' path is still assumed. However, get_extension_control_directories() added the system extension directory with a NULL macro in that case. As a result, pg_available_extensions could expose the expanded system directory path instead of reporting '$system' as the location. Record the implicitly-added system directory with the '$system' macro, so pg_available_extensions reports the documented symbolic location and does not leak the actual system path. Update the extension_control_path TAP test to check the reported location directly. Author: Chao Li Reviewed-by: Lu Feng Reviewed-by: Matheus Alcantara Reviewed-by: Jim Jones Discussion: https://postgr.es/m/357C774A-ECE9-4455-B641-315205D4D9A1@gmail.com --- src/backend/commands/extension.c | 8 +++++--- .../test_extensions/t/001_extension_control_path.pl | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index a330b5fd6ce..d073585c421 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -513,6 +513,7 @@ is_extension_script_filename(const char *filename) static List * get_extension_control_directories(void) { +#define EXTENSION_SYSTEM_MACRO "$system" char sharepath[MAXPGPATH]; char *system_dir; char *ecp; @@ -526,7 +527,7 @@ get_extension_control_directories(void) { ExtensionLocation *location = palloc_object(ExtensionLocation); - location->macro = NULL; + location->macro = pstrdup(EXTENSION_SYSTEM_MACRO); location->loc = system_dir; paths = lappend(paths, location); } @@ -556,10 +557,10 @@ get_extension_control_directories(void) * Substitute the path macro if needed or append "extension" * suffix if it is a custom extension control path. */ - if (strcmp(piece, "$system") == 0) + if (strcmp(piece, EXTENSION_SYSTEM_MACRO) == 0) { location->macro = pstrdup(piece); - mangled = substitute_path_macro(piece, "$system", system_dir); + mangled = substitute_path_macro(piece, EXTENSION_SYSTEM_MACRO, system_dir); } else { @@ -582,6 +583,7 @@ get_extension_control_directories(void) } return paths; +#undef EXTENSION_SYSTEM_MACRO } /* diff --git a/src/test/modules/test_extensions/t/001_extension_control_path.pl b/src/test/modules/test_extensions/t/001_extension_control_path.pl index c1cec0dc622..4a013a7da4b 100644 --- a/src/test/modules/test_extensions/t/001_extension_control_path.pl +++ b/src/test/modules/test_extensions/t/001_extension_control_path.pl @@ -109,10 +109,10 @@ is($ret, "t", "\$system extension is shown correctly in pg_available_extensions"); $ret = $node->safe_psql('postgres', - "set extension_control_path = ''; select count(*) > 0 as ok from pg_available_extensions where name = 'plpgsql'" + "set extension_control_path = ''; select location from pg_available_extensions where name = 'plpgsql'" ); -is($ret, "t", - "\$system extension is shown correctly in pg_available_extensions with empty extension_control_path" +is($ret, "\$system", + "\$system location is shown correctly in pg_available_extensions with empty extension_control_path" ); # Test with an extension that does not exists -- 2.50.1 (Apple Git-155)