[gmime: 5/8] Simplified base64 decoding logic for handling '=' padding



commit 9407e6347ace3300e34c40dd81f6ee5b705a092e
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Tue Oct 31 17:19:30 2017 -0400

    Simplified base64 decoding logic for handling '=' padding
    
    This also fixes decoding base64 blobs that contain
    '=' padding characters in the middle of the blob.
    
    The old logic could output a nul-byte into the output.

 gmime/gmime-encodings.c |   61 ++++++++++++++++++----------------------------
 1 files changed, 24 insertions(+), 37 deletions(-)
---
diff --git a/gmime/gmime-encodings.c b/gmime/gmime-encodings.c
index 0d24353..0138253 100644
--- a/gmime/gmime-encodings.c
+++ b/gmime/gmime-encodings.c
@@ -511,60 +511,47 @@ g_mime_encoding_base64_decode_step (const unsigned char *inbuf, size_t inlen, un
        register unsigned char *outptr;
        const unsigned char *inend;
        register guint32 saved;
-       unsigned char c;
-       int npad, n, i;
+       unsigned char last[2];
+       unsigned char c, rank;
+       int n;
        
        inend = inbuf + inlen;
        outptr = outbuf;
        inptr = inbuf;
        
-       npad = (*state >> 8) & 0xff;
-       n = *state & 0xff;
        saved = *save;
+       n = *state;
+       
+       if (n < 0) {
+               last[0] = '=';
+               n = -n;
+       } else {
+               last[0] = '\0';
+       }
+       
+       last[1] = '\0';
        
        /* convert 4 base64 bytes to 3 normal bytes */
        while (inptr < inend) {
-               c = gmime_base64_rank[*inptr++];
-               if (c != 0xff) {
-                       saved = (saved << 6) | c;
+               rank = gmime_base64_rank[(c = *inptr++)];
+               if (rank != 0xff) {
+                       saved = (saved << 6) | rank;
+                       last[1] = last[0];
+                       last[0] = c;
                        n++;
                        if (n == 4) {
                                *outptr++ = saved >> 16;
-                               *outptr++ = saved >> 8;
-                               *outptr++ = saved;
+                               if (last[1] != '=')
+                                       *outptr++ = saved >> 8;
+                               if (last[0] != '=')
+                                       *outptr++ = saved;
                                n = 0;
-                               
-                               if (npad > 0) {
-                                       outptr -= npad;
-                                       npad = 0;
-                               }
                        }
                }
        }
        
-       /* quickly scan back for '=' on the end somewhere */
-       /* fortunately we can drop 1 output char for each trailing '=' (up to 2) */
-       for (i = 2; inptr > inbuf && i; ) {
-               inptr--;
-               if (gmime_base64_rank[*inptr] != 0xff) {
-                       if (*inptr == '=' && outptr > outbuf) {
-                               if (n == 0) {
-                                       /* we've got a complete quartet so it's
-                                          safe to drop an output character. */
-                                       outptr--;
-                               } else if (npad < 2) {
-                                       /* keep a record of the number of ='s at
-                                          the end of the input stream, up to 2 */
-                                       npad++;
-                               }
-                       }
-                       
-                       i--;
-               }
-       }
-       
-       *state = (npad << 8) | n;
-       *save = n ? saved : 0;
+       *state = last[0] == '=' ? -n : n;
+       *save = saved;
        
        return (outptr - outbuf);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]