aboutsummaryrefslogtreecommitdiffstats
path: root/src/libutil/str_util.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2020-07-03 17:17:30 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2020-07-03 17:17:30 +0100
commitcc6cf0e2525823199bce1653ab0bcb731a66a414 (patch)
tree75592a410b08cc78b2daaffaa2febea5ca2c8649 /src/libutil/str_util.c
parent5bcf700ce9b09e6183897fb8d51227740eb7d78f (diff)
downloadrspamd-cc6cf0e2525823199bce1653ab0bcb731a66a414.tar.gz
rspamd-cc6cf0e2525823199bce1653ab0bcb731a66a414.zip
[Fix] Fix rfc based base32 decoding
Diffstat (limited to 'src/libutil/str_util.c')
-rw-r--r--src/libutil/str_util.c72
1 files 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);