Bug 1362449 - part 8 - use our base64 decoding routines instead of NSPR's; r=erahm
authorNathan Froyd <froydnj@mozilla.com>
Wed, 06 Sep 2017 16:58:36 -0400
changeset 428878 6fed9af7f5e26f433b08b9b9749800ec9cf82f2d
parent 428877 e364a330eb3eb3452c777f551400c1fa9b9bdcba
child 428879 8454297462a380f62fbdc551649f4086cf44e314
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerserahm
bugs1362449
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1362449 - part 8 - use our base64 decoding routines instead of NSPR's; r=erahm Our base64 decoding routines are a little nicer, and using them is a necessary step to templating all the necessary routines.
xpcom/io/Base64.cpp
--- a/xpcom/io/Base64.cpp
+++ b/xpcom/io/Base64.cpp
@@ -456,31 +456,68 @@ Decode2to1(const T* aSrc, U* aDest, Deco
   return true;
 }
 
 static nsresult
 Base64DecodeHelper(const char* aBase64, uint32_t aBase64Len, char* aBinary,
                    uint32_t* aBinaryLen)
 {
   MOZ_ASSERT(aBinary);
-  if (!PL_Base64Decode(aBase64, aBase64Len, aBinary)) {
-    return NS_ERROR_INVALID_ARG;
+
+  const char* input = aBase64;
+  uint32_t inputLength = aBase64Len;
+  char* binary = aBinary;
+  uint32_t binaryLength = 0;
+
+  // Handle trailing '=' characters.
+  if (inputLength && (inputLength % 4 == 0)) {
+    if (aBase64[inputLength - 1] == '=') {
+      if (aBase64[inputLength - 2] == '=') {
+        inputLength -= 2;
+      } else {
+        inputLength -= 1;
+      }
+    }
   }
 
-  // PL_Base64Decode doesn't null terminate the buffer for us when we pass
-  // the buffer in. Do that manually, taking into account the number of '='
-  // characters we were passed.
-  if (aBase64Len != 0 && aBase64[aBase64Len - 1] == '=') {
-    if (aBase64Len > 1 && aBase64[aBase64Len - 2] == '=') {
-      *aBinaryLen -= 2;
-    } else {
-      *aBinaryLen -= 1;
+  while (inputLength >= 4) {
+    if (!Decode4to3(input, binary, Base64CharToValue<char>)) {
+      return NS_ERROR_INVALID_ARG;
+    }
+
+    input += 4;
+    inputLength -= 4;
+    binary += 3;
+    binaryLength += 3;
+  }
+
+  switch (inputLength) {
+  case 3:
+    if (!Decode3to2(input, binary, Base64CharToValue<char>)) {
+      return NS_ERROR_INVALID_ARG;
     }
+    binaryLength += 2;
+    break;
+  case 2:
+    if (!Decode2to1(input, binary, Base64CharToValue<char>)) {
+      return NS_ERROR_INVALID_ARG;
+    }
+    binaryLength += 1;
+    break;
+  case 1:
+    return NS_ERROR_INVALID_ARG;
+  case 0:
+    break;
+  default:
+    MOZ_CRASH("Too many characters leftover");
   }
-  aBinary[*aBinaryLen] = '\0';
+
+  aBinary[binaryLength] = '\0';
+  *aBinaryLen = binaryLength;
+
   return NS_OK;
 }
 
 nsresult
 Base64Decode(const char* aBase64, uint32_t aBase64Len, char** aBinary,
              uint32_t* aBinaryLen)
 {
   // Check for overflow.