BUG #19702: decode() accepts Base64 payload after terminal padding
Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.
You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:
docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253856psql -h localhost -U postgresBuilt from patchset v2 (message #2), September 20, 2026 at 03:12 PM.
Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:
git clone --branch t253856_2 https://github.com/hackorum-dev/postgres.gitIn a checkout you already have, add the fork once:
git remote add hackorum https://github.com/hackorum-dev/postgres.gitthen, for this patchset and every later one:
git fetch hackorum t253856_2 && git checkout t253856_2Patchset v2 (message #2) is on t253856_2
The following bug has been logged on the website:
Bug reference: 19702
Logged by: Qifan Liu
Email address: imchifan@163.com
PostgreSQL version: 18.6
Operating system: Linux/amd64
Description:
decode() accepts Base64 alphabet characters after terminal '=' padding and
incorporates them into the decoded bytea value. Once terminal padding
completes a Base64 value, only ignorable whitespace may follow. Applications
relying on decode() to validate Base64 input may consequently process
malformed input as valid data.
Steps to reproduce
------------------
Run the following with psql:
\set ON_ERROR_STOP on
SELECT encode(decode('YQ==Yg==', 'base64'), 'hex') AS decoded_hex;
SELECT encode(decode('YQ==AAAA', 'base64'), 'hex') AS
decoded_hex_after_padding;
Actual result
-------------
decoded_hex
-------------
6162
(1 row)
decoded_hex_after_padding
---------------------------
6100
(1 row)
Expected result
---------------
Both decode() calls should reject their input with SQLSTATE 22023 because
Base64 alphabet characters occur after terminal '=' padding. They should not
silently decode the trailing payload.
Additional information
----------------------
The issue was reproduced on PostgreSQL 20devel, PostgreSQL 18.6, and
PostgreSQL 17.11.
Hi Qifan,
Thanks for reporting that issue.
I can reproduce this on master. The decoder sets "end" at the first "="
and never looks at it again, so later data and later "=" all pass
0001 raises an error for anything but whitespace after the padding, the
same rule base32hex already has. 0002 adds tests. 0003 fixes the two
copies of this code, pg_b64_decode() in src/common and the armor decoder
in pgcrypto. dearmor() shows the same bug when the CRC matches.
This rejects input that used to pass, so I am not sure about the back
branches. I would leave that to the committer.
Thanks,
Shihao