diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-07-03 17:17:30 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-07-03 17:17:30 +0100 |
commit | cc6cf0e2525823199bce1653ab0bcb731a66a414 (patch) | |
tree | 75592a410b08cc78b2daaffaa2febea5ca2c8649 /src/libutil/str_util.c | |
parent | 5bcf700ce9b09e6183897fb8d51227740eb7d78f (diff) | |
download | rspamd-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.c | 72 |
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); |