LCOV - code coverage report
Current view: top level - nsprpub/lib/libc/src - base64.c (source / functions) Hit Total Coverage
Test: output.info Lines: 113 153 73.9 %
Date: 2017-07-14 16:53:18 Functions: 8 9 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "plbase64.h"
       7             : #include "prlog.h" /* For PR_NOT_REACHED */
       8             : #include "prmem.h" /* for malloc / PR_MALLOC */
       9             : 
      10             : #include <string.h> /* for strlen */
      11             : 
      12             : static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      13             : 
      14             : static void
      15         120 : encode3to4
      16             : (
      17             :     const unsigned char    *src,
      18             :     unsigned char          *dest
      19             : )
      20             : {
      21         120 :     PRUint32 b32 = (PRUint32)0;
      22         120 :     PRIntn i, j = 18;
      23             : 
      24         480 :     for( i = 0; i < 3; i++ )
      25             :     {
      26         360 :         b32 <<= 8;
      27         360 :         b32 |= (PRUint32)src[i];
      28             :     }
      29             : 
      30         600 :     for( i = 0; i < 4; i++ )
      31             :     {
      32         480 :         dest[i] = base[ (PRUint32)((b32>>j) & 0x3F) ];
      33         480 :         j -= 6;
      34             :     }
      35             : 
      36         120 :     return;
      37             : }
      38             : 
      39             : static void
      40           4 : encode2to4
      41             : (
      42             :     const unsigned char    *src,
      43             :     unsigned char          *dest
      44             : )
      45             : {
      46           4 :     dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
      47           4 :     dest[1] = base[ (PRUint32)(((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)) ];
      48           4 :     dest[2] = base[ (PRUint32)((src[1] & 0x0F) << 2) ];
      49           4 :     dest[3] = (unsigned char)'=';
      50           4 :     return;
      51             : }
      52             : 
      53             : static void
      54           0 : encode1to4
      55             : (
      56             :     const unsigned char    *src,
      57             :     unsigned char          *dest
      58             : )
      59             : {
      60           0 :     dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
      61           0 :     dest[1] = base[ (PRUint32)((src[0] & 0x03) << 4) ];
      62           0 :     dest[2] = (unsigned char)'=';
      63           0 :     dest[3] = (unsigned char)'=';
      64           0 :     return;
      65             : }
      66             : 
      67             : static void
      68           5 : encode
      69             : (
      70             :     const unsigned char    *src,
      71             :     PRUint32                srclen,
      72             :     unsigned char          *dest
      73             : )
      74             : {
      75         130 :     while( srclen >= 3 )
      76             :     {
      77         120 :         encode3to4(src, dest);
      78         120 :         src += 3;
      79         120 :         dest += 4;
      80         120 :         srclen -= 3;
      81             :     }
      82             : 
      83           5 :     switch( srclen )
      84             :     {
      85             :         case 2:
      86           4 :             encode2to4(src, dest);
      87           4 :             break;
      88             :         case 1:
      89           0 :             encode1to4(src, dest);
      90           0 :             break;
      91             :         case 0:
      92           1 :             break;
      93             :         default:
      94           0 :             PR_NOT_REACHED("coding error");
      95             :     }
      96             : 
      97           5 :     return;
      98             : }
      99             : 
     100             : /*
     101             :  * PL_Base64Encode
     102             :  *
     103             :  * If the destination argument is NULL, a return buffer is 
     104             :  * allocated, and the data therein will be null-terminated.  
     105             :  * If the destination argument is not NULL, it is assumed to
     106             :  * be of sufficient size, and the contents will not be null-
     107             :  * terminated by this routine.
     108             :  *
     109             :  * Returns null if the allocation fails.
     110             :  */
     111             : 
     112             : PR_IMPLEMENT(char *)
     113             : PL_Base64Encode
     114             : (
     115             :     const char *src,
     116             :     PRUint32    srclen,
     117             :     char       *dest
     118             : )
     119             : {
     120           5 :     if( 0 == srclen )
     121             :     {
     122           0 :         size_t len = strlen(src);
     123           0 :         srclen = len;
     124             :         /* Detect truncation. */
     125           0 :         if( srclen != len )
     126             :         {
     127           0 :             return (char *)0;
     128             :         }
     129             :     }
     130             : 
     131           5 :     if( (char *)0 == dest )
     132             :     {
     133             :         PRUint32 destlen;
     134             :         /* Ensure all PRUint32 values stay within range. */
     135           4 :         if( srclen > (PR_UINT32_MAX/4) * 3 )
     136             :         {
     137           0 :             return (char *)0;
     138             :         }
     139           4 :         destlen = ((srclen + 2)/3) * 4;
     140           4 :         dest = (char *)PR_MALLOC(destlen + 1);
     141           4 :         if( (char *)0 == dest )
     142             :         {
     143           0 :             return (char *)0;
     144             :         }
     145           4 :         dest[ destlen ] = (char)0; /* null terminate */
     146             :     }
     147             : 
     148           5 :     encode((const unsigned char *)src, srclen, (unsigned char *)dest);
     149           5 :     return dest;
     150             : }
     151             : 
     152             : static PRInt32
     153       13765 : codetovalue
     154             : (
     155             :     unsigned char c
     156             : )
     157             : {
     158       13765 :     if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') )
     159             :     {
     160        8122 :         return (PRInt32)(c - (unsigned char)'A');
     161             :     }
     162        5643 :     else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') )
     163             :     {
     164        4338 :         return ((PRInt32)(c - (unsigned char)'a') +26);
     165             :     }
     166        1305 :     else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') )
     167             :     {
     168        1233 :         return ((PRInt32)(c - (unsigned char)'0') +52);
     169             :     }
     170          72 :     else if( (unsigned char)'+' == c )
     171             :     {
     172          23 :         return (PRInt32)62;
     173             :     }
     174          49 :     else if( (unsigned char)'/' == c )
     175             :     {
     176          49 :         return (PRInt32)63;
     177             :     }
     178             :     else
     179             :     {
     180           0 :         return -1;
     181             :     }
     182             : }
     183             : 
     184             : static PRStatus
     185        3360 : decode4to3
     186             : (
     187             :     const unsigned char    *src,
     188             :     unsigned char          *dest
     189             : )
     190             : {
     191        3360 :     PRUint32 b32 = (PRUint32)0;
     192             :     PRInt32 bits;
     193             :     PRIntn i;
     194             : 
     195       16800 :     for( i = 0; i < 4; i++ )
     196             :     {
     197       13440 :         bits = codetovalue(src[i]);
     198       13440 :         if( bits < 0 )
     199             :         {
     200           0 :             return PR_FAILURE;
     201             :         }
     202             : 
     203       13440 :         b32 <<= 6;
     204       13440 :         b32 |= bits;
     205             :     }
     206             : 
     207        3360 :     dest[0] = (unsigned char)((b32 >> 16) & 0xFF);
     208        3360 :     dest[1] = (unsigned char)((b32 >>  8) & 0xFF);
     209        3360 :     dest[2] = (unsigned char)((b32      ) & 0xFF);
     210             : 
     211        3360 :     return PR_SUCCESS;
     212             : }
     213             : 
     214             : static PRStatus
     215          47 : decode3to2
     216             : (
     217             :     const unsigned char    *src,
     218             :     unsigned char          *dest
     219             : )
     220             : {
     221          47 :     PRUint32 b32 = (PRUint32)0;
     222             :     PRInt32 bits;
     223             :     PRUint32 ubits;
     224             : 
     225          47 :     bits = codetovalue(src[0]);
     226          47 :     if( bits < 0 )
     227             :     {
     228           0 :         return PR_FAILURE;
     229             :     }
     230             : 
     231          47 :     b32 = (PRUint32)bits;
     232          47 :     b32 <<= 6;
     233             : 
     234          47 :     bits = codetovalue(src[1]);
     235          47 :     if( bits < 0 )
     236             :     {
     237           0 :         return PR_FAILURE;
     238             :     }
     239             : 
     240          47 :     b32 |= (PRUint32)bits;
     241          47 :     b32 <<= 4;
     242             : 
     243          47 :     bits = codetovalue(src[2]);
     244          47 :     if( bits < 0 )
     245             :     {
     246           0 :         return PR_FAILURE;
     247             :     }
     248             : 
     249          47 :     ubits = (PRUint32)bits;
     250          47 :     b32 |= (ubits >> 2);
     251             : 
     252          47 :     dest[0] = (unsigned char)((b32 >> 8) & 0xFF);
     253          47 :     dest[1] = (unsigned char)((b32     ) & 0xFF);
     254             : 
     255          47 :     return PR_SUCCESS;
     256             : }
     257             : 
     258             : static PRStatus
     259          92 : decode2to1
     260             : (
     261             :     const unsigned char    *src,
     262             :     unsigned char          *dest
     263             : )
     264             : {
     265             :     PRUint32 b32;
     266             :     PRUint32 ubits;
     267             :     PRInt32 bits;
     268             : 
     269          92 :     bits = codetovalue(src[0]);
     270          92 :     if( bits < 0 )
     271             :     {
     272           0 :         return PR_FAILURE;
     273             :     }
     274             : 
     275          92 :     ubits = (PRUint32)bits;
     276          92 :     b32 = (ubits << 2);
     277             : 
     278          92 :     bits = codetovalue(src[1]);
     279          92 :     if( bits < 0 )
     280             :     {
     281           0 :         return PR_FAILURE;
     282             :     }
     283             : 
     284          92 :     ubits = (PRUint32)bits;
     285          92 :     b32 |= (ubits >> 4);
     286             : 
     287          92 :     dest[0] = (unsigned char)b32;
     288             : 
     289          92 :     return PR_SUCCESS;
     290             : }
     291             : 
     292             : static PRStatus
     293         172 : decode
     294             : (
     295             :     const unsigned char    *src,
     296             :     PRUint32                srclen,
     297             :     unsigned char          *dest
     298             : )
     299             : {
     300             :     PRStatus rv;
     301             : 
     302        3704 :     while( srclen >= 4 )
     303             :     {
     304        3360 :         rv = decode4to3(src, dest);
     305        3360 :         if( PR_SUCCESS != rv )
     306             :         {
     307           0 :             return PR_FAILURE;
     308             :         }
     309             : 
     310        3360 :         src += 4;
     311        3360 :         dest += 3;
     312        3360 :         srclen -= 4;
     313             :     }
     314             : 
     315         172 :     switch( srclen )
     316             :     {
     317             :         case 3:
     318          47 :             rv = decode3to2(src, dest);
     319          47 :             break;
     320             :         case 2:
     321          92 :             rv = decode2to1(src, dest);
     322          92 :             break;
     323             :         case 1:
     324           0 :             rv = PR_FAILURE;
     325           0 :             break;
     326             :         case 0:
     327          33 :             rv = PR_SUCCESS;
     328          33 :             break;
     329             :         default:
     330           0 :             PR_NOT_REACHED("coding error");
     331             :     }
     332             : 
     333         172 :     return rv;
     334             : }
     335             : 
     336             : /*
     337             :  * PL_Base64Decode
     338             :  *
     339             :  * If the destination argument is NULL, a return buffer is
     340             :  * allocated and the data therein will be null-terminated.
     341             :  * If the destination argument is not null, it is assumed
     342             :  * to be of sufficient size, and the data will not be null-
     343             :  * terminated by this routine.
     344             :  * 
     345             :  * Returns null if the allocation fails, or if the source string is 
     346             :  * not well-formed.
     347             :  */
     348             : 
     349             : PR_IMPLEMENT(char *)
     350             : PL_Base64Decode
     351             : (
     352             :     const char *src,
     353             :     PRUint32    srclen,
     354             :     char       *dest
     355             : )
     356             : {
     357             :     PRStatus status;
     358         172 :     PRBool allocated = PR_FALSE;
     359             : 
     360         172 :     if( (char *)0 == src )
     361             :     {
     362           0 :         return (char *)0;
     363             :     }
     364             : 
     365         172 :     if( 0 == srclen )
     366             :     {
     367           0 :         size_t len = strlen(src);
     368           0 :         srclen = len;
     369             :         /* Detect truncation. */
     370           0 :         if( srclen != len )
     371             :         {
     372           0 :             return (char *)0;
     373             :         }
     374             :     }
     375             : 
     376         172 :     if( srclen && (0 == (srclen & 3)) )
     377             :     {
     378         172 :         if( (char)'=' == src[ srclen-1 ] )
     379             :         {
     380         139 :             if( (char)'=' == src[ srclen-2 ] )
     381             :             {
     382          92 :                 srclen -= 2;
     383             :             }
     384             :             else
     385             :             {
     386          47 :                 srclen -= 1;
     387             :             }
     388             :         }
     389             :     }
     390             : 
     391         172 :     if( (char *)0 == dest )
     392             :     {
     393             :         /* The following computes ((srclen * 3) / 4) without overflow. */
     394           0 :         PRUint32 destlen = (srclen / 4) * 3 + ((srclen % 4) * 3) / 4;
     395           0 :         dest = (char *)PR_MALLOC(destlen + 1);
     396           0 :         if( (char *)0 == dest )
     397             :         {
     398           0 :             return (char *)0;
     399             :         }
     400           0 :         dest[ destlen ] = (char)0; /* null terminate */
     401           0 :         allocated = PR_TRUE;
     402             :     }
     403             : 
     404         172 :     status = decode((const unsigned char *)src, srclen, (unsigned char *)dest);
     405         172 :     if( PR_SUCCESS != status )
     406             :     {
     407           0 :         if( PR_TRUE == allocated )
     408             :         {
     409           0 :             PR_DELETE(dest);
     410             :         }
     411             : 
     412           0 :         return (char *)0;
     413             :     }
     414             : 
     415         172 :     return dest;
     416             : }

Generated by: LCOV version 1.13