From e617b9cf0adf52427dde5ab804d0a8e75d55e7e6 Mon Sep 17 00:00:00 2001 From: Ishjaap Singh Date: Sat, 24 Oct 2026 17:01:52 +0000 Subject: [PATCH v2] psql: Add test for unterminated prompt escapes Exercise %:name: and %`command` prompt escapes, both terminated and missing their closing delimiter. Without the preceding fix, the unterminated cases read past the end of the prompt string. In a build with AddressSanitizer the test then fails; in a normal build the over-read usually goes unnoticed and the test passes either way. --- src/bin/psql/meson.build | 1 + src/bin/psql/t/040_prompt.pl | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 src/bin/psql/t/040_prompt.pl diff --git a/src/bin/psql/meson.build b/src/bin/psql/meson.build index 922b2845..1106698e 100644 --- a/src/bin/psql/meson.build +++ b/src/bin/psql/meson.build @@ -78,6 +78,7 @@ tests += { 't/010_tab_completion.pl', 't/020_cancel.pl', 't/030_pager.pl', + 't/040_prompt.pl', ], }, } diff --git a/src/bin/psql/t/040_prompt.pl b/src/bin/psql/t/040_prompt.pl new file mode 100644 index 00000000..6367aeec --- /dev/null +++ b/src/bin/psql/t/040_prompt.pl @@ -0,0 +1,49 @@ + +# Copyright (c) 2026, PostgreSQL Global Development Group + +# Test psql prompt escapes that are missing their closing delimiter. +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +# If we don't have IO::Pty, forget it, because IPC::Run depends on that +# to support pty connections +eval { require IO::Pty; }; +if ($@) +{ + plan skip_all => 'IO::Pty is needed to run this test'; +} + +my $node = PostgreSQL::Test::Cluster->new('main'); +$node->init; +$node->start; + +my $h = $node->interactive_psql('postgres'); + +# Check that the prompt is displayed as expected after setting PROMPT1. +sub check_prompt +{ + my ($prompt, $pattern, $annotation) = @_; + + my $out = $h->query_until($pattern, "\\set PROMPT1 '$prompt'\n"); + like($out, $pattern, $annotation); +} + +$h->query_until(qr/=# $/, "\\set myvar VAL\n"); + +check_prompt('%:myvar:> ', qr/VAL> $/, 'terminated %:name: escape'); +check_prompt('%`echo cmd`> ', qr/cmd> $/, 'terminated %`command` escape'); + +# An unterminated escape uses the rest of the prompt string as the +# variable name or command. This used to read past the end of the string. +check_prompt('X%:myvar', qr/XVAL$/, 'unterminated %:name escape'); +check_prompt('Y%`echo cmd', qr/Ycmd$/, 'unterminated %`command escape'); +check_prompt('Z%:', qr/Z$/, 'unterminated empty %: escape'); +check_prompt('W%`', qr/W$/, 'unterminated empty %` escape'); + +$h->quit or die "psql returned $?"; + +done_testing(); -- 2.43.0