aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/base64.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/lib/base64.c b/lib/base64.c
index 54e4ed5d7..98b281309 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -93,24 +93,38 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
while((src[length] != '=') && src[length])
length++;
- while(src[length+equalsTerm] == '=')
+ /* A maximum of two = padding characters is allowed */
+ if(src[length] == '=') {
equalsTerm++;
-
+ if(src[length+equalsTerm] == '=')
+ equalsTerm++;
+ }
numQuantums = (length + equalsTerm) / 4;
+ /* Don't allocate a buffer if the decoded length is 0 */
+ if (numQuantums <= 0)
+ return 0;
+
rawlen = (numQuantums * 3) - equalsTerm;
- newstr = malloc(rawlen+1);
+ /* The buffer must be large enough to make room for the last quantum
+ (which may be partially thrown out) and the zero terminator. */
+ newstr = malloc(rawlen+4);
if(!newstr)
return 0;
*outptr = newstr;
+ /* Decode all but the last quantum (which may not decode to a
+ multiple of 3 bytes) */
for(i = 0; i < numQuantums - 1; i++) {
decodeQuantum((unsigned char *)newstr, src);
newstr += 3; src += 4;
}
+ /* This final decode may actually read slightly past the end of the buffer
+ if the input string is missing pad bytes. This will almost always be
+ harmless. */
decodeQuantum(lastQuantum, src);
for(i = 0; i < 3 - equalsTerm; i++)
newstr[i] = lastQuantum[i];