commit cc6cf0e: [Fix] Fix rfc based base32 decoding

Vsevolod Stakhov vsevolod at highsecure.ru
Fri Jul 3 16:21:08 UTC 2020


Author: Vsevolod Stakhov
Date: 2020-07-03 17:17:30 +0100
URL: https://github.com/rspamd/rspamd/commit/cc6cf0e2525823199bce1653ab0bcb731a66a414 (HEAD -> master)

[Fix] Fix rfc based base32 decoding

---
 src/libutil/str_util.c | 72 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 56 insertions(+), 16 deletions(-)

diff --git a/src/libutil/str_util.c b/src/libutil/str_util.c
index 5245cd516..c503396a2 100644
--- a/src/libutil/str_util.c
+++ b/src/libutil/str_util.c
@@ -826,6 +826,7 @@ rspamd_decode_base32_buf (const gchar *in, gsize inlen, guchar *out, gsize outle
 	guint processed_bits = 0;
 	gsize i;
 	const guchar *b32_dec;
+	bool inverse_bits = true;
 
 	end = out + outlen;
 	o = out;
@@ -836,38 +837,77 @@ rspamd_decode_base32_buf (const gchar *in, gsize inlen, guchar *out, gsize outle
 		break;
 	case RSPAMD_BASE32_BLEACH:
 		b32_dec = b32_dec_bleach;
+		inverse_bits = false;
 		break;
 	case RSPAMD_BASE32_RFC:
 		b32_dec = b32_dec_rfc;
+		inverse_bits = false;
 		break;
 	default:
 		g_assert_not_reached ();
 		abort ();
 	}
 
-	for (i = 0; i < inlen; i ++) {
-		c = (guchar)in[i];
+	if (inverse_bits) {
+		for (i = 0; i < inlen; i++) {
+			c = (guchar) in[i];
 
-		if (processed_bits >= 8) {
-			processed_bits -= 8;
-			*o++ = acc & 0xFF;
-			acc >>= 8;
+			if (processed_bits >= 8) {
+				/* Emit from left to right */
+				processed_bits -= 8;
+				*o++ = acc & 0xFF;
+				acc >>= 8;
+			}
+
+			decoded = b32_dec[c];
+			if (decoded == 0xff || o >= end) {
+				return -1;
+			}
+
+			acc = (decoded << processed_bits) | acc;
+			processed_bits += 5;
 		}
 
-		decoded = b32_dec[c];
-		if (decoded == 0xff || o >= end) {
+		if (processed_bits > 0 && o < end) {
+			*o++ = (acc & 0xFF);
+		}
+		else if (o > end) {
 			return -1;
 		}
-
-		acc = (decoded << processed_bits) | acc;
-		processed_bits += 5;
 	}
+	else {
+		for (i = 0; i < inlen; i++) {
+			c = (guchar) in[i];
 
-	if (processed_bits > 0 && o < end) {
-		*o++ = (acc & 0xFF);
-	}
-	else if (o > end) {
-		return -1;
+			decoded = b32_dec[c];
+			if (decoded == 0xff) {
+				return -1;
+			}
+
+			acc = (acc << 5) | decoded;
+			processed_bits += 5;
+
+			if (processed_bits >= 8) {
+				/* Emit from right to left */
+				processed_bits -= 8;
+
+				/* Output buffer overflow */
+				if (o >= end) {
+					return -1;
+				}
+
+				*o++ = (acc >> processed_bits) & 0xFF;
+				/* Preserve lowers at the higher parts of the input */
+				acc = (acc & ((1u << processed_bits) - 1));
+			}
+		}
+
+		if (processed_bits > 0 && o < end) {
+			*o++ = (acc & 0xFF);
+		}
+		else if (o > end) {
+			return -1;
+		}
 	}
 
 	return (o - out);


More information about the Commits mailing list