[gmime] Fix for base64 decoder



commit 30ddec4da69590fdeb15efbb833ce0dbb2b70b45
Author: Jeffrey Stedfast <fejj gnome org>
Date:   Wed Sep 1 22:12:05 2010 -0400

    Fix for base64 decoder
    
    2010-09-01  Jeffrey Stedfast  <fejj novell com>
    
    	* gmime/gmime-encodings.c (g_mime_encoding_base64_decode_step):
    	Need to keep state to keep track of the number of ='s we've
    backed
    	out over in case it crosses buffer boundaries.

 ChangeLog               |    6 +++++
 gmime/gmime-encodings.c |   49 ++++++++++++++++++++++++++++++----------------
 2 files changed, 38 insertions(+), 17 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index eb4e88e..80c5ac5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2010-09-01  Jeffrey Stedfast  <fejj novell com>
+
+	* gmime/gmime-encodings.c (g_mime_encoding_base64_decode_step):
+	Need to keep state to keep track of the number of ='s we've backed
+	out over in case it crosses buffer boundaries.
+
 2010-08-30  Jeffrey Stedfast  <fejj novell com>
 
 	* gmime/gmime-param.c (decode_token): Make less strict in order to
diff --git a/gmime/gmime-encodings.c b/gmime/gmime-encodings.c
index 4aabbe7..df8b9d9 100644
--- a/gmime/gmime-encodings.c
+++ b/gmime/gmime-encodings.c
@@ -506,45 +506,60 @@ g_mime_encoding_base64_decode_step (const unsigned char *inbuf, size_t inlen, un
 	const unsigned char *inend;
 	register guint32 saved;
 	unsigned char c;
-	int i;
+	int npad, n, i;
 	
 	inend = inbuf + inlen;
 	outptr = outbuf;
+	inptr = inbuf;
 	
-	/* convert 4 base64 bytes to 3 normal bytes */
+	npad = (*state >> 8) & 0xff;
+	n = *state & 0xff;
 	saved = *save;
-	i = *state;
-	inptr = inbuf;
+	
+	/* convert 4 base64 bytes to 3 normal bytes */
 	while (inptr < inend) {
 		c = gmime_base64_rank[*inptr++];
 		if (c != 0xff) {
 			saved = (saved << 6) | c;
-			i++;
-			if (i == 4) {
+			n++;
+			if (n == 4) {
 				*outptr++ = saved >> 16;
 				*outptr++ = saved >> 8;
 				*outptr++ = saved;
-				i = 0;
+				n = 0;
+				
+				if (npad > 0) {
+					outptr -= npad;
+					npad = 0;
+				}
 			}
 		}
 	}
 	
-	*save = saved;
-	*state = i;
-	
-	/* quick scan back for '=' on the end somewhere */
-	/* fortunately we can drop 1 output char for each trailing = (upto 2) */
-	i = 2;
-	while (inptr > inbuf && i) {
+	/* 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)
-				outptr--;
+			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--;
 		}
 	}
 	
-	/* if i != 0 then there is a truncation error! */
+	*state = (npad << 8) | n;
+	*save = saved;
+	
 	return (outptr - outbuf);
 }
 



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