Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wAXvI-0004r3-1T for pgsql-bugs@arkaria.postgresql.org; Wed, 08 Apr 2026 18:46:44 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wAXvG-001PK5-2b for pgsql-bugs@arkaria.postgresql.org; Wed, 08 Apr 2026 18:46:43 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wAFq4-0038D0-2g for pgsql-bugs@lists.postgresql.org; Tue, 07 Apr 2026 23:28:09 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wAFq2-00000001COi-1O6y for pgsql-bugs@lists.postgresql.org; Tue, 07 Apr 2026 23:28:08 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=kAu/7DMH/OsRK59o6Gbsa+3w6ZoCWySfkkgZlQuzBgo=; b=bmecUmEW5ibulIo2Hj0+WLs6qx p4pYyLTUA/QshrlrFFyzkw+sm0HSgRl/bGrIRhe6Hj0eufYuODyQw5GgSr7XphqG4CqKR786yvna2 fYaUf2phE7ZuhQOT+AUOlPSXyEulDyaCkPWM9HIf/bRtuDFIJoujlC6URjcTdl3YjUQaFGTORIPr3 zAMIsMlLqohZniYqvrMkYG1iedHmWTJnK6qiKRKw22RiGe2ZWqNbnVYvfysh7MaeAMAzB0LU/cYuk POKAv+S0F04G9FSueRspHhT5DqsimwcYEgsVHBLSj8AnhvU6n2PMxeoGlcX/wR3ZP5wVXKI0gtNhm FKtqd/gw==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wAFq0-0038ej-0g for pgsql-bugs@lists.postgresql.org; Tue, 07 Apr 2026 23:28:05 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wAFpy-001P90-0G for pgsql-bugs@lists.postgresql.org; Tue, 07 Apr 2026 23:28:02 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19452: heap-buffer-overflow in `pg_basebackup --format=tar --gzip` To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: alexander.kurdakov@tantorlabs.ru Reply-To: alexander.kurdakov@tantorlabs.ru, pgsql-bugs@lists.postgresql.org Date: Tue, 07 Apr 2026 23:27:17 +0000 Message-ID: <19452-4e6c86f7c5eb55ac@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19452 Logged by: Alexander Kurdakov Email address: alexander.kurdakov@tantorlabs.ru PostgreSQL version: 18.0 Operating system: Ubuntu 22.04.5 LTS Description: =20 Build (based on Cirrus CI ASan task configuration): ./configure \ --prefix=3D$(pwd)/build \ --enable-cassert \ --enable-tap-tests \ --enable-debug \ CFLAGS=3D"-Og -ggdb -fno-sanitize-recover=3Dall -fsanitize=3Daddress" \ LDFLAGS=3D"-fsanitize=3Daddress" make -j$(nproc) make install export PATH=3D$(pwd)/build/bin:$PATH export ASAN_OPTIONS=3D"print_stacktrace=3D1:disable_coredump=3D0:abort_on_error=3D= 1:detect_leaks=3D0" Reproduction: initdb -D /tmp/pgdata pg_ctl -D /tmp/pgdata -l /tmp/pg.log start pg_basebackup --format=3Dtar --gzip -X fetch --write-recovery-conf \ -D /tmp/backup --no-sync --checkpoint=3Dfast ASan output: =3D=3D192019=3D=3DERROR: AddressSanitizer: heap-buffer-overflow on address 0x5120000002e1 at pc 0x59338d50dc17 bp 0x7ffe6e687f50 sp 0x7ffe6e6876f8 READ of size 287 at 0x5120000002e1 thread T0 #0 __interceptor_memcpy (pg_basebackup+0x9ec16) #1 (/lib/x86_64-linux-gnu/libz.so.1+0x12050) #2 gzwrite (/lib/x86_64-linux-gnu/libz.so.1+0x12219) #3 astreamer_gzip_writer_content astreamer_gzip.c:162 #4 astreamer_content astreamer.h:140 #5 astreamer_tar_archiver_content astreamer_tar.c:435 #6 astreamer_content astreamer.h:140 #7 astreamer_tar_parser_content astreamer_tar.c:225 #8 astreamer_content astreamer.h:140 #9 ReceiveArchiveStreamChunk pg_basebackup.c:1441 #10 ReceiveCopyData pg_basebackup.c:1046 0x5120000002e1 is located 0 bytes to the right of 289-byte region allocated by pqGetCopyData3 (fe-protocol3.c:1931) Analysis: In astreamer_tar_parser_content(), the ASTREAMER_MEMBER_TRAILER case passes the wrong pointer to astreamer_content(). astreamer_buffer_until() accumulates padding bytes into bbs_buffer and advances *data past the consumed bytes. The server always sends tar padding as a separate CopyData message (_tarWritePadding calls bbsink_archive_contents with exactly pad_bytes bytes), so after buffering, *data points one byte past the end of the malloc'd PQgetCopyData() buffer. The code passes this stale *data pointer instead of streamer->bbs_buffer.data. The downstream gzip writer's deflate() then reads pad_bytes bytes of out-of-bounds memory. Any file whose size is not a multiple of 512 triggers this. PG_VERSION (3 bytes, padding=3D509) and postgresql.auto.conf (88 bytes, padding=3D424) are present in every initdb, so the overflow happens on every run with the flags above. Fix (pass bbs_buffer.data instead of data): --- a/src/fe_utils/astreamer_tar.c +++ b/src/fe_utils/astreamer_tar.c @@ -222,7 +222,8 @@ /* OK, now we can send it. */ astreamer_content(mystreamer->base.bbs_next, &mystreamer->member, - data, mystreamer->pad_bytes_expected, + mystreamer->base.bbs_buffer.data, + mystreamer->pad_bytes_expected, ASTREAMER_MEMBER_TRAILER);