From 44a1eb291a4224ddfe43d8a423b82d79fa4cfd14 Mon Sep 17 00:00:00 2001 From: Shihao Date: Sat, 19 Sep 2026 10:47:19 -0400 Subject: [PATCH v1 3/3] Reject data after base64 padding in other decoders pg_b64_decode() in src/common and the armor decoder in pgcrypto share the logic fixed in the previous commit. dearmor() took an armor with data after the padding when the CRC matched. Fix both the same way. Author: Shihao Zhong Discussion: https://postgr.es/m/19702-9ed4a131fcfadb9d@postgresql.org --- contrib/pgcrypto/expected/pgp-armor.out | 10 ++++++++++ contrib/pgcrypto/pgp-armor.c | 8 ++++++-- contrib/pgcrypto/sql/pgp-armor.sql | 10 ++++++++++ src/common/base64.c | 7 ++++--- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/contrib/pgcrypto/expected/pgp-armor.out b/contrib/pgcrypto/expected/pgp-armor.out index 0f5ff461805..b3662a642f0 100644 --- a/contrib/pgcrypto/expected/pgp-armor.out +++ b/contrib/pgcrypto/expected/pgp-armor.out @@ -100,6 +100,16 @@ em9va2E= -----END PGP MESSAGE----- '); ERROR: Corrupt ascii-armor +-- corrupt (data after padding) +select dearmor(' +-----BEGIN PGP MESSAGE----- + +YQ== +AAAA +=Pr0b +-----END PGP MESSAGE----- +'); +ERROR: Corrupt ascii-armor -- corrupt (no space after the colon) select * from pgp_armor_headers(' -----BEGIN PGP MESSAGE----- diff --git a/contrib/pgcrypto/pgp-armor.c b/contrib/pgcrypto/pgp-armor.c index bfc90af063d..ddd40d72a6e 100644 --- a/contrib/pgcrypto/pgp-armor.c +++ b/contrib/pgcrypto/pgp-armor.c @@ -119,9 +119,9 @@ pg_base64_decode(const uint8 *src, unsigned len, uint8 *dst) else if (c == '=') { /* - * end sequence + * end sequence, after it only the second "=" of "==" is allowed */ - if (!end) + if (!end || pos != 3) { if (pos == 2) end = 1; @@ -137,6 +137,10 @@ pg_base64_decode(const uint8 *src, unsigned len, uint8 *dst) else return PXE_PGP_CORRUPT_ARMOR; + /* no data is allowed after padding */ + if (end && c != '=') + return PXE_PGP_CORRUPT_ARMOR; + /* * add it to buffer */ diff --git a/contrib/pgcrypto/sql/pgp-armor.sql b/contrib/pgcrypto/sql/pgp-armor.sql index 736b54206f0..d4a4743b4c8 100644 --- a/contrib/pgcrypto/sql/pgp-armor.sql +++ b/contrib/pgcrypto/sql/pgp-armor.sql @@ -55,6 +55,16 @@ em9va2E= -----END PGP MESSAGE----- '); +-- corrupt (data after padding) +select dearmor(' +-----BEGIN PGP MESSAGE----- + +YQ== +AAAA +=Pr0b +-----END PGP MESSAGE----- +'); + -- corrupt (no space after the colon) select * from pgp_armor_headers(' -----BEGIN PGP MESSAGE----- diff --git a/src/common/base64.c b/src/common/base64.c index aaaefc2921a..9cd92cacb59 100644 --- a/src/common/base64.c +++ b/src/common/base64.c @@ -134,8 +134,8 @@ pg_b64_decode(const char *src, int len, uint8 *dst, int dstlen) if (c == '=') { - /* end sequence */ - if (!end) + /* end sequence, after it only the second "=" of "==" is allowed */ + if (!end || pos != 3) { if (pos == 2) end = 1; @@ -155,7 +155,8 @@ pg_b64_decode(const char *src, int len, uint8 *dst, int dstlen) else { b = -1; - if (c > 0 && c < 127) + /* no data is allowed after padding */ + if (c > 0 && c < 127 && !end) b = b64lookup[(unsigned char) c]; if (b < 0) { -- 2.37.1 (Apple Git-137.1)