segmentation fault in pg_restore with corrupt file

Previous Topic Next Topic
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

segmentation fault in pg_restore with corrupt file

Jon Snell

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  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/
(gdb) bt
#0  0x00007ffff7cbe2e3 in ?? () from /lib/x86_64-linux-gnu/
#1  0x00007ffff7be5182 in ?? () from /lib/x86_64-linux-gnu/
#2  0x00007ffff7bd83dd in vsscanf () from /lib/x86_64-linux-gnu/
#3  0x00007ffff7bd2b94 in sscanf () from /lib/x86_64-linux-gnu/
#4  0x0000555555564c10 in ReadToc (AH=AH@entry=0x5555555a0750)
    at pg_backup_archiver.c:2578
#5  0x0000555555566668 in InitArchiveFmt_Custom (AH=AH@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@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);

Jon Snell

smime.p7s (5K) Download Attachment