LCOV - code coverage report
Current view: top level - lib/gl - base64.c (source / functions) Hit Total Coverage
Test: GNU SASL Lines: 145 147 98.6 %
Date: 2012-05-28 Functions: 9 9 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 102 110 92.7 %

           Branch data     Line data    Source code
       1                 :            : /* base64.c -- Encode binary data using printable characters.
       2                 :            :    Copyright (C) 1999-2001, 2004-2006, 2009-2012 Free Software Foundation, Inc.
       3                 :            : 
       4                 :            :    This program is free software; you can redistribute it and/or modify
       5                 :            :    it under the terms of the GNU Lesser General Public License as published by
       6                 :            :    the Free Software Foundation; either version 2.1, or (at your option)
       7                 :            :    any later version.
       8                 :            : 
       9                 :            :    This program is distributed in the hope that it will be useful,
      10                 :            :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :            :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12                 :            :    GNU Lesser General Public License for more details.
      13                 :            : 
      14                 :            :    You should have received a copy of the GNU Lesser General Public License
      15                 :            :    along with this program; if not, see <http://www.gnu.org/licenses/>.  */
      16                 :            : 
      17                 :            : /* Written by Simon Josefsson.  Partially adapted from GNU MailUtils
      18                 :            :  * (mailbox/filter_trans.c, as of 2004-11-28).  Improved by review
      19                 :            :  * from Paul Eggert, Bruno Haible, and Stepan Kasal.
      20                 :            :  *
      21                 :            :  * See also RFC 4648 <http://www.ietf.org/rfc/rfc4648.txt>.
      22                 :            :  *
      23                 :            :  * Be careful with error checking.  Here is how you would typically
      24                 :            :  * use these functions:
      25                 :            :  *
      26                 :            :  * bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
      27                 :            :  * if (!ok)
      28                 :            :  *   FAIL: input was not valid base64
      29                 :            :  * if (out == NULL)
      30                 :            :  *   FAIL: memory allocation error
      31                 :            :  * OK: data in OUT/OUTLEN
      32                 :            :  *
      33                 :            :  * size_t outlen = base64_encode_alloc (in, inlen, &out);
      34                 :            :  * if (out == NULL && outlen == 0 && inlen != 0)
      35                 :            :  *   FAIL: input too long
      36                 :            :  * if (out == NULL)
      37                 :            :  *   FAIL: memory allocation error
      38                 :            :  * OK: data in OUT/OUTLEN.
      39                 :            :  *
      40                 :            :  */
      41                 :            : 
      42                 :            : #include <config.h>
      43                 :            : 
      44                 :            : /* Get prototype. */
      45                 :            : #include "base64.h"
      46                 :            : 
      47                 :            : /* Get malloc. */
      48                 :            : #include <stdlib.h>
      49                 :            : 
      50                 :            : /* Get UCHAR_MAX. */
      51                 :            : #include <limits.h>
      52                 :            : 
      53                 :            : #include <string.h>
      54                 :            : 
      55                 :            : /* C89 compliant way to cast 'char' to 'unsigned char'. */
      56                 :            : static inline unsigned char
      57                 :      35389 : to_uchar (char ch)
      58                 :            : {
      59                 :      35389 :   return ch;
      60                 :            : }
      61                 :            : 
      62                 :            : /* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
      63                 :            :    If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
      64                 :            :    possible.  If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
      65                 :            :    terminate the output buffer. */
      66                 :            : void
      67                 :        500 : base64_encode (const char *restrict in, size_t inlen,
      68                 :            :                char *restrict out, size_t outlen)
      69                 :            : {
      70                 :            :   static const char b64str[64] =
      71                 :            :     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      72                 :            : 
      73 [ +  + ][ +  - ]:       3685 :   while (inlen && outlen)
      74                 :            :     {
      75                 :       3192 :       *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
      76         [ +  + ]:       3192 :       if (!--outlen)
      77                 :          2 :         break;
      78                 :       3190 :       *out++ = b64str[((to_uchar (in[0]) << 4)
      79         [ +  + ]:       3190 :                        + (--inlen ? to_uchar (in[1]) >> 4 : 0))
      80                 :       3190 :                       & 0x3f];
      81         [ +  + ]:       3190 :       if (!--outlen)
      82                 :          1 :         break;
      83         [ +  + ]:       6300 :       *out++ =
      84                 :            :         (inlen
      85                 :       3111 :          ? b64str[((to_uchar (in[1]) << 2)
      86         [ +  + ]:       3111 :                    + (--inlen ? to_uchar (in[2]) >> 6 : 0))
      87                 :       3111 :                   & 0x3f]
      88                 :            :          : '=');
      89         [ +  + ]:       3189 :       if (!--outlen)
      90                 :          1 :         break;
      91         [ +  + ]:       3188 :       *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
      92         [ +  + ]:       3188 :       if (!--outlen)
      93                 :          3 :         break;
      94         [ +  + ]:       3185 :       if (inlen)
      95                 :       2934 :         inlen--;
      96         [ +  + ]:       3185 :       if (inlen)
      97                 :       2727 :         in += 3;
      98                 :            :     }
      99                 :            : 
     100         [ +  + ]:        500 :   if (outlen)
     101                 :        492 :     *out = '\0';
     102                 :        500 : }
     103                 :            : 
     104                 :            : /* Allocate a buffer and store zero terminated base64 encoded data
     105                 :            :    from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
     106                 :            :    the length of the encoded data, excluding the terminating zero.  On
     107                 :            :    return, the OUT variable will hold a pointer to newly allocated
     108                 :            :    memory that must be deallocated by the caller.  If output string
     109                 :            :    length would overflow, 0 is returned and OUT is set to NULL.  If
     110                 :            :    memory allocation failed, OUT is set to NULL, and the return value
     111                 :            :    indicates length of the requested memory block, i.e.,
     112                 :            :    BASE64_LENGTH(inlen) + 1. */
     113                 :            : size_t
     114                 :        491 : base64_encode_alloc (const char *in, size_t inlen, char **out)
     115                 :            : {
     116                 :        491 :   size_t outlen = 1 + BASE64_LENGTH (inlen);
     117                 :            : 
     118                 :            :   /* Check for overflow in outlen computation.
     119                 :            :    *
     120                 :            :    * If there is no overflow, outlen >= inlen.
     121                 :            :    *
     122                 :            :    * If the operation (inlen + 2) overflows then it yields at most +1, so
     123                 :            :    * outlen is 0.
     124                 :            :    *
     125                 :            :    * If the multiplication overflows, we lose at least half of the
     126                 :            :    * correct value, so the result is < ((inlen + 2) / 3) * 2, which is
     127                 :            :    * less than (inlen + 2) * 0.66667, which is less than inlen as soon as
     128                 :            :    * (inlen > 4).
     129                 :            :    */
     130         [ +  + ]:        491 :   if (inlen > outlen)
     131                 :            :     {
     132                 :          1 :       *out = NULL;
     133                 :          1 :       return 0;
     134                 :            :     }
     135                 :            : 
     136                 :        490 :   *out = malloc (outlen);
     137         [ -  + ]:        490 :   if (!*out)
     138                 :          0 :     return outlen;
     139                 :            : 
     140                 :        490 :   base64_encode (in, inlen, *out, outlen);
     141                 :            : 
     142                 :        491 :   return outlen - 1;
     143                 :            : }
     144                 :            : 
     145                 :            : /* With this approach this file works independent of the charset used
     146                 :            :    (think EBCDIC).  However, it does assume that the characters in the
     147                 :            :    Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255.  POSIX
     148                 :            :    1003.1-2001 require that char and unsigned char are 8-bit
     149                 :            :    quantities, though, taking care of that problem.  But this may be a
     150                 :            :    potential problem on non-POSIX C99 platforms.
     151                 :            : 
     152                 :            :    IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
     153                 :            :    as the formal parameter rather than "x".  */
     154                 :            : #define B64(_)                                  \
     155                 :            :   ((_) == 'A' ? 0                               \
     156                 :            :    : (_) == 'B' ? 1                             \
     157                 :            :    : (_) == 'C' ? 2                             \
     158                 :            :    : (_) == 'D' ? 3                             \
     159                 :            :    : (_) == 'E' ? 4                             \
     160                 :            :    : (_) == 'F' ? 5                             \
     161                 :            :    : (_) == 'G' ? 6                             \
     162                 :            :    : (_) == 'H' ? 7                             \
     163                 :            :    : (_) == 'I' ? 8                             \
     164                 :            :    : (_) == 'J' ? 9                             \
     165                 :            :    : (_) == 'K' ? 10                            \
     166                 :            :    : (_) == 'L' ? 11                            \
     167                 :            :    : (_) == 'M' ? 12                            \
     168                 :            :    : (_) == 'N' ? 13                            \
     169                 :            :    : (_) == 'O' ? 14                            \
     170                 :            :    : (_) == 'P' ? 15                            \
     171                 :            :    : (_) == 'Q' ? 16                            \
     172                 :            :    : (_) == 'R' ? 17                            \
     173                 :            :    : (_) == 'S' ? 18                            \
     174                 :            :    : (_) == 'T' ? 19                            \
     175                 :            :    : (_) == 'U' ? 20                            \
     176                 :            :    : (_) == 'V' ? 21                            \
     177                 :            :    : (_) == 'W' ? 22                            \
     178                 :            :    : (_) == 'X' ? 23                            \
     179                 :            :    : (_) == 'Y' ? 24                            \
     180                 :            :    : (_) == 'Z' ? 25                            \
     181                 :            :    : (_) == 'a' ? 26                            \
     182                 :            :    : (_) == 'b' ? 27                            \
     183                 :            :    : (_) == 'c' ? 28                            \
     184                 :            :    : (_) == 'd' ? 29                            \
     185                 :            :    : (_) == 'e' ? 30                            \
     186                 :            :    : (_) == 'f' ? 31                            \
     187                 :            :    : (_) == 'g' ? 32                            \
     188                 :            :    : (_) == 'h' ? 33                            \
     189                 :            :    : (_) == 'i' ? 34                            \
     190                 :            :    : (_) == 'j' ? 35                            \
     191                 :            :    : (_) == 'k' ? 36                            \
     192                 :            :    : (_) == 'l' ? 37                            \
     193                 :            :    : (_) == 'm' ? 38                            \
     194                 :            :    : (_) == 'n' ? 39                            \
     195                 :            :    : (_) == 'o' ? 40                            \
     196                 :            :    : (_) == 'p' ? 41                            \
     197                 :            :    : (_) == 'q' ? 42                            \
     198                 :            :    : (_) == 'r' ? 43                            \
     199                 :            :    : (_) == 's' ? 44                            \
     200                 :            :    : (_) == 't' ? 45                            \
     201                 :            :    : (_) == 'u' ? 46                            \
     202                 :            :    : (_) == 'v' ? 47                            \
     203                 :            :    : (_) == 'w' ? 48                            \
     204                 :            :    : (_) == 'x' ? 49                            \
     205                 :            :    : (_) == 'y' ? 50                            \
     206                 :            :    : (_) == 'z' ? 51                            \
     207                 :            :    : (_) == '0' ? 52                            \
     208                 :            :    : (_) == '1' ? 53                            \
     209                 :            :    : (_) == '2' ? 54                            \
     210                 :            :    : (_) == '3' ? 55                            \
     211                 :            :    : (_) == '4' ? 56                            \
     212                 :            :    : (_) == '5' ? 57                            \
     213                 :            :    : (_) == '6' ? 58                            \
     214                 :            :    : (_) == '7' ? 59                            \
     215                 :            :    : (_) == '8' ? 60                            \
     216                 :            :    : (_) == '9' ? 61                            \
     217                 :            :    : (_) == '+' ? 62                            \
     218                 :            :    : (_) == '/' ? 63                            \
     219                 :            :    : -1)
     220                 :            : 
     221                 :            : static const signed char b64[0x100] = {
     222                 :            :   B64 (0), B64 (1), B64 (2), B64 (3),
     223                 :            :   B64 (4), B64 (5), B64 (6), B64 (7),
     224                 :            :   B64 (8), B64 (9), B64 (10), B64 (11),
     225                 :            :   B64 (12), B64 (13), B64 (14), B64 (15),
     226                 :            :   B64 (16), B64 (17), B64 (18), B64 (19),
     227                 :            :   B64 (20), B64 (21), B64 (22), B64 (23),
     228                 :            :   B64 (24), B64 (25), B64 (26), B64 (27),
     229                 :            :   B64 (28), B64 (29), B64 (30), B64 (31),
     230                 :            :   B64 (32), B64 (33), B64 (34), B64 (35),
     231                 :            :   B64 (36), B64 (37), B64 (38), B64 (39),
     232                 :            :   B64 (40), B64 (41), B64 (42), B64 (43),
     233                 :            :   B64 (44), B64 (45), B64 (46), B64 (47),
     234                 :            :   B64 (48), B64 (49), B64 (50), B64 (51),
     235                 :            :   B64 (52), B64 (53), B64 (54), B64 (55),
     236                 :            :   B64 (56), B64 (57), B64 (58), B64 (59),
     237                 :            :   B64 (60), B64 (61), B64 (62), B64 (63),
     238                 :            :   B64 (64), B64 (65), B64 (66), B64 (67),
     239                 :            :   B64 (68), B64 (69), B64 (70), B64 (71),
     240                 :            :   B64 (72), B64 (73), B64 (74), B64 (75),
     241                 :            :   B64 (76), B64 (77), B64 (78), B64 (79),
     242                 :            :   B64 (80), B64 (81), B64 (82), B64 (83),
     243                 :            :   B64 (84), B64 (85), B64 (86), B64 (87),
     244                 :            :   B64 (88), B64 (89), B64 (90), B64 (91),
     245                 :            :   B64 (92), B64 (93), B64 (94), B64 (95),
     246                 :            :   B64 (96), B64 (97), B64 (98), B64 (99),
     247                 :            :   B64 (100), B64 (101), B64 (102), B64 (103),
     248                 :            :   B64 (104), B64 (105), B64 (106), B64 (107),
     249                 :            :   B64 (108), B64 (109), B64 (110), B64 (111),
     250                 :            :   B64 (112), B64 (113), B64 (114), B64 (115),
     251                 :            :   B64 (116), B64 (117), B64 (118), B64 (119),
     252                 :            :   B64 (120), B64 (121), B64 (122), B64 (123),
     253                 :            :   B64 (124), B64 (125), B64 (126), B64 (127),
     254                 :            :   B64 (128), B64 (129), B64 (130), B64 (131),
     255                 :            :   B64 (132), B64 (133), B64 (134), B64 (135),
     256                 :            :   B64 (136), B64 (137), B64 (138), B64 (139),
     257                 :            :   B64 (140), B64 (141), B64 (142), B64 (143),
     258                 :            :   B64 (144), B64 (145), B64 (146), B64 (147),
     259                 :            :   B64 (148), B64 (149), B64 (150), B64 (151),
     260                 :            :   B64 (152), B64 (153), B64 (154), B64 (155),
     261                 :            :   B64 (156), B64 (157), B64 (158), B64 (159),
     262                 :            :   B64 (160), B64 (161), B64 (162), B64 (163),
     263                 :            :   B64 (164), B64 (165), B64 (166), B64 (167),
     264                 :            :   B64 (168), B64 (169), B64 (170), B64 (171),
     265                 :            :   B64 (172), B64 (173), B64 (174), B64 (175),
     266                 :            :   B64 (176), B64 (177), B64 (178), B64 (179),
     267                 :            :   B64 (180), B64 (181), B64 (182), B64 (183),
     268                 :            :   B64 (184), B64 (185), B64 (186), B64 (187),
     269                 :            :   B64 (188), B64 (189), B64 (190), B64 (191),
     270                 :            :   B64 (192), B64 (193), B64 (194), B64 (195),
     271                 :            :   B64 (196), B64 (197), B64 (198), B64 (199),
     272                 :            :   B64 (200), B64 (201), B64 (202), B64 (203),
     273                 :            :   B64 (204), B64 (205), B64 (206), B64 (207),
     274                 :            :   B64 (208), B64 (209), B64 (210), B64 (211),
     275                 :            :   B64 (212), B64 (213), B64 (214), B64 (215),
     276                 :            :   B64 (216), B64 (217), B64 (218), B64 (219),
     277                 :            :   B64 (220), B64 (221), B64 (222), B64 (223),
     278                 :            :   B64 (224), B64 (225), B64 (226), B64 (227),
     279                 :            :   B64 (228), B64 (229), B64 (230), B64 (231),
     280                 :            :   B64 (232), B64 (233), B64 (234), B64 (235),
     281                 :            :   B64 (236), B64 (237), B64 (238), B64 (239),
     282                 :            :   B64 (240), B64 (241), B64 (242), B64 (243),
     283                 :            :   B64 (244), B64 (245), B64 (246), B64 (247),
     284                 :            :   B64 (248), B64 (249), B64 (250), B64 (251),
     285                 :            :   B64 (252), B64 (253), B64 (254), B64 (255)
     286                 :            : };
     287                 :            : 
     288                 :            : #if UCHAR_MAX == 255
     289                 :            : # define uchar_in_range(c) true
     290                 :            : #else
     291                 :            : # define uchar_in_range(c) ((c) <= 255)
     292                 :            : #endif
     293                 :            : 
     294                 :            : /* Return true if CH is a character from the Base64 alphabet, and
     295                 :            :    false otherwise.  Note that '=' is padding and not considered to be
     296                 :            :    part of the alphabet.  */
     297                 :            : bool
     298                 :       6835 : isbase64 (char ch)
     299                 :            : {
     300                 :       6835 :   return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
     301                 :            : }
     302                 :            : 
     303                 :            : /* Initialize decode-context buffer, CTX.  */
     304                 :            : void
     305                 :          5 : base64_decode_ctx_init (struct base64_decode_context *ctx)
     306                 :            : {
     307                 :          5 :   ctx->i = 0;
     308                 :          5 : }
     309                 :            : 
     310                 :            : /* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
     311                 :            :    none of those four is a newline, then return *IN.  Otherwise, copy up to
     312                 :            :    4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
     313                 :            :    index CTX->i and setting CTX->i to reflect the number of bytes copied,
     314                 :            :    and return CTX->buf.  In either case, advance *IN to point to the byte
     315                 :            :    after the last one processed, and set *N_NON_NEWLINE to the number of
     316                 :            :    verified non-newline bytes accessible through the returned pointer.  */
     317                 :            : static inline char *
     318                 :          8 : get_4 (struct base64_decode_context *ctx,
     319                 :            :        char const *restrict *in, char const *restrict in_end,
     320                 :            :        size_t *n_non_newline)
     321                 :            : {
     322         [ +  + ]:          8 :   if (ctx->i == 4)
     323                 :          2 :     ctx->i = 0;
     324                 :            : 
     325         [ +  + ]:          8 :   if (ctx->i == 0)
     326                 :            :     {
     327                 :          6 :       char const *t = *in;
     328 [ +  + ][ +  + ]:          6 :       if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL)
     329                 :            :         {
     330                 :            :           /* This is the common case: no newline.  */
     331                 :          1 :           *in += 4;
     332                 :          1 :           *n_non_newline = 4;
     333                 :          1 :           return (char *) t;
     334                 :            :         }
     335                 :            :     }
     336                 :            : 
     337                 :            :   {
     338                 :            :     /* Copy non-newline bytes into BUF.  */
     339                 :          7 :     char const *p = *in;
     340         [ +  + ]:         22 :     while (p < in_end)
     341                 :            :       {
     342                 :         19 :         char c = *p++;
     343         [ +  + ]:         19 :         if (c != '\n')
     344                 :            :           {
     345                 :         16 :             ctx->buf[ctx->i++] = c;
     346         [ +  + ]:         16 :             if (ctx->i == 4)
     347                 :          4 :               break;
     348                 :            :           }
     349                 :            :       }
     350                 :            : 
     351                 :          7 :     *in = p;
     352                 :          7 :     *n_non_newline = ctx->i;
     353                 :          8 :     return ctx->buf;
     354                 :            :   }
     355                 :            : }
     356                 :            : 
     357                 :            : #define return_false                            \
     358                 :            :   do                                            \
     359                 :            :     {                                           \
     360                 :            :       *outp = out;                              \
     361                 :            :       return false;                             \
     362                 :            :     }                                           \
     363                 :            :   while (false)
     364                 :            : 
     365                 :            : /* Decode up to four bytes of base64-encoded data, IN, of length INLEN
     366                 :            :    into the output buffer, *OUT, of size *OUTLEN bytes.  Return true if
     367                 :            :    decoding is successful, false otherwise.  If *OUTLEN is too small,
     368                 :            :    as many bytes as possible are written to *OUT.  On return, advance
     369                 :            :    *OUT to point to the byte after the last one written, and decrement
     370                 :            :    *OUTLEN to reflect the number of bytes remaining in *OUT.  */
     371                 :            : static inline bool
     372                 :       2108 : decode_4 (char const *restrict in, size_t inlen,
     373                 :            :           char *restrict *outp, size_t *outleft)
     374                 :            : {
     375                 :       2108 :   char *out = *outp;
     376         [ +  + ]:       2108 :   if (inlen < 2)
     377                 :        324 :     return false;
     378                 :            : 
     379 [ +  + ][ -  + ]:       1784 :   if (!isbase64 (in[0]) || !isbase64 (in[1]))
     380                 :          7 :     return false;
     381                 :            : 
     382         [ +  + ]:       1777 :   if (*outleft)
     383                 :            :     {
     384                 :       1776 :       *out++ = ((b64[to_uchar (in[0])] << 2)
     385                 :       1776 :                 | (b64[to_uchar (in[1])] >> 4));
     386                 :       1776 :       --*outleft;
     387                 :            :     }
     388                 :            : 
     389         [ +  + ]:       1777 :   if (inlen == 2)
     390                 :          2 :     return_false;
     391                 :            : 
     392         [ +  + ]:       1775 :   if (in[2] == '=')
     393                 :            :     {
     394         [ +  + ]:         68 :       if (inlen != 4)
     395                 :          2 :         return_false;
     396                 :            : 
     397         [ +  + ]:         66 :       if (in[3] != '=')
     398                 :          4 :         return_false;
     399                 :            :     }
     400                 :            :   else
     401                 :            :     {
     402         [ +  + ]:       1707 :       if (!isbase64 (in[2]))
     403                 :          3 :         return_false;
     404                 :            : 
     405         [ +  + ]:       1704 :       if (*outleft)
     406                 :            :         {
     407                 :       1702 :           *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
     408                 :       1702 :                     | (b64[to_uchar (in[2])] >> 2));
     409                 :       1702 :           --*outleft;
     410                 :            :         }
     411                 :            : 
     412         [ +  + ]:       1704 :       if (inlen == 3)
     413                 :          2 :         return_false;
     414                 :            : 
     415         [ +  + ]:       1702 :       if (in[3] == '=')
     416                 :            :         {
     417         [ +  + ]:        135 :           if (inlen != 4)
     418                 :          2 :             return_false;
     419                 :            :         }
     420                 :            :       else
     421                 :            :         {
     422         [ +  + ]:       1567 :           if (!isbase64 (in[3]))
     423                 :          2 :             return_false;
     424                 :            : 
     425         [ +  + ]:       1565 :           if (*outleft)
     426                 :            :             {
     427                 :       1562 :               *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
     428                 :       1562 :                         | b64[to_uchar (in[3])]);
     429                 :       1562 :               --*outleft;
     430                 :            :             }
     431                 :            :         }
     432                 :            :     }
     433                 :            : 
     434                 :       1760 :   *outp = out;
     435                 :       2108 :   return true;
     436                 :            : }
     437                 :            : 
     438                 :            : /* Decode base64-encoded input array IN of length INLEN to output array
     439                 :            :    OUT that can hold *OUTLEN bytes.  The input data may be interspersed
     440                 :            :    with newlines.  Return true if decoding was successful, i.e. if the
     441                 :            :    input was valid base64 data, false otherwise.  If *OUTLEN is too
     442                 :            :    small, as many bytes as possible will be written to OUT.  On return,
     443                 :            :    *OUTLEN holds the length of decoded bytes in OUT.  Note that as soon
     444                 :            :    as any non-alphabet, non-newline character is encountered, decoding
     445                 :            :    is stopped and false is returned.  If INLEN is zero, then process
     446                 :            :    only whatever data is stored in CTX.
     447                 :            : 
     448                 :            :    Initially, CTX must have been initialized via base64_decode_ctx_init.
     449                 :            :    Subsequent calls to this function must reuse whatever state is recorded
     450                 :            :    in that buffer.  It is necessary for when a quadruple of base64 input
     451                 :            :    bytes spans two input buffers.
     452                 :            : 
     453                 :            :    If CTX is NULL then newlines are treated as garbage and the input
     454                 :            :    buffer is processed as a unit.  */
     455                 :            : 
     456                 :            : bool
     457                 :        335 : base64_decode_ctx (struct base64_decode_context *ctx,
     458                 :            :                    const char *restrict in, size_t inlen,
     459                 :            :                    char *restrict out, size_t *outlen)
     460                 :            : {
     461                 :        335 :   size_t outleft = *outlen;
     462                 :        335 :   bool ignore_newlines = ctx != NULL;
     463                 :        335 :   bool flush_ctx = false;
     464                 :        335 :   unsigned int ctx_i = 0;
     465                 :            : 
     466         [ +  + ]:        335 :   if (ignore_newlines)
     467                 :            :     {
     468                 :          8 :       ctx_i = ctx->i;
     469                 :          8 :       flush_ctx = inlen == 0;
     470                 :            :     }
     471                 :            : 
     472                 :            : 
     473                 :            :   while (true)
     474                 :            :     {
     475                 :        346 :       size_t outleft_save = outleft;
     476 [ +  + ][ +  - ]:        346 :       if (ctx_i == 0 && !flush_ctx)
     477                 :            :         {
     478                 :            :           while (true)
     479                 :            :             {
     480                 :            :               /* Save a copy of outleft, in case we need to re-parse this
     481                 :            :                  block of four bytes.  */
     482                 :       2095 :               outleft_save = outleft;
     483         [ +  + ]:       2095 :               if (!decode_4 (in, inlen, &out, &outleft))
     484                 :        340 :                 break;
     485                 :            : 
     486                 :       1755 :               in += 4;
     487                 :       1755 :               inlen -= 4;
     488                 :       1755 :             }
     489                 :            :         }
     490                 :            : 
     491 [ +  + ][ +  + ]:        346 :       if (inlen == 0 && !flush_ctx)
     492                 :        324 :         break;
     493                 :            : 
     494                 :            :       /* Handle the common case of 72-byte wrapped lines.
     495                 :            :          This also handles any other multiple-of-4-byte wrapping.  */
     496 [ +  + ][ +  + ]:         22 :       if (inlen && *in == '\n' && ignore_newlines)
                 [ +  - ]
     497                 :            :         {
     498                 :          6 :           ++in;
     499                 :          6 :           --inlen;
     500                 :          6 :           continue;
     501                 :            :         }
     502                 :            : 
     503                 :            :       /* Restore OUT and OUTLEFT.  */
     504                 :         16 :       out -= outleft_save - outleft;
     505                 :         16 :       outleft = outleft_save;
     506                 :            : 
     507                 :            :       {
     508                 :         16 :         char const *in_end = in + inlen;
     509                 :            :         char const *non_nl;
     510                 :            : 
     511         [ +  + ]:         16 :         if (ignore_newlines)
     512                 :          8 :           non_nl = get_4 (ctx, &in, in_end, &inlen);
     513                 :            :         else
     514                 :          8 :           non_nl = in;  /* Might have nl in this case. */
     515                 :            : 
     516                 :            :         /* If the input is empty or consists solely of newlines (0 non-newlines),
     517                 :            :            then we're done.  Likewise if there are fewer than 4 bytes when not
     518                 :            :            flushing context and not treating newlines as garbage.  */
     519 [ +  + ][ +  + ]:         16 :         if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines))
         [ +  - ][ +  + ]
     520                 :            :           {
     521                 :          3 :             inlen = 0;
     522                 :          3 :             break;
     523                 :            :           }
     524         [ +  + ]:         13 :         if (!decode_4 (non_nl, inlen, &out, &outleft))
     525                 :          8 :           break;
     526                 :            : 
     527                 :          5 :         inlen = in_end - in;
     528                 :            :       }
     529                 :         11 :     }
     530                 :            : 
     531                 :        335 :   *outlen -= outleft;
     532                 :            : 
     533                 :        335 :   return inlen == 0;
     534                 :            : }
     535                 :            : 
     536                 :            : /* Allocate an output buffer in *OUT, and decode the base64 encoded
     537                 :            :    data stored in IN of size INLEN to the *OUT buffer.  On return, the
     538                 :            :    size of the decoded data is stored in *OUTLEN.  OUTLEN may be NULL,
     539                 :            :    if the caller is not interested in the decoded length.  *OUT may be
     540                 :            :    NULL to indicate an out of memory error, in which case *OUTLEN
     541                 :            :    contains the size of the memory block needed.  The function returns
     542                 :            :    true on successful decoding and memory allocation errors.  (Use the
     543                 :            :    *OUT and *OUTLEN parameters to differentiate between successful
     544                 :            :    decoding and memory error.)  The function returns false if the
     545                 :            :    input was invalid, in which case *OUT is NULL and *OUTLEN is
     546                 :            :    undefined. */
     547                 :            : bool
     548                 :        328 : base64_decode_alloc_ctx (struct base64_decode_context *ctx,
     549                 :            :                          const char *in, size_t inlen, char **out,
     550                 :            :                          size_t *outlen)
     551                 :            : {
     552                 :            :   /* This may allocate a few bytes too many, depending on input,
     553                 :            :      but it's not worth the extra CPU time to compute the exact size.
     554                 :            :      The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the
     555                 :            :      input ends with "=" and minus another 1 if the input ends with "==".
     556                 :            :      Dividing before multiplying avoids the possibility of overflow.  */
     557                 :        328 :   size_t needlen = 3 * (inlen / 4) + 3;
     558                 :            : 
     559                 :        328 :   *out = malloc (needlen);
     560         [ -  + ]:        328 :   if (!*out)
     561                 :          0 :     return true;
     562                 :            : 
     563         [ +  + ]:        328 :   if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen))
     564                 :            :     {
     565                 :          8 :       free (*out);
     566                 :          8 :       *out = NULL;
     567                 :          8 :       return false;
     568                 :            :     }
     569                 :            : 
     570         [ +  - ]:        320 :   if (outlen)
     571                 :        320 :     *outlen = needlen;
     572                 :            : 
     573                 :        328 :   return true;
     574                 :            : }

Generated by: LCOV version 1.9