Bug 1362449 - part 6 - factor out base64url decoding routines; r=erahm
authorNathan Froyd <froydnj@mozilla.com>
Wed, 06 Sep 2017 16:58:37 -0400
changeset 428876 966a99fcb8ce3f5f96d3730b62cbdb9fd2fe00b6
parent 428875 9080c5fb07696d23b40d94c1100ec188cc99212d
child 428877 e364a330eb3eb3452c777f551400c1fa9b9bdcba
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 6 - factor out base64url decoding routines; r=erahm The decoding logic is the same for Base64 and Base64URL; we might as well reuse the routines that we already have for Base64URL decoding so we don't make mistakes in the logic.
xpcom/io/Base64.cpp
--- a/xpcom/io/Base64.cpp
+++ b/xpcom/io/Base64.cpp
@@ -406,16 +406,61 @@ Base64Encode(const nsACString& aBinary, 
 }
 
 nsresult
 Base64Encode(const nsAString& aBinary, nsAString& aBase64)
 {
   return Base64EncodeHelper(aBinary, aBase64);
 }
 
+template<typename Decoder>
+static bool
+Decode4to3(const char* aSrc, uint8_t* aDest, Decoder aToVal)
+{
+  uint8_t w, x, y, z;
+  if (!aToVal(aSrc[0], &w) ||
+      !aToVal(aSrc[1], &x) ||
+      !aToVal(aSrc[2], &y) ||
+      !aToVal(aSrc[3], &z)) {
+    return false;
+  }
+  aDest[0] = w << 2 | x >> 4;
+  aDest[1] = x << 4 | y >> 2;
+  aDest[2] = y << 6 | z;
+  return true;
+}
+
+template<typename Decoder>
+static bool
+Decode3to2(const char* aSrc, uint8_t* aDest, Decoder aToVal)
+{
+  uint8_t w, x, y;
+  if (!aToVal(aSrc[0], &w) ||
+      !aToVal(aSrc[1], &x) ||
+      !aToVal(aSrc[2], &y)) {
+    return false;
+  }
+  aDest[0] = w << 2 | x >> 4;
+  aDest[1] = x << 4 | y >> 2;
+  return true;
+}
+
+template<typename Decoder>
+static bool
+Decode2to1(const char* aSrc, uint8_t* aDest, Decoder aToVal)
+{
+  uint8_t w, x;
+  if (!aToVal(aSrc[0], &w) ||
+      !aToVal(aSrc[1], &x)) {
+    return false;
+  }
+  aDest[0] = w << 2 | x >> 4;
+  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;
   }
@@ -584,44 +629,33 @@ Base64URLDecode(const nsACString& aBase6
 
   if (NS_WARN_IF(!aBinary.SetCapacity(binaryLen, mozilla::fallible))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   aBinary.SetLengthAndRetainStorage(binaryLen);
   uint8_t* binary = aBinary.Elements();
 
   for (; base64Len >= 4; base64Len -= 4) {
-    uint8_t w, x, y, z;
-    if (!Base64URLCharToValue(*base64++, &w) ||
-        !Base64URLCharToValue(*base64++, &x) ||
-        !Base64URLCharToValue(*base64++, &y) ||
-        !Base64URLCharToValue(*base64++, &z)) {
+    if (!Decode4to3(base64, binary, Base64URLCharToValue)) {
       return NS_ERROR_INVALID_ARG;
     }
-    *binary++ = w << 2 | x >> 4;
-    *binary++ = x << 4 | y >> 2;
-    *binary++ = y << 6 | z;
+    base64 += 4;
+    binary += 3;
   }
 
   if (base64Len == 3) {
-    uint8_t w, x, y;
-    if (!Base64URLCharToValue(*base64++, &w) ||
-        !Base64URLCharToValue(*base64++, &x) ||
-        !Base64URLCharToValue(*base64++, &y)) {
+    if (!Decode3to2(base64, binary, Base64URLCharToValue)) {
       return NS_ERROR_INVALID_ARG;
     }
-    *binary++ = w << 2 | x >> 4;
-    *binary++ = x << 4 | y >> 2;
+    binary += 2;
   } else if (base64Len == 2) {
-    uint8_t w, x;
-    if (!Base64URLCharToValue(*base64++, &w) ||
-        !Base64URLCharToValue(*base64++, &x)) {
+    if (!Decode2to1(base64, binary, Base64URLCharToValue)) {
       return NS_ERROR_INVALID_ARG;
     }
-    *binary++ = w << 2 | x >> 4;
+    binary += 1;
   } else if (base64Len) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // Set the length to the actual number of decoded bytes.
   aBinary.TruncateLength(binary - aBinary.Elements());
   return NS_OK;
 }