On Mon, 21 Sept 2026 at 08:31, Chao Li <[email protected]> wrote:
>
> Hi,
>
> I happened to encounter a psql crash that could not be reproduced reliably 
> with a normal build. However, AddressSanitizer reproduces it consistently.
>
> 1. Build psql with AddressSanitizer
> ```
> % ./configure CFLAGS='-O1 -g -fsanitize=address -fno-omit-frame-pointer' 
> LDFLAGS='-fsanitize=address’
> % make -C src/bin/psql psql
> ```
> Note: On my MacBook, gcc points to clang.
>
> 2. Run psql and set PROMPT1 to an unterminated variable
> ```
> evantest=# \set PROMPT1 '%:aa'
> =================================================================
> ==34121==ERROR: AddressSanitizer: heap-buffer-overflow on address 
> 0x602000001f35 at pc 0x0001024be288 bp 0x00016d976930 sp 0x00016d976928
> READ of size 1 at 0x602000001f35 thread T0
>     #0 0x0001024be284 in get_prompt prompt.c:103
>     #1 0x0001024bc1a8 in MainLoop mainloop.c:166
>     #2 0x0001024ce05c in main startup.c:471
>     #3 0x0001827ac4e0 in start+0x1b4c (dyld:arm64e+0x204e0)
>
> 0x602000001f35 is located 0 bytes after 5-byte region 
> [0x602000001f30,0x602000001f35)
> allocated by thread T0 here:
>     #0 0x000103172b54 in strdup+0x108 
> (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x3ab54)
>     #1 0x0001025080e4 in pg_strdup fe_memutils.c:101
>     #2 0x0001024dcf5c in SetVariable variables.c:316
>     #3 0x0001024952e4 in exec_command_set command.c:2923
>     #4 0x00010248b8b8 in exec_command command.c:445
>     #5 0x0001024889e4 in HandleSlashCmds command.c:260
>     #6 0x0001024bcb70 in MainLoop mainloop.c:499
>     #7 0x0001024ce05c in main startup.c:471
>     #8 0x0001827ac4e0 in start+0x1b4c (dyld:arm64e+0x204e0)
>
> SUMMARY: AddressSanitizer: heap-buffer-overflow prompt.c:103 in get_prompt
> Shadow bytes around the buggy address:
>   0x602000001c80: fa fa 03 fa fa fa 02 fa fa fa 00 03 fa fa 06 fa
>   0x602000001d00: fa fa 02 fa fa fa 00 02 fa fa 00 02 fa fa 00 05
>   0x602000001d80: fa fa 00 02 fa fa 00 07 fa fa 02 fa fa fa 00 02
>   0x602000001e00: fa fa 00 02 fa fa 00 02 fa fa 00 02 fa fa 00 02
>   0x602000001e80: fa fa 00 07 fa fa 00 fa fa fa 00 04 fa fa fd fa
> =>0x602000001f00: fa fa fd fa fa fa[05]fa fa fa fd fa fa fa fa fa
>   0x602000001f80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
>   0x602000002000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
>   0x602000002080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
>   0x602000002100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
>   0x602000002180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
> Shadow byte legend (one shadow byte represents 8 application bytes):
>   Addressable:           00
>   Partially addressable: 01 02 03 04 05 06 07
>   Heap left redzone:       fa
>   Freed heap region:       fd
>   Stack left redzone:      f1
>   Stack mid redzone:       f2
>   Stack right redzone:     f3
>   Stack after return:      f5
>   Stack use after scope:   f8
>   Global redzone:          f9
>   Global init order:       f6
>   Poisoned by user:        f7
>   Container overflow:      fc
>   Array cookie:            ac
>   Intra object redzone:    bb
>   ASan internal:           fe
>   Left alloca redzone:     ca
>   Right alloca redzone:    cb
> ==34121==ABORTING
> zsh: abort      psql -d evantest
> ```
>
> The problem is that the current code assumes a terminating “:" exists. When 
> it does, "p += nameend + 1" makes p point to the terminating colon, and the 
> for loop's increment advances p to the string's terminating '\0'. When the 
> terminating colon is absent, the same assignment already makes p point to 
> '\0', and the for loop's increment advances p one past the end of the string. 
> The next loop condition then dereferences p out of bounds. If that invalid 
> read yields a nonzero value, the loop continues and can perform further 
> out-of-bounds reads.
>
> The fix is straightforward, only advance over the terminating colon when it 
> exists. The same problem also exists for the %\command`` escape.
>
> See the attached patch for details.
>
> Best regards,
> --
> Chao Li (Evan)
> HighGo Software Co., Ltd.
> https://www.highgo.com/
>


Hi!
I think this is indeed a real issue, please register CF item for this.
Looks like this code is dating back to a45195a191 [0], so this bug
exists in all supported versions.

Code fix itself is fine but maybe write it like `if p[1] != NULL` for
consistency.


[0] 
https://github.com/postgres/postgres/blob/a45195a191eec367a4f305bb71ab541d17a3b9f9/src/bin/psql/prompt.c#L227

-- 
Best regards,
Kirill Reshke


Reply via email to