BUG #19613: pg_restore: several SEGVs in ReadToc() in pg_backup_archiver.c

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: ilia(dot)kashintsev(at)gmail(dot)com
Subject: BUG #19613: pg_restore: several SEGVs in ReadToc() in pg_backup_archiver.c
Date: 2026-08-07 13:37:25
Message-ID: 19613-3a9ffc23ee402382@postgresql.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 19613
Logged by: Ilia Kashintsev
Email address: ilia(dot)kashintsev(at)gmail(dot)com
PostgreSQL version: 19beta2
Operating system: Ubuntu 24.04.4 LTS
Description:

Hello maintainers!
I have found several SEGVs on unknown address in ReadToc().

They occur because return value of numerous ReadStr(AH) calls is never
checked, with sscanf() or strcmp() being called on tmp == NULL.

For example pg_backup_archiver:2738-2739:

tmp = ReadStr(AH);
sscanf(tmp, "%u", &te->catalogId.tableoid); <------

Steps to reproduce:

1) Build the project with ASAN;
sudo mkdir -p /builds2
sudo chown "$(whoami)" /builds2

mkdir -p asan_build
cd asan_build
export CC=clang
export CXX=clang++
export CFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer"
export CXXFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer"
export LDFLAGS="-fsanitize=address"

../postgres/configure --prefix=/builds2/pg-asan
make -j
sudo make install

2) Run the example:

echo 'UEdETVABDDABMAEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwADAAMDAwMDA=' | base64 -d
> inp.bin
/builds2/pg-asan/bin/pg_restore -f dump.sql inp.bin

Sanitizer output:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==247028==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000
(pc 0x778e90f7995d bp 0x7ffe3361c840 sp 0x7ffe3361c818 T0)
==247028==The signal is caused by a READ memory access.
==247028==Hint: address points to the zero page.
#0 0x778e90f7995d in __strlen_avx2
string/../sysdeps/x86_64/multiarch/strlen-avx2.S:76
#1 0x778e90e853d4 in _IO_str_init_static_internal libio/strops.c:41:11
#2 0x778e90e4dd10 in _IO_strfile_read
stdio-common/../libio/strfile.h:90:3
#3 0x778e90e4dd10 in __isoc23_vsscanf
stdio-common/isoc23_vsscanf.c:24:13
#4 0x62420175134d in __isoc23_sscanf
(/builds2/pg-asan/bin/pg_restore+0x6734d) (BuildId:
b947abf32a751f35042d5aa2948e2318357a75a0)
#5 0x62420182553e in ReadToc
/home/reproduce/asan_build/../postgres/src/bin/pg_dump/pg_backup_archiver.c:2739:4
#6 0x62420182c929 in InitArchiveFmt_Custom
/home/reproduce/asan_build/../postgres/src/bin/pg_dump/pg_backup_custom.c:180:3
#7 0x6242018164f1 in _allocAH
/home/reproduce/asan_build/../postgres/src/bin/pg_dump/pg_backup_archiver.c:2470:4
#8 0x624201816b1e in OpenArchive
/home/reproduce/asan_build/../postgres/src/bin/pg_dump/pg_backup_archiver.c:254:7
#9 0x624201807641 in main
/home/reproduce/asan_build/../postgres/src/bin/pg_dump/pg_restore.c:488:7
#10 0x778e90e181c9 in __libc_start_call_main
csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#11 0x778e90e1828a in __libc_start_main csu/../csu/libc-start.c:360:3
#12 0x62420172c984 in _start (/builds2/pg-asan/bin/pg_restore+0x42984)
(BuildId: b947abf32a751f35042d5aa2948e2318357a75a0)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV
string/../sysdeps/x86_64/multiarch/strlen-avx2.S:76 in __strlen_avx2
==247028==ABORTING

Suggested fix:
Checking the return value of ReadStr resolves the issue.

diff --git a/src/bin/pg_dump/pg_backup_archiver.c
b/src/bin/pg_dump/pg_backup_archiver.c
index d7da3fc..3e9ac90 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -2736,18 +2736,26 @@ ReadToc(ArchiveHandle *AH)
if (AH->version >= K_VERS_1_8)
{
tmp = ReadStr(AH);
+ if (tmp == NULL)
+ pg_fatal("corrupt TOC: missing tableoid");
sscanf(tmp, "%u", &te->catalogId.tableoid);
free(tmp);
}
else
te->catalogId.tableoid = InvalidOid;
tmp = ReadStr(AH);
+ if (tmp == NULL)
+ pg_fatal("corrupt TOC: missing oid");
sscanf(tmp, "%u", &te->catalogId.oid);
free(tmp);

te->tag = ReadStr(AH);
- te->desc = ReadStr(AH);
+ if (te->tag == NULL)
+ pg_fatal("corrupt TOC: missing entry tag");

+ te->desc = ReadStr(AH);
+ if (te->desc == NULL)
+ pg_fatal("corrupt TOC: missing entry description");
if (AH->version >= K_VERS_1_11)
{
te->section = ReadInt(AH);
@@ -2804,6 +2812,8 @@ ReadToc(ArchiveHandle *AH)
{
tmp = ReadStr(AH);

+ if (tmp == NULL)
+ pg_fatal("corrupt TOC: missing WITH OIDS
marker");
if (strcmp(tmp, "true") == 0)
is_supported = false;

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Andrey Rachitskiy 2026-08-08 08:23:35 Re: BUG #19441: Backend waits for serializable snapshot indefinitely on removing temp relations
Previous Message PG Bug reporting form 2026-08-07 13:32:09 BUG #19612: SEGV in ParseConfigFp() in guc-file.l