segmentation fault in pg_restore with corrupt file

From: Jon Snell <jsnell(at)legalserver(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: segmentation fault in pg_restore with corrupt file
Date: 2021-01-21 22:40:46
Message-ID: CF8A97DB-240C-4E9E-826D-743D6AD1C27B@legalserver.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Hi,

While attempting to isolate an error, I noticed that pg_restore segmentation faults on a corrupt file:
$ pg_restore -l clientname.small.dmp
Segmentation fault

The corrupt dump file was generated with pg_dump version Debian 11.10-1.pgdg90+ using (the -t seems to be the source of corruption):
ssh -t example.com PGPASSWORD=passwordhere pg_dump --cluster 11/main -U clientname -d clientname_live --schema-only -Fc > clientname.small.dmp

If it's helpful, I can supply the first 3500 bytes of the problem file, as that is enough to replicate the segmentation fault.

I have replicated the issue both with debian package of postgresql 13.1 (Debian 13.1-1.pgdg100+1) and a fresh checkout of the source (commit 920f853dc948b98a5dc96580c4ee011a302e33e4).

Here is a backtrace from the freshly compiled pg_restore:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7cbe2e3 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0 0x00007ffff7cbe2e3 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff7be5182 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffff7bd83dd in vsscanf () from /lib/x86_64-linux-gnu/libc.so.6
#3 0x00007ffff7bd2b94 in sscanf () from /lib/x86_64-linux-gnu/libc.so.6
#4 0x0000555555564c10 in ReadToc (AH=AH(at)entry=0x5555555a0750)
at pg_backup_archiver.c:2578
#5 0x0000555555566668 in InitArchiveFmt_Custom (AH=AH(at)entry=0x5555555a0750)
at pg_backup_custom.c:185
#6 0x000055555555ea0d in _allocAH (FileSpec=0x7fffffffe5d1 "clientname.small.dmp",
fmt=archUnknown, compression=0, dosync=<optimized out>, mode=archModeRead,
setupWorkerPtr=0x55555555e170 <setupRestoreWorker>)
at pg_backup_archiver.c:2348
#7 0x0000555555559ecc in main (argc=3, argv=0x7fffffffe308)
at pg_restore.c:414
(gdb) fr 4
#4 0x0000555555564c10 in ReadToc (AH=AH(at)entry=0x5555555a0750)
at pg_backup_archiver.c:2578
2578 sscanf(tmp, "%u", &te->catalogId.tableoid);
(gdb) print tmp
$1 = 0x0

As you can see, tmp is NULL in this context because the previous ReadStr returned null, causing sscanf to segfault.

While this isn't a blocking issue for me (since pg was not the source of the corruption), I thought it might be nice for the next person to provide cleaner error handling, possibly this patch:

diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 1f82c6499b..4a07d43cc5 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -2575,6 +2575,8 @@ ReadToc(ArchiveHandle *AH)
if (AH->version >= K_VERS_1_8)
{
tmp = ReadStr(AH);
+ if (tmp == NULL)
+ fatal("Null catalog table oid -- perhaps a corrupt TOC");
sscanf(tmp, "%u", &te->catalogId.tableoid);
free(tmp);
}

thanks,
Jon Snell

Browse pgsql-bugs by date

  From Date Subject
Next Message PG Bug reporting form 2021-01-22 05:37:56 BUG #16833: postgresql 13.1 process crash every hour
Previous Message PG Bug reporting form 2021-01-21 22:16:55 BUG #16832: Interrupted system call when working with large data tables