| From: | Andrey Rachitskiy <pl0h0yp1(at)gmail(dot)com> |
|---|---|
| To: | ilia(dot)kashintsev(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Re: BUG #19613: pg_restore: several SEGVs in ReadToc() in pg_backup_archiver.c |
| Date: | 2026-08-11 07:05:53 |
| Message-ID: | CAB8bMisXgPyHXQeiPTbemp_uANRXPUgyytbDsMfywJGyAqvDOA@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
Hi, Ilia!
Thanks for the report.
The attached patch
adds a small ReadRequiredStr() helper for fields that must be present in
a valid archive, and keeps ReadStr() for the nullable cases. The error
names the missing field and follows the existing "perhaps a corrupt TOC"
wording.
Verified with the reporter's base64 reproducer under AddressSanitizer:
pg_restore exits with a TOC error and no ASan SEGV.
вт, 11 авг. 2026 г. в 09:55, PG Bug reporting form <noreply(at)postgresql(dot)org>:
> 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;
>
>
>
>
>
--
Regards,
Rachitskiy Andrey
--
Regards,
Rachitskiy Andrey
| Attachment | Content-Type | Size |
|---|---|---|
| 0001-Fix-SEGV-in-ReadToc-on-NULL-ReadStr-results.patch | text/x-patch | 2.9 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Andrey Rachitskiy | 2026-08-11 15:24:19 | Re: BUG #19615: COVAR_POP / COVAR_SAMP / REGR_SXY return 0.0 instead of NaN |
| Previous Message | Andrey Rachitskiy | 2026-08-11 06:30:03 | Re: BUG #19612: SEGV in ParseConfigFp() in guc-file.l |