LCOV - code coverage report
Current view: top level - src/bcrypt - base64.cpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 92.8 % 69 64 5
Test Date: 2026-06-13 19:44:58 Functions: 100.0 % 2 2

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : //
       4                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6                 : //
       7                 : // Official repository: https://github.com/cppalliance/http
       8                 : //
       9                 : 
      10                 : #include "base64.hpp"
      11                 : 
      12                 : namespace boost {
      13                 : namespace http {
      14                 : namespace bcrypt {
      15                 : namespace detail {
      16                 : 
      17                 : namespace {
      18                 : 
      19                 : // bcrypt's non-standard base64 alphabet
      20                 : constexpr char encode_table[] =
      21                 :     "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      22                 : 
      23                 : // Decode table: maps ASCII char to 6-bit value, or 0xFF for invalid
      24                 : constexpr std::uint8_t decode_table[256] = {
      25                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 0-7
      26                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 8-15
      27                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 16-23
      28                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 24-31
      29                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 32-39
      30                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,  // 40-47  (. /)
      31                 :     0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D,  // 48-55  (0-7)
      32                 :     0x3E, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 56-63  (8-9)
      33                 :     0xFF, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,  // 64-71  (A-G)
      34                 :     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,  // 72-79  (H-O)
      35                 :     0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,  // 80-87  (P-W)
      36                 :     0x19, 0x1A, 0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 88-95  (X-Z)
      37                 :     0xFF, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22,  // 96-103 (a-g)
      38                 :     0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,  // 104-111 (h-o)
      39                 :     0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,  // 112-119 (p-w)
      40                 :     0x33, 0x34, 0x35, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  // 120-127 (x-z)
      41                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      42                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      43                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      44                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      45                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      46                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      47                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      48                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      49                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      50                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      51                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      52                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      53                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      54                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      55                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      56                 :     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      57                 : };
      58                 : 
      59                 : } // namespace
      60                 : 
      61                 : std::size_t
      62 HIT          43 : base64_encode(
      63                 :     char* dest,
      64                 :     std::uint8_t const* src,
      65                 :     std::size_t n)
      66                 : {
      67              43 :     char* out = dest;
      68                 : 
      69             294 :     while (n >= 3)
      70                 :     {
      71             251 :         std::uint32_t v =
      72             251 :             (static_cast<std::uint32_t>(src[0]) << 16) |
      73             251 :             (static_cast<std::uint32_t>(src[1]) << 8) |
      74             251 :             static_cast<std::uint32_t>(src[2]);
      75                 : 
      76             251 :         *out++ = encode_table[(v >> 18) & 0x3F];
      77             251 :         *out++ = encode_table[(v >> 12) & 0x3F];
      78             251 :         *out++ = encode_table[(v >> 6) & 0x3F];
      79             251 :         *out++ = encode_table[v & 0x3F];
      80                 : 
      81             251 :         src += 3;
      82             251 :         n -= 3;
      83                 :     }
      84                 : 
      85              43 :     if (n == 2)
      86                 :     {
      87              18 :         std::uint32_t v =
      88              18 :             (static_cast<std::uint32_t>(src[0]) << 16) |
      89              18 :             (static_cast<std::uint32_t>(src[1]) << 8);
      90                 : 
      91              18 :         *out++ = encode_table[(v >> 18) & 0x3F];
      92              18 :         *out++ = encode_table[(v >> 12) & 0x3F];
      93              18 :         *out++ = encode_table[(v >> 6) & 0x3F];
      94                 :     }
      95              25 :     else if (n == 1)
      96                 :     {
      97              25 :         std::uint32_t v =
      98              25 :             static_cast<std::uint32_t>(src[0]) << 16;
      99                 : 
     100              25 :         *out++ = encode_table[(v >> 18) & 0x3F];
     101              25 :         *out++ = encode_table[(v >> 12) & 0x3F];
     102                 :     }
     103                 : 
     104              43 :     return static_cast<std::size_t>(out - dest);
     105                 : }
     106                 : 
     107                 : int
     108              25 : base64_decode(
     109                 :     std::uint8_t* dest,
     110                 :     char const* src,
     111                 :     std::size_t n)
     112                 : {
     113              25 :     std::uint8_t* out = dest;
     114              25 :     std::size_t i = 0;
     115                 : 
     116             170 :     while (i + 4 <= n)
     117                 :     {
     118             145 :         std::uint8_t a = decode_table[static_cast<unsigned char>(src[i])];
     119             145 :         std::uint8_t b = decode_table[static_cast<unsigned char>(src[i + 1])];
     120             145 :         std::uint8_t c = decode_table[static_cast<unsigned char>(src[i + 2])];
     121             145 :         std::uint8_t d = decode_table[static_cast<unsigned char>(src[i + 3])];
     122                 : 
     123             145 :         if ((a | b | c | d) & 0x80)
     124 MIS           0 :             return -1;
     125                 : 
     126 HIT         145 :         std::uint32_t v =
     127             145 :             (static_cast<std::uint32_t>(a) << 18) |
     128             145 :             (static_cast<std::uint32_t>(b) << 12) |
     129             145 :             (static_cast<std::uint32_t>(c) << 6) |
     130             145 :             static_cast<std::uint32_t>(d);
     131                 : 
     132             145 :         *out++ = static_cast<std::uint8_t>(v >> 16);
     133             145 :         *out++ = static_cast<std::uint8_t>(v >> 8);
     134             145 :         *out++ = static_cast<std::uint8_t>(v);
     135                 : 
     136             145 :         i += 4;
     137                 :     }
     138                 : 
     139                 :     // Handle remaining 2 or 3 characters
     140              25 :     if (i + 3 == n)
     141                 :     {
     142              10 :         std::uint8_t a = decode_table[static_cast<unsigned char>(src[i])];
     143              10 :         std::uint8_t b = decode_table[static_cast<unsigned char>(src[i + 1])];
     144              10 :         std::uint8_t c = decode_table[static_cast<unsigned char>(src[i + 2])];
     145                 : 
     146              10 :         if ((a | b | c) & 0x80)
     147 MIS           0 :             return -1;
     148                 : 
     149 HIT          10 :         std::uint32_t v =
     150              10 :             (static_cast<std::uint32_t>(a) << 18) |
     151              10 :             (static_cast<std::uint32_t>(b) << 12) |
     152              10 :             (static_cast<std::uint32_t>(c) << 6);
     153                 : 
     154              10 :         *out++ = static_cast<std::uint8_t>(v >> 16);
     155              10 :         *out++ = static_cast<std::uint8_t>(v >> 8);
     156                 :     }
     157              15 :     else if (i + 2 == n)
     158                 :     {
     159              15 :         std::uint8_t a = decode_table[static_cast<unsigned char>(src[i])];
     160              15 :         std::uint8_t b = decode_table[static_cast<unsigned char>(src[i + 1])];
     161                 : 
     162              15 :         if ((a | b) & 0x80)
     163 MIS           0 :             return -1;
     164                 : 
     165 HIT          15 :         std::uint32_t v =
     166              15 :             (static_cast<std::uint32_t>(a) << 18) |
     167              15 :             (static_cast<std::uint32_t>(b) << 12);
     168                 : 
     169              15 :         *out++ = static_cast<std::uint8_t>(v >> 16);
     170                 :     }
     171 MIS           0 :     else if (i + 1 == n)
     172                 :     {
     173                 :         // Single trailing character is invalid
     174               0 :         return -1;
     175                 :     }
     176                 : 
     177 HIT          25 :     return static_cast<int>(out - dest);
     178                 : }
     179                 : 
     180                 : } // detail
     181                 : } // bcrypt
     182                 : } // http
     183                 : } // boost
        

Generated by: LCOV version 2.3