Commit e17c1b25 authored by Steve Holme's avatar Steve Holme
Browse files

base64: Added basic validation to base64 input string when decoding

A base64 string should be a multiple of 4 characters in length, not
contain any more than 2 padding characters and only contain padding
characters at the end of string. For example: Y3VybA==

Strings such as the following are considered invalid:

Y=   - Invalid length
Y==  - Invalid length
Y=== - More than two padding characters
Y=x= - Padding character contained within string
parent 7d1eb66c
Loading
Loading
Loading
Loading
+15 −4
Original line number Original line Diff line number Diff line
@@ -82,6 +82,7 @@ static void decodeQuantum(unsigned char *dest, const char *src)
CURLcode Curl_base64_decode(const char *src,
CURLcode Curl_base64_decode(const char *src,
                            unsigned char **outptr, size_t *outlen)
                            unsigned char **outptr, size_t *outlen)
{
{
  size_t srcLen = 0;
  size_t length = 0;
  size_t length = 0;
  size_t equalsTerm = 0;
  size_t equalsTerm = 0;
  size_t i;
  size_t i;
@@ -92,21 +93,31 @@ CURLcode Curl_base64_decode(const char *src,


  *outptr = NULL;
  *outptr = NULL;
  *outlen = 0;
  *outlen = 0;
  srcLen = strlen(src);


  /* Check the length of the input string is valid */
  if(!srcLen || srcLen % 4)
    return CURLE_BAD_CONTENT_ENCODING;

  /* Find the position of any = padding characters */
  while((src[length] != '=') && src[length])
  while((src[length] != '=') && src[length])
    length++;
    length++;

  /* A maximum of two = padding characters is allowed */
  /* A maximum of two = padding characters is allowed */
  if(src[length] == '=') {
  if(src[length] == '=') {
    equalsTerm++;
    equalsTerm++;
    if(src[length+equalsTerm] == '=')
    if(src[length+equalsTerm] == '=')
      equalsTerm++;
      equalsTerm++;
  }
  }
  numQuantums = (length + equalsTerm) / 4;
  
  
  /* Don't allocate a buffer if the decoded length is 0 */
  /* Check the = padding characters weren't part way through the input */
  if(numQuantums == 0)
  if(length + equalsTerm != srcLen)
    return CURLE_OK;
    return CURLE_BAD_CONTENT_ENCODING;

  /* Calculate the number of quantums */
  numQuantums = (length + equalsTerm) / 4;


  /* Calculate the size of the decoded string */
  rawlen = (numQuantums * 3) - equalsTerm;
  rawlen = (numQuantums * 3) - equalsTerm;


  /* The buffer must be large enough to make room for the last quantum
  /* The buffer must be large enough to make room for the last quantum
+18 −2
Original line number Original line Diff line number Diff line
@@ -104,11 +104,27 @@ fail_unless(size == 1, "size should be 1");
verify_memory(decoded, "i", 2);
verify_memory(decoded, "i", 2);
Curl_safefree(decoded);
Curl_safefree(decoded);


/* this is an illegal input */
/* This is illegal input as the data is too short */
size = 1; /* not zero */
size = 1; /* not zero */
decoded = &anychar; /* not NULL */
decoded = &anychar; /* not NULL */
rc = Curl_base64_decode("aQ", &decoded, &size);
rc = Curl_base64_decode("aQ", &decoded, &size);
/* return code indiferent, but output shall be as follows */
fail_unless(rc == CURLE_BAD_CONTENT_ENCODING, "return code should be CURLE_BAD_CONTENT_ENCODING");
fail_unless(size == 0, "size should be 0");
fail_if(decoded, "returned pointer should be NULL");

/* This is illegal input as it contains three padding characters */
size = 1; /* not zero */
decoded = &anychar; /* not NULL */
rc = Curl_base64_decode("a===", &decoded, &size);
fail_unless(rc == CURLE_BAD_CONTENT_ENCODING, "return code should be CURLE_BAD_CONTENT_ENCODING");
fail_unless(size == 0, "size should be 0");
fail_if(decoded, "returned pointer should be NULL");

/* This is illegal input as it contains a padding character mid input */
size = 1; /* not zero */
decoded = &anychar; /* not NULL */
rc = Curl_base64_decode("a=Q=", &decoded, &size);
fail_unless(rc == CURLE_BAD_CONTENT_ENCODING, "return code should be CURLE_BAD_CONTENT_ENCODING");
fail_unless(size == 0, "size should be 0");
fail_unless(size == 0, "size should be 0");
fail_if(decoded, "returned pointer should be NULL");
fail_if(decoded, "returned pointer should be NULL");