gnunet-svn
[Top][All Lists]
Advanced

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

[libmicrohttpd] branch master updated (3eb2fb6d -> eecdde25)


From: gnunet
Subject: [libmicrohttpd] branch master updated (3eb2fb6d -> eecdde25)
Date: Thu, 09 Jun 2022 15:56:15 +0200

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from 3eb2fb6d Fixed very rare data races when closing upgraded connection
     new d2ec9e93 mhd_str.h: fixed typo in doxy
     new 4866181f MHD_bin_to_hex(): fixed wrong return value (unused currently 
by MHD).
     new b1dd47ab Implemented base64 decoding with thorough checks for the 
input data validity
     new 496dfffc test_str_base64: added test for base64 decoding
     new 483d47c9 Basic Auth: switched to the internal Base64 decoding 
implementation
     new eecdde25 Removed Public Domain base64 decoding files

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/include/microhttpd.h         |   7 +-
 src/microhttpd/.gitignore        |   1 +
 src/microhttpd/Makefile.am       |  12 +-
 src/microhttpd/base64.c          |  85 -----
 src/microhttpd/base64.h          |  26 --
 src/microhttpd/basicauth.c       | 200 +++++------
 src/microhttpd/mhd_str.c         | 114 +++++-
 src/microhttpd/mhd_str.h         |  29 +-
 src/microhttpd/test_str_base64.c | 748 +++++++++++++++++++++++++++++++++++++++
 9 files changed, 997 insertions(+), 225 deletions(-)
 delete mode 100644 src/microhttpd/base64.c
 delete mode 100644 src/microhttpd/base64.h
 create mode 100644 src/microhttpd/test_str_base64.c

diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index ada9af5d..4936e912 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -4670,9 +4670,10 @@ struct MHD_BasicAuthInfo
  * sent by the client
  *
  * @param connection the MHD connection structure
- * @return NULL not valid Basic Authentication header is present in
- *         current request, or pointer to structure with username and
- *         password, which must be freed by #MHD_free().
+ * @return NULL if no valid Basic Authentication header is present in
+ *         current request, or
+ *         pointer to structure with username and password, which must be
+ *         freed by #MHD_free().
  * @note Available since #MHD_VERSION 0x00097517
  * @ingroup authentication
  */
diff --git a/src/microhttpd/.gitignore b/src/microhttpd/.gitignore
index d7050119..daddef33 100644
--- a/src/microhttpd/.gitignore
+++ b/src/microhttpd/.gitignore
@@ -80,3 +80,4 @@ test_postprocessor_md
 /test_set_panic
 /test_auth_parse
 /test_str_quote
+/test_str_base64
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index f6e1e2bd..11e4537c 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -175,8 +175,7 @@ endif
 
 if ENABLE_BAUTH
 libmicrohttpd_la_SOURCES += \
-  basicauth.c basicauth.h \
-  base64.c base64.h
+  basicauth.c basicauth.h
 endif
 
 if ENABLE_HTTPS
@@ -264,6 +263,10 @@ if ENABLE_DAUTH
 check_PROGRAMS += \
   test_str_quote
 endif
+if ENABLE_BAUTH
+check_PROGRAMS += \
+  test_str_base64
+endif
 
 TESTS = $(check_PROGRAMS)
 
@@ -440,10 +443,13 @@ test_sha1_SOURCES = \
 
 test_auth_parse_SOURCES = \
   test_auth_parse.c gen_auth.c gen_auth.h  mhd_str.h mhd_str.c mhd_assert.h
-  
+
 test_str_quote_SOURCES = \
   test_str_quote.c mhd_str.h mhd_str.c mhd_assert.h
 
+test_str_base64_SOURCES = \
+  test_str_base64.c mhd_str.h mhd_str.c mhd_assert.h
+
 test_options_SOURCES = \
   test_options.c
 test_options_LDADD = \
diff --git a/src/microhttpd/base64.c b/src/microhttpd/base64.c
deleted file mode 100644
index 3d2dd3f1..00000000
--- a/src/microhttpd/base64.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * This code implements the BASE64 algorithm.
- * This code is in the public domain; do with it what you wish.
- *
- * @file base64.c
- * @brief This code implements the BASE64 algorithm
- * @author Matthieu Speder
- * @author Karlson2k (Evgeny Grin): fixes and improvements
- */
-#include "mhd_options.h"
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif /* HAVE_STDLIB_H */
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_STDDEF_H
-#include <stddef.h>
-#endif /* HAVE_STDDEF_H */
-#include "base64.h"
-
-static const char base64_digits[] =
-{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-  0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
-  14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26,
-  27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
-  45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-
-char *
-BASE64Decode (const char *src,
-              size_t in_len,
-              size_t *out_len)
-{
-  unsigned char *dest;
-  char *result;
-
-  if (in_len % 4)
-  {
-    /* Wrong base64 string length */
-    return NULL;
-  }
-  dest = (unsigned char *) malloc (in_len / 4 * 3 + 1);
-  result = (char *) dest;
-  if (NULL == result)
-    return NULL; /* out of memory */
-  for (; 0 < in_len && 0 != *src; in_len -= 4)
-  {
-    char a = base64_digits[(unsigned char) *(src++)];
-    char b = base64_digits[(unsigned char) *(src++)];
-    char c = base64_digits[(unsigned char) *(src++)];
-    char d = base64_digits[(unsigned char) *(src++)];
-    if (((char) -1 == a) || (0 == a) || (0 == b) || (0 == c) || (0 == d))
-    {
-      free (result);
-      return NULL;
-    }
-    *(dest++) = (unsigned char) (((unsigned char) a) << 2)
-                | (unsigned char) ((((unsigned char) b) & 0x30) >> 4);
-    if (c == (char) -1)
-      break;
-    *(dest++) = (unsigned char) ((((unsigned char) b) & 0x0f) << 4)
-                | (unsigned char) ((((unsigned char) c) & 0x3c) >> 2);
-    if (d == (char) -1)
-      break;
-    *(dest++) = (unsigned char) ((((unsigned char) c) & 0x03) << 6)
-                | ((unsigned char) d);
-  }
-  *dest = 0;
-  if (NULL != out_len)
-    *out_len = (size_t) (dest - (unsigned char *) result);
-  return result;
-}
-
-
-/* end of base64.c */
diff --git a/src/microhttpd/base64.h b/src/microhttpd/base64.h
deleted file mode 100644
index e5f11319..00000000
--- a/src/microhttpd/base64.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This code implements the BASE64 algorithm.
- * This code is in the public domain; do with it what you wish.
- *
- * @file base64.c
- * @brief This code implements the BASE64 algorithm
- * @author Matthieu Speder
- */
-#ifndef BASE64_H
-#define BASE64_H
-
-#include "mhd_options.h"
-#ifdef HAVE_STDDEF_H
-#include <stddef.h>
-#elif defined(HAVE_STDLIB_H)
-#include <stdlib.h>
-#else
-#include <stdio.h>
-#endif
-
-char *
-BASE64Decode (const char *src,
-              size_t in_len,
-              size_t *out_len);
-
-#endif /* !BASE64_H */
diff --git a/src/microhttpd/basicauth.c b/src/microhttpd/basicauth.c
index fb7bed0f..8c3adbdb 100644
--- a/src/microhttpd/basicauth.c
+++ b/src/microhttpd/basicauth.c
@@ -29,7 +29,6 @@
 #include "platform.h"
 #include "mhd_limits.h"
 #include "internal.h"
-#include "base64.h"
 #include "mhd_compat.h"
 #include "mhd_str.h"
 
@@ -60,9 +59,10 @@ get_rq_bauth_params (struct MHD_Connection *connection)
  * sent by the client
  *
  * @param connection the MHD connection structure
- * @return NULL not valid Basic Authentication header is present in
- *         current request, or pointer to structure with username and
- *         password, which must be freed by #MHD_free().
+ * @return NULL if no valid Basic Authentication header is present in
+ *         current request, or
+ *         pointer to structure with username and password, which must be
+ *         freed by #MHD_free().
  * @note Available since #MHD_VERSION 0x00097517
  * @ingroup authentication
  */
@@ -70,13 +70,8 @@ _MHD_EXTERN struct MHD_BasicAuthInfo *
 MHD_basic_auth_get_username_password3 (struct MHD_Connection *connection)
 {
   const struct MHD_RqBAuth *params;
-  char *decoded;
-  size_t decoded_len;
+  size_t decoded_max_len;
   struct MHD_BasicAuthInfo *ret;
-  size_t username_len;
-  char *colon;
-  size_t password_pos;
-  size_t password_len;
 
   params = get_rq_bauth_params (connection);
 
@@ -86,63 +81,66 @@ MHD_basic_auth_get_username_password3 (struct 
MHD_Connection *connection)
   if ((NULL == params->token68.str) || (0 == params->token68.len))
     return NULL;
 
-  decoded = BASE64Decode (params->token68.str, params->token68.len,
-                          &decoded_len);
-  if ((NULL == decoded) || (0 == decoded_len))
+  decoded_max_len = (params->token68.len / 4) * 3;
+  ret = (struct MHD_BasicAuthInfo *) malloc (sizeof(struct MHD_BasicAuthInfo)
+                                             + decoded_max_len + 1);
+  if (NULL != ret)
   {
+    size_t decoded_len;
+    char *decoded;
+
+    decoded = (char *) (ret + 1);
+    decoded_len = MHD_base64_to_bin_n (params->token68.str, 
params->token68.len,
+                                       decoded, decoded_max_len);
+    mhd_assert (decoded_max_len >= decoded_len);
+    if (0 != decoded_len)
+    {
+      size_t username_len;
+      char *colon;
+
+      colon = memchr (decoded, ':', decoded_len);
+      if (NULL != colon)
+      {
+        size_t password_pos;
+        size_t password_len;
+
+        username_len = (size_t) (colon - decoded);
+        password_pos = username_len + 1;
+        password_len = decoded_len - password_pos;
+        ret->password = decoded + password_pos;
+        ret->password[password_len] = 0;  /* Zero-terminate the string */
+        ret->password_len = password_len;
+      }
+      else
+      {
+        username_len = decoded_len;
+        ret->password = NULL;
+        ret->password_len = 0;
+      }
+      ret->username = decoded;
+      ret->username[username_len] = 0;  /* Zero-terminate the string */
+      ret->username_len = username_len;
+
+      return ret; /* Success exit point */
+    }
 #ifdef HAVE_MESSAGES
-    MHD_DLOG (connection->daemon,
-              _ ("Error decoding Basic Authorization authentication.\n"));
+    else
+      MHD_DLOG (connection->daemon,
+                _ ("Error decoding Basic Authorization authentication.\n"));
 #endif /* HAVE_MESSAGES */
-    if (NULL != decoded)
-      free (decoded);
-    return NULL;
-  }
-  colon = memchr (decoded, ':', decoded_len);
-  if (NULL != colon)
-  {
-    username_len = (size_t) (colon - decoded);
-    password_pos = username_len + 1;
-    password_len = decoded_len - password_pos;
+
+    free (ret);
   }
+#ifdef HAVE_MESSAGES
   else
-    username_len = decoded_len;
-
-  ret = (struct MHD_BasicAuthInfo *) malloc (sizeof(struct MHD_BasicAuthInfo)
-                                             + decoded_len + 1);
-  if (NULL == ret)
   {
-    free (decoded);
-#ifdef HAVE_MESSAGES
     MHD_DLOG (connection->daemon,
               _ ("Failed to allocate memory to process " \
                  "Basic Authorization authentication.\n"));
-#endif /* HAVE_MESSAGES */
-    return NULL;
-  }
-
-  ret->username = (char *) (ret + 1);
-  memcpy (ret->username, decoded, decoded_len);
-  free (decoded);
-  ret->username[username_len] = 0; /* Zero-terminate the string */
-  ret->username_len = username_len;
-  if (NULL != colon)
-  {
-    mhd_assert (decoded_len >= password_pos);
-    mhd_assert (decoded_len > password_pos || 0 == password_len);
-    mhd_assert (decoded_len > password_len);
-    mhd_assert (decoded_len > username_len);
-    ret->password = ret->username + password_pos;
-    ret->password[password_len] = 0; /* Zero-terminate the string */
-    ret->password_len = password_len;
-  }
-  else
-  {
-    ret->password = NULL;
-    ret->password_len = 0;
   }
+#endif /* HAVE_MESSAGES */
 
-  return ret;
+  return NULL; /* Failure exit point */
 }
 
 
@@ -160,69 +158,59 @@ _MHD_EXTERN char *
 MHD_basic_auth_get_username_password (struct MHD_Connection *connection,
                                       char **password)
 {
-  const struct MHD_RqBAuth *params;
-  char *decode;
-  size_t decode_len;
-  const char *separator;
-
-  params = get_rq_bauth_params (connection);
+  struct MHD_BasicAuthInfo *info;
 
-  if (NULL == params)
+  info = MHD_basic_auth_get_username_password3 (connection);
+  if (NULL == info)
     return NULL;
 
-  if ((NULL == params->token68.str) || (0 == params->token68.len))
-    return NULL;
-
-  decode = BASE64Decode (params->token68.str, params->token68.len, 
&decode_len);
-  if ((NULL == decode) || (0 == decode_len))
-  {
-#ifdef HAVE_MESSAGES
-    MHD_DLOG (connection->daemon,
-              _ ("Error decoding basic authentication.\n"));
-#endif
-    if (NULL != decode)
-      free (decode);
-    return NULL;
-  }
-  /* Find user:password pattern */
-  if (NULL != (separator = memchr (decode,
-                                   ':',
-                                   decode_len)))
+  /* For backward compatibility this function must return NULL if
+   * no password is provided */
+  if (NULL != info->password)
   {
-    char *user;
-    size_t user_len;
-    size_t password_len;
-
-    user = decode; /* Reuse already allocated buffer */
-    user_len = (size_t) (separator - decode);
-    user[user_len] = 0;
+    char *username;
 
-    if (NULL == password)
-      return user;
-
-    password_len = decode_len - user_len - 1;
-    *password = (char *) malloc (password_len + 1);
-    if (NULL != *password)
+    username = malloc (info->username_len + 1);
+    if (NULL != username)
     {
-      if (0 != password_len)
-        memcpy (*password, decode + user_len + 1, password_len);
-      (*password)[password_len] = 0;
-
-      return user;
+      memcpy (username, info->username, info->username_len + 1);
+      mhd_assert (0 == username[info->username_len]);
+      if (NULL != password)
+      {
+        *password = malloc (info->password_len + 1);
+        if (NULL != *password)
+        {
+          memcpy (*password, info->password, info->password_len + 1);
+          mhd_assert (0 == (*password)[info->password_len]);
+
+          free (info);
+          return username; /* Success exit point */
+        }
+#ifdef HAVE_MESSAGES
+        else
+          MHD_DLOG (connection->daemon,
+                    _ ("Failed to allocate memory.\n"));
+#endif /* HAVE_MESSAGES */
+      }
+      else
+      {
+        free (info);
+        return username; /* Success exit point */
+      }
+
+      free (username);
     }
 #ifdef HAVE_MESSAGES
     else
       MHD_DLOG (connection->daemon,
                 _ ("Failed to allocate memory.\n"));
 #endif /* HAVE_MESSAGES */
+
   }
-#ifdef HAVE_MESSAGES
-  else
-    MHD_DLOG (connection->daemon,
-              _ ("Basic authentication doesn't contain ':' separator.\n"));
-#endif
-  free (decode);
-  return NULL;
+  free (info);
+  if (NULL != password)
+    *password = NULL;
+  return NULL;  /* Failure exit point */
 }
 
 
diff --git a/src/microhttpd/mhd_str.c b/src/microhttpd/mhd_str.c
index d3d8c594..d90008c0 100644
--- a/src/microhttpd/mhd_str.c
+++ b/src/microhttpd/mhd_str.c
@@ -1383,7 +1383,7 @@ MHD_bin_to_hex (const void *bin,
     hex[i * 2 + 1] = (char) ((j < 10) ? (j + '0') : (j - 10 + 'a'));
   }
   hex[i * 2] = 0;
-  return i;
+  return i * 2;
 }
 
 
@@ -1535,3 +1535,115 @@ MHD_str_quote (const char *unquoted,
 
 
 #endif /* DAUTH_SUPPORT || BAUTH_SUPPORT */
+
+#ifdef BAUTH_SUPPORT
+
+size_t
+MHD_base64_to_bin_n (const char *base64,
+                     size_t base64_len,
+                     void *bin,
+                     size_t bin_size)
+{
+#ifndef MHD_FAVOR_SMALL_CODE
+#define map_type int
+#else  /* MHD_FAVOR_SMALL_CODE */
+#define map_type int8_t
+#endif /* MHD_FAVOR_SMALL_CODE */
+  static const map_type map[] = {
+    /* -1 = invalid char, -2 = padding
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A,  B,  C,  D,  E,  F */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 00..0F 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 10..1F 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,  /* 20..2F 
*/
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,  /* 30..3F 
*/
+    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 40..4F 
*/
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,  /* 50..5F 
*/
+    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 60..6F 
*/
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1   /* 70..7F 
*/
+#ifndef MHD_FAVOR_SMALL_CODE
+    ,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 80..8F 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 90..9F 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* A0..AF 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* B0..BF 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* C0..CF 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* D0..DF 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* E0..EF 
*/
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* F0..FF 
*/
+#endif /* ! MHD_FAVOR_SMALL_CODE */
+  };
+  const uint8_t *const in = (const uint8_t *) base64;
+  uint8_t *const out = (uint8_t *) bin;
+  size_t i;
+  size_t j;
+  if (0 == base64_len)
+    return 0;  /* Nothing to decode */
+  if (0 != base64_len % 4)
+    return 0;  /* Wrong input length */
+  if (base64_len / 4 * 3 - 2 > bin_size)
+    return 0;
+
+  j = 0;
+  for (i = 0; i < (base64_len - 4); i += 4)
+  {
+#ifdef MHD_FAVOR_SMALL_CODE
+    if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3])))
+      return 0;
+#endif /* MHD_FAVOR_SMALL_CODE */
+    if (1)
+    {
+      const map_type v1 = map[in[i + 0]];
+      const map_type v2 = map[in[i + 1]];
+      const map_type v3 = map[in[i + 2]];
+      const map_type v4 = map[in[i + 3]];
+      if ((0 > v1) || (0 > v2) || (0 > v3) || (0 > v4))
+        return 0;
+      out[j + 0] = (uint8_t) ((((uint8_t) v1) << 2) | (((uint8_t) v2) >> 4));
+      out[j + 1] = (uint8_t) ((((uint8_t) v2) << 4) | (((uint8_t) v3) >> 2));
+      out[j + 2] = (uint8_t) ((((uint8_t) v3) << 6) | (((uint8_t) v4)));
+    }
+    j += 3;
+  }
+#ifdef MHD_FAVOR_SMALL_CODE
+  if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3])))
+    return 0;
+#endif /* MHD_FAVOR_SMALL_CODE */
+  if (1)
+  { /* The last four chars block */
+    const map_type v1 = map[in[i + 0]];
+    const map_type v2 = map[in[i + 1]];
+    const map_type v3 = map[in[i + 2]];
+    const map_type v4 = map[in[i + 3]];
+    if ((0 > v1) || (0 > v2))
+      return 0; /* Invalid char or padding at first two positions */
+    mhd_assert (j < bin_size);
+    out[j++] = (uint8_t) ((((uint8_t) v1) << 2) | (((uint8_t) v2) >> 4));
+    if (0 > v3)
+    { /* Third char is either padding or invalid */
+      if ((-2 != v3) || (-2 != v4))
+        return 0;  /* Both two last chars must be padding */
+      if (0 != (uint8_t) (((uint8_t) v2) << 4))
+        return 0;  /* Wrong last char */
+      return j;
+    }
+    if (j >= bin_size)
+      return 0; /* Not enough space */
+    out[j++] = (uint8_t) ((((uint8_t) v2) << 4) | (((uint8_t) v3) >> 2));
+    if (0 > v4)
+    { /* Fourth char is either padding or invalid */
+      if (-2 != v4)
+        return 0;  /* The char must be padding */
+      if (0 != (uint8_t) (((uint8_t) v3) << 6))
+        return 0;  /* Wrong last char */
+      return j;
+    }
+    if (j >= bin_size)
+      return 0; /* Not enough space */
+    out[j++] = (uint8_t) ((((uint8_t) v3) << 6) | (((uint8_t) v4)));
+  }
+  return j;
+#undef map_type
+}
+
+
+#endif /* BAUTH_SUPPORT */
diff --git a/src/microhttpd/mhd_str.h b/src/microhttpd/mhd_str.h
index dbe97352..17921aa1 100644
--- a/src/microhttpd/mhd_str.h
+++ b/src/microhttpd/mhd_str.h
@@ -475,7 +475,7 @@ MHD_uint8_to_str_pad (uint8_t val,
  * hexadecimal digits, zero-terminate the result.
  * @param bin the pointer to the binary data to convert
  * @param size the size in bytes of the binary data to convert
- * @param hex the output buffer, but be at least 2 * @a size + 1
+ * @param hex the output buffer, should be at least 2 * @a size + 1
  * @return The number of characters written to the output buffer,
  *         not including terminating zero.
  */
@@ -583,4 +583,31 @@ MHD_str_quote (const char *unquoted,
 
 #endif /* DAUTH_SUPPORT || BAUTH_SUPPORT */
 
+#ifdef BAUTH_SUPPORT
+
+/**
+ * Convert Base64 encoded string to binary data.
+ * @param base64 the input string with Base64 encoded data, could be NOT zero
+ *               terminated
+ * @param base64_len the number of characters to decode in @a base64 string,
+ *                   valid number must be a multiple of four
+ * @param[out] bin the pointer to the output buffer, the buffer may be altered
+ *                 even if decoding failed
+ * @param bin_size the size of the @a bin buffer in bytes, if the size is
+ *                 at least @a base64_len / 4 * 3 then result will always
+ *                 fit, regardless of the amount of the padding characters
+ * @return 0 if @base64_len is zero, or input string has wrong data (not
+ *         valid Base64 sequence), or @a bin_size is too small;
+ *         non-zero number of bytes written to the @a bin, the number must be
+ *         (base64_len / 4 * 3 - 2), (base64_len / 4 * 3 - 1) or
+ *         (base64_len / 4 * 3), depending on the number of padding characters.
+ */
+size_t
+MHD_base64_to_bin_n (const char *base64,
+                     size_t base64_len,
+                     void *bin,
+                     size_t bin_size);
+
+#endif /* BAUTH_SUPPORT */
+
 #endif /* MHD_STR_H */
diff --git a/src/microhttpd/test_str_base64.c b/src/microhttpd/test_str_base64.c
new file mode 100644
index 00000000..9daa6cb7
--- /dev/null
+++ b/src/microhttpd/test_str_base64.c
@@ -0,0 +1,748 @@
+/*
+  This file is part of libmicrohttpd
+  Copyright (C) 2022 Karlson2k (Evgeny Grin)
+
+  This test tool is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2, or
+  (at your option) any later version.
+
+  This test tool is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+*/
+
+/**
+ * @file microhttpd/test_str_base64.c
+ * @brief  Unit tests for base64 strings processing
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#include "mhd_options.h"
+#include <string.h>
+#include <stdio.h>
+#include "mhd_str.h"
+#include "mhd_assert.h"
+
+#ifndef MHD_STATICSTR_LEN_
+/**
+ * Determine length of static string / macro strings at compile time.
+ */
+#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1)
+#endif /* ! MHD_STATICSTR_LEN_ */
+
+
+#define TEST_BIN_MAX_SIZE 1024
+
+/* return zero if succeed, one otherwise */
+static unsigned int
+expect_decoded_n (const char *const encoded, const size_t encoded_len,
+                  const uint8_t *const decoded, const size_t decoded_size,
+                  const unsigned int line_num)
+{
+  static const char fill_chr = '#';
+  static uint8_t buf[TEST_BIN_MAX_SIZE];
+  size_t res_size;
+  unsigned int ret;
+
+  mhd_assert (NULL != encoded);
+  mhd_assert (NULL != decoded);
+  mhd_assert (TEST_BIN_MAX_SIZE > decoded_size);
+  mhd_assert (encoded_len >= decoded_size);
+  mhd_assert (0 == encoded_len || encoded_len > decoded_size);
+
+  ret = 0;
+  memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
+  res_size = MHD_base64_to_bin_n (encoded, encoded_len, buf, decoded_size);
+
+  if (res_size != decoded_size)
+  {
+    ret = 1;
+    fprintf (stderr,
+             "'MHD_base64_to_bin_n ()' FAILED: Wrong returned value:\n");
+  }
+  else if ((0 != decoded_size) && (0 != memcmp (buf, decoded, decoded_size)))
+  {
+    ret = 1;
+    fprintf (stderr,
+             "'MHD_base64_to_bin_n ()' FAILED: Wrong output binary:\n");
+  }
+  if (0 != ret)
+  {
+    static char prnt[TEST_BIN_MAX_SIZE * 2 + 1];
+    size_t prnt_size;
+    if (TEST_BIN_MAX_SIZE <= res_size * 2)
+    {
+      fprintf (stderr,
+               "\tRESULT  : MHD_base64_to_bin_n ('%.*s', %u, ->(too long), %u)"
+               " -> %u\n",
+               (int) encoded_len, encoded, (unsigned) encoded_len,
+               (unsigned) decoded_size, (unsigned) res_size);
+    }
+    else
+    {
+      prnt_size = MHD_bin_to_hex (buf, res_size, prnt);
+      mhd_assert (2 * res_size == prnt_size);
+
+      fprintf (stderr,
+               "\tRESULT  : MHD_base64_to_bin_n ('%.*s', %u, ->%.*sh, %u)"
+               " -> %u\n",
+               (int) encoded_len, encoded, (unsigned) encoded_len,
+               (int) prnt_size, prnt, (unsigned) decoded_size,
+               (unsigned) res_size);
+    }
+    prnt_size = MHD_bin_to_hex (decoded, decoded_size, prnt);
+    mhd_assert (2 * decoded_size == prnt_size);
+    fprintf (stderr,
+             "\tEXPECTED: MHD_base64_to_bin_n ('%.*s', %u, ->%.*sh, %u)"
+             " -> %u\n",
+             (int) encoded_len, encoded, (unsigned) encoded_len,
+             (int) prnt_size, prnt, (unsigned) decoded_size,
+             (unsigned) decoded_size);
+    fprintf (stderr,
+             "The check is at line: %u\n\n", line_num);
+  }
+  return ret;
+}
+
+
+#define expect_decoded(e,d) \
+        expect_decoded_n(e,MHD_STATICSTR_LEN_(e),\
+                         (const uint8_t*)(d),MHD_STATICSTR_LEN_(d), \
+                         __LINE__)
+
+static unsigned int
+check_decode_str (void)
+{
+  unsigned int r = 0; /**< The number of errors */
+
+  r += expect_decoded ("", "");
+
+  /* Base sequences without padding */
+  r += expect_decoded ("YWFh", "aaa");
+  r += expect_decoded ("YmJi", "bbb");
+  r += expect_decoded ("Y2Nj", "ccc");
+  r += expect_decoded ("ZGRk", "ddd");
+  r += expect_decoded ("bGxs", "lll");
+  r += expect_decoded ("bW1t", "mmm");
+  r += expect_decoded ("bm5u", "nnn");
+  r += expect_decoded ("b29v", "ooo");
+  r += expect_decoded ("d3d3", "www");
+  r += expect_decoded ("eHh4", "xxx");
+  r += expect_decoded ("eXl5", "yyy");
+  r += expect_decoded ("enp6", "zzz");
+  r += expect_decoded ("QUFB", "AAA");
+  r += expect_decoded ("R0dH", "GGG");
+  r += expect_decoded ("TU1N", "MMM");
+  r += expect_decoded ("VFRU", "TTT");
+  r += expect_decoded ("Wlpa", "ZZZ");
+  r += expect_decoded ("MDEy", "012");
+  r += expect_decoded ("MzQ1", "345");
+  r += expect_decoded ("Njc4", "678");
+  r += expect_decoded ("OTAx", "901");
+  r += expect_decoded ("YWFhYWFh", "aaaaaa");
+  r += expect_decoded ("YmJiYmJi", "bbbbbb");
+  r += expect_decoded ("Y2NjY2Nj", "cccccc");
+  r += expect_decoded ("ZGRkZGRk", "dddddd");
+  r += expect_decoded ("bGxsbGxs", "llllll");
+  r += expect_decoded ("bW1tbW1t", "mmmmmm");
+  r += expect_decoded ("bm5ubm5u", "nnnnnn");
+  r += expect_decoded ("b29vb29v", "oooooo");
+  r += expect_decoded ("d3d3d3d3", "wwwwww");
+  r += expect_decoded ("eHh4eHh4", "xxxxxx");
+  r += expect_decoded ("eXl5eXl5", "yyyyyy");
+  r += expect_decoded ("enp6enp6", "zzzzzz");
+  r += expect_decoded ("QUFBQUFB", "AAAAAA");
+  r += expect_decoded ("R0dHR0dH", "GGGGGG");
+  r += expect_decoded ("TU1NTU1N", "MMMMMM");
+  r += expect_decoded ("VFRUVFRU", "TTTTTT");
+  r += expect_decoded ("WlpaWlpa", "ZZZZZZ");
+  r += expect_decoded ("MDEyMDEy", "012012");
+  r += expect_decoded ("MzQ1MzQ1", "345345");
+  r += expect_decoded ("Njc4Njc4", "678678");
+  r += expect_decoded ("OTAxOTAx", "901901");
+
+  /* Various lengths */
+  r += expect_decoded ("YQ==", "a");
+  r += expect_decoded ("YmM=", "bc");
+  r += expect_decoded ("REVGRw==", "DEFG");
+  r += expect_decoded ("MTIzdA==", "123t");
+  r += expect_decoded ("MTIzNDU=", "12345");
+  r += expect_decoded ("VGVzdCBTdHI=", "Test Str");
+  r += expect_decoded ("VGVzdCBzdHJpbmc=", "Test string");
+  r += expect_decoded ("VGVzdCBzdHJpbmcu", "Test string.");
+  r += expect_decoded ("TG9uZ2VyIHN0cmluZw==", "Longer string");
+  r += expect_decoded ("TG9uZ2VyIHN0cmluZy4=", "Longer string.");
+  r += expect_decoded ("TG9uZ2VyIHN0cmluZzIu", "Longer string2.");
+
+  return r;
+}
+
+
+#define expect_decoded_arr(e,a) \
+        expect_decoded_n(e,MHD_STATICSTR_LEN_(e),\
+                         a,(sizeof(a)/sizeof(a[0])), \
+                         __LINE__)
+
+static unsigned int
+check_decode_bin (void)
+{
+  unsigned int r = 0; /**< The number of errors */
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe,
+     0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
+     0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+     0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
+     0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+     0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
+     0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
+     0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
+     0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
+     0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
+     0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
+     0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
+     0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
+     0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
+     0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+     0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2,
+     0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
+     0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+     0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+     0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2,
+     0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
+     0xff };
+    r += expect_decoded_arr ("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISI" 
\
+                             "jJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERU" 
\
+                             "ZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoa" 
\
+                             "WprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouM" 
\
+                             "jY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+" 
\
+                             "wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0t" 
\
+                             "PU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19" 
\
+                             "vf4+fr7/P3+/w==", bin);
+  }
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+     0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
+     0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
+     0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+     0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
+     0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b,
+     0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
+     0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+     0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+     0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+     0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3,
+     0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+     0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
+     0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+     0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
+     0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+     0x0 };
+    r += expect_decoded_arr ("AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiM" 
\
+                             "kJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRk" 
\
+                             "dISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpa" 
\
+                             "mtsbW5vcHFyc3R1dnd4eXp7fH1+f4CBgoOEhYaHiImKi4yN" 
\
+                             "jo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7C" 
\
+                             "xsrO0tba3uLm6u7y9vr/AwcLDxMXGx8jJysvMzc7P0NHS09" 
\
+                             "TV1tfY2drb3N3e3+Dh4uPk5ebn6Onq6+zt7u/w8fLz9PX29" 
\
+                             "/j5+vv8/f7/AA==", bin);
+  }
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 
0x10,
+     0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
+     0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+     0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
+     0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
+     0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+     0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+     0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64,
+     0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+     0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c,
+     0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+     0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94,
+     0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
+     0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac,
+     0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
+     0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4,
+     0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+     0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc,
+     0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+     0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4,
+     0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x0,
+     0x1 };
+    r += expect_decoded_arr ("AgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQ" 
\
+                             "lJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0" 
\
+                             "hJSktMTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa" 
\
+                             "2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SFhoeIiYqLjI2O" 
\
+                             "j5CRkpOUlZaXmJmam5ydnp+goaKjpKWmp6ipqqusra6vsLG" 
\
+                             "ys7S1tre4ubq7vL2+v8DBwsPExcbHyMnKy8zNzs/Q0dLT1N" 
\
+                             "XW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+" 
\
+                             "Pn6+/z9/v8AAQ==", bin);
+  }
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,
+     0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
+     0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+     0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
+     0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
+     0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+     0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+     0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64,
+     0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+     0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c,
+     0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+     0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94,
+     0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
+     0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac,
+     0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
+     0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4,
+     0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+     0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc,
+     0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+     0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4,
+     0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x0,
+     0x1, 0x2 };
+    r += expect_decoded_arr ("AwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCU" 
\
+                             "mJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSE" 
\
+                             "lKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprb" 
\
+                             "G1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P" 
\
+                             "kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbK" 
\
+                             "ztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1d" 
\
+                             "bX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+" 
\
+                             "fr7/P3+/wABAg==", bin);
+  }
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4,
+     0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
+     0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc,
+     0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0,
+     0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4,
+     0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
+     0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac,
+     0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
+     0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94,
+     0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88,
+     0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c,
+     0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
+     0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64,
+     0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58,
+     0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c,
+     0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
+     0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34,
+     0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28,
+     0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c,
+     0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
+     0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1,
+     0x0 };
+    r += expect_decoded_arr ("//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3" 
\
+                             "c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7ur" 
\
+                             "m4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXl" 
\
+                             "pWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRz" 
\
+                             "cnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVB" 
\
+                             "PTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLS" 
\
+                             "wrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKC" 
\
+                             "QgHBgUEAwIBAA==", bin);
+  }
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0x0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5,
+     0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9,
+     0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd,
+     0xdc, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1,
+     0xd0, 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5,
+     0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9,
+     0xb8, 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad,
+     0xac, 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1,
+     0xa0, 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95,
+     0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89,
+     0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d,
+     0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71,
+     0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65,
+     0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59,
+     0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d,
+     0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41,
+     0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35,
+     0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
+     0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d,
+     0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
+     0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3,
+     0x2, 0x1};
+    r += expect_decoded_arr ("AP/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397" 
\
+                             "d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7" 
\
+                             "q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl" 
\
+                             "5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0" 
\
+                             "c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlF" 
\
+                             "QT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi" 
\
+                             "0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLC" 
\
+                             "gkIBwYFBAMCAQ==", bin);
+  }
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0x1, 0x0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 
0xf5,
+     0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9,
+     0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd,
+     0xdc, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1,
+     0xd0, 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5,
+     0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9,
+     0xb8, 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad,
+     0xac, 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1,
+     0xa0, 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95,
+     0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89,
+     0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d,
+     0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71,
+     0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65,
+     0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59,
+     0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d,
+     0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41,
+     0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35,
+     0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
+     0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d,
+     0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
+     0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3,
+     0x2};
+    r += expect_decoded_arr ("AQD//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/" 
\
+                             "e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vL" 
\
+                             "u6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZm" 
\
+                             "JeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1" 
\
+                             "dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1J" 
\
+                             "RUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy" 
\
+                             "4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MC" 
\
+                             "woJCAcGBQQDAg==", bin);
+  }
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0x2, 0x1, 0x0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6,
+     0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea,
+     0xe9, 0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde,
+     0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2,
+     0xd1, 0xd0, 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6,
+     0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba,
+     0xb9, 0xb8, 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae,
+     0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2,
+     0xa1, 0xa0, 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
+     0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a,
+     0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e,
+     0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72,
+     0x71, 0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66,
+     0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a,
+     0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e,
+     0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42,
+     0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
+     0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a,
+     0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
+     0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12,
+     0x11, 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4,
+     0x3};
+    r += expect_decoded_arr ("AgEA//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eD" 
\
+                             "f3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vb" 
\
+                             "y7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuam" 
\
+                             "ZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2" 
\
+                             "dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFN" 
\
+                             "SUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC" 
\
+                             "8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4ND" 
\
+                             "AsKCQgHBgUEAw==", bin);
+  }
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3,
+     0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7,
+     0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, 0xdb,
+     0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, 0xcf,
+     0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3,
+     0xc2, 0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xb7,
+     0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, 0xab,
+     0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, 0x9f,
+     0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93,
+     0x92, 0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87,
+     0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b,
+     0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6f,
+     0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63,
+     0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57,
+     0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, 0x4b,
+     0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f,
+     0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33,
+     0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27,
+     0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b,
+     0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0xf,
+     0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0,
+     0xff};
+    r += expect_decoded_arr ("/v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dz" 
\
+                             "b2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ub" 
\
+                             "i3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWl" 
\
+                             "ZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNy" 
\
+                             "cXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9" 
\
+                             "OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLC" 
\
+                             "sqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJC" 
\
+                             "AcGBQQDAgEA/w==", bin);
+  }
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2,
+     0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7, 0xe6,
+     0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda,
+     0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, 0xcf, 0xce,
+     0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2,
+     0xc1, 0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xb7, 0xb6,
+     0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa,
+     0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, 0x9f, 0x9e,
+     0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92,
+     0x91, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
+     0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a,
+     0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6f, 0x6e,
+     0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62,
+     0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56,
+     0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a,
+     0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3e,
+     0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32,
+     0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
+     0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a,
+     0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0xf, 0xe, 0xd,
+     0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xff,
+     0xfe};
+    r += expect_decoded_arr ("/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nv" 
\
+                             "a2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uL" 
\
+                             "e2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVl" 
\
+                             "JOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3Jx" 
\
+                             "cG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05" 
\
+                             "NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKy" 
\
+                             "opKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIB" 
\
+                             "wYFBAMCAQD//g==", bin);
+  }
+
+  if (1)
+  {
+    static const uint8_t bin[256] =
+    {0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1,
+     0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7, 0xe6, 0xe5,
+     0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9,
+     0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, 0xcf, 0xce, 0xcd,
+     0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1,
+     0xc0, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xb7, 0xb6, 0xb5,
+     0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
+     0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, 0x9f, 0x9e, 0x9d,
+     0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91,
+     0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85,
+     0x84, 0x83, 0x82, 0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79,
+     0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6f, 0x6e, 0x6d,
+     0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61,
+     0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55,
+     0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49,
+     0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3e, 0x3d,
+     0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
+     0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
+     0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19,
+     0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0xf, 0xe, 0xd, 0xc,
+     0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xff, 0xfe,
+     0xfd };
+    r += expect_decoded_arr ("/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29r" 
\
+                             "Z2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7" 
\
+                             "a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk" 
\
+                             "5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFw" 
\
+                             "b25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1" 
\
+                             "MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKi" 
\
+                             "koJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHB" 
\
+                             "gUEAwIBAP/+/Q==", bin);
+  }
+
+  return r;
+}
+
+
+/* return zero if succeed, one otherwise */
+static unsigned int
+expect_fail_n (const char *const encoded, const size_t encoded_len,
+               const unsigned int line_num)
+{
+  static const char fill_chr = '#';
+  static uint8_t buf[TEST_BIN_MAX_SIZE];
+  size_t res_size;
+  unsigned int ret;
+
+  mhd_assert (NULL != encoded);
+  mhd_assert (TEST_BIN_MAX_SIZE > encoded_len);
+
+  ret = 0;
+  memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
+  res_size = MHD_base64_to_bin_n (encoded, encoded_len, buf, sizeof(buf));
+
+  if (res_size != 0)
+  {
+    ret = 1;
+    fprintf (stderr,
+             "'MHD_base64_to_bin_n ()' FAILED: Wrong returned value:\n");
+  }
+  if (0 != ret)
+  {
+    static char prnt[TEST_BIN_MAX_SIZE * 2 + 1];
+    size_t prnt_size;
+    if (TEST_BIN_MAX_SIZE <= res_size * 2)
+    {
+      fprintf (stderr,
+               "\tRESULT  : MHD_base64_to_bin_n ('%.*s', %u, ->(too long), %u)"
+               " -> %u\n",
+               (int) encoded_len, encoded, (unsigned) encoded_len,
+               (unsigned) sizeof(buf), (unsigned) res_size);
+    }
+    else
+    {
+      prnt_size = MHD_bin_to_hex (buf, res_size, prnt);
+      mhd_assert (2 * res_size == prnt_size);
+
+      fprintf (stderr,
+               "\tRESULT  : MHD_base64_to_bin_n ('%.*s', %u, ->%.*sh, %u)"
+               " -> %u\n",
+               (int) encoded_len, encoded, (unsigned) encoded_len,
+               (int) prnt_size, prnt, (unsigned) sizeof(buf),
+               (unsigned) res_size);
+    }
+    fprintf (stderr,
+             "\tEXPECTED: MHD_base64_to_bin_n ('%.*s', %u, ->(empty), %u)"
+             " -> 0\n",
+             (int) encoded_len, encoded, (unsigned) encoded_len,
+             (unsigned) sizeof(buf));
+    fprintf (stderr,
+             "The check is at line: %u\n\n", line_num);
+  }
+  return ret;
+}
+
+
+#define expect_fail(e) \
+        expect_fail_n(e,MHD_STATICSTR_LEN_(e),__LINE__)
+
+
+static unsigned int
+check_fail (void)
+{
+  unsigned int r = 0; /**< The number of errors */
+
+  /* Base sequences with wrong length */
+  r += expect_fail ("YWFh/");
+  r += expect_fail ("YWFh/Q");
+  r += expect_fail ("YWFhE/Q");
+  r += expect_fail ("bW1tbW1t/");
+  r += expect_fail ("bW1tbW1t/Q");
+  r += expect_fail ("bW1tbW1tE/Q");
+
+  /* Base sequences with wrong char */
+  r += expect_fail ("%mJi");
+  r += expect_fail ("Y%Nj");
+  r += expect_fail ("ZG%k");
+  r += expect_fail ("bGx%");
+  r += expect_fail ("#W1t");
+  r += expect_fail ("b#5u");
+  r += expect_fail ("b2#v");
+  r += expect_fail ("d3d#");
+  r += expect_fail ("^Hh4");
+  r += expect_fail ("e^l5");
+  r += expect_fail ("en^6");
+  r += expect_fail ("QUF^");
+  r += expect_fail ("~0dH");
+  r += expect_fail ("T~1N");
+  r += expect_fail ("VF~U");
+  r += expect_fail ("Wlp~");
+  r += expect_fail ("*DEy");
+  r += expect_fail ("M*Q1");
+  r += expect_fail ("Nj*4");
+  r += expect_fail ("OTA*");
+  r += expect_fail ("&WFhYWFh");
+  r += expect_fail ("Y&JiYmJi");
+  r += expect_fail ("Y2&jY2Nj");
+  r += expect_fail ("ZGR&ZGRk");
+  r += expect_fail ("bGxs&Gxs");
+  r += expect_fail ("bW1tb&1t");
+  r += expect_fail ("bm5ubm&u");
+  r += expect_fail ("b29vb29&");
+  r += expect_fail ("!3d3d3d3");
+  r += expect_fail ("e!h4eHh4");
+  r += expect_fail ("eX!5eXl5");
+  r += expect_fail ("enp!enp6");
+  r += expect_fail ("QUFB!UFB");
+  r += expect_fail ("R0dHR!dH");
+  r += expect_fail ("TU1NTU!N");
+  r += expect_fail ("VFRUVFR!");
+
+  /* Bad high-ASCII char */
+  r += expect_fail ("\xff" "WFhYWFh");
+  r += expect_fail ("Y\xfe" "JiYmJi");
+  r += expect_fail ("Y2\xfd" "jY2Nj");
+  r += expect_fail ("ZGR\xfc" "ZGRk");
+  r += expect_fail ("bGxs\xfb" "Gxs");
+  r += expect_fail ("bW1tbW\xfa" "1t");
+  r += expect_fail ("bm5ubm\xf9" "u");
+  r += expect_fail ("b29vb29\xf8");
+  r += expect_fail ("d3d3d3d\x80");
+  r += expect_fail ("eHh4eH\x81" "4");
+  r += expect_fail ("eXl5e\x82" "l5");
+  r += expect_fail ("enp6\x83" "np6");
+  r += expect_fail ("QUF\x84" "QUFB");
+  r += expect_fail ("TU\x85" "NTU1N");
+  r += expect_fail ("V\x86" "RUVFRU");
+  r += expect_fail ("\x87" "lpaWlpa");
+
+  /* Base sequences with wrong padding char */
+  r += expect_fail ("=lpaWlpa");
+  r += expect_fail ("M=EyMDEy");
+  r += expect_fail ("Mz=1MzQ1");
+  r += expect_fail ("Njc=Njc4");
+  r += expect_fail ("OTAx=TAx");
+  r += expect_fail ("ZGRkZ=Rk");
+  r += expect_fail ("bGxsbG=s");
+  r += expect_fail ("bW1tb===");
+  r += expect_fail ("bm5u====");
+
+  /* Bad last char (valid for Base64, but padding part is not zero */
+  r += expect_fail ("TG9uZ2VyIHN0cmluZo==");
+  r += expect_fail ("TG9uZ2VyIHN0cmluZyK=");
+
+  return r;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  unsigned int errcount = 0;
+  (void) argc; (void) argv; /* Unused. Silent compiler warning. */
+  errcount += check_decode_str ();
+  errcount += check_decode_bin ();
+  errcount += check_fail ();
+  if (0 == errcount)
+    printf ("All tests were passed without errors.\n");
+  return errcount == 0 ? 0 : 1;
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]