libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

test_str_bin_hex.c (15044B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2022 Karlson2k (Evgeny Grin)
      4 
      5   This test tool is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU General Public License as
      7   published by the Free Software Foundation; either version 2, or
      8   (at your option) any later version.
      9 
     10   This test tool is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13   Lesser General Public License for more details.
     14 
     15   You should have received a copy of the GNU Lesser General Public
     16   License along with this library; if not, write to the Free Software
     17   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     18 */
     19 
     20 /**
     21  * @file microhttpd/test_str_bin_hex.c
     22  * @brief  Unit tests for hex strings <-> binary data processing
     23  * @author Karlson2k (Evgeny Grin)
     24  */
     25 
     26 #include "mhd_options.h"
     27 #include <string.h>
     28 #include <stdio.h>
     29 #include "mhd_str.h"
     30 #include "mhd_assert.h"
     31 
     32 #ifndef MHD_STATICSTR_LEN_
     33 /**
     34  * Determine length of static string / macro strings at compile time.
     35  */
     36 #define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1)
     37 #endif /* ! MHD_STATICSTR_LEN_ */
     38 
     39 
     40 static char tmp_bufs[4][4 * 1024]; /* should be enough for testing */
     41 static size_t buf_idx = 0;
     42 
     43 /* print non-printable chars as char codes */
     44 static char *
     45 n_prnt (const char *str, size_t len)
     46 {
     47   static char *buf;  /* should be enough for testing */
     48   static const size_t buf_size = sizeof(tmp_bufs[0]);
     49   size_t r_pos = 0;
     50   size_t w_pos = 0;
     51   if (++buf_idx >= (sizeof(tmp_bufs) / sizeof(tmp_bufs[0])))
     52     buf_idx = 0;
     53   buf = tmp_bufs[buf_idx];
     54 
     55   while (len > r_pos && w_pos + 1 < buf_size)
     56   {
     57     const unsigned char c = (unsigned char) str[r_pos];
     58     if ((c == '\\') || (c == '"') )
     59     {
     60       if (w_pos + 2 >= buf_size)
     61         break;
     62       buf[w_pos++] = '\\';
     63       buf[w_pos++] = (char) c;
     64     }
     65     else if ((c >= 0x20) && (c <= 0x7E) )
     66       buf[w_pos++] = (char) c;
     67     else
     68     {
     69       if (w_pos + 4 >= buf_size)
     70         break;
     71       if (snprintf (buf + w_pos, buf_size - w_pos, "\\x%02hX", (short unsigned
     72                                                                 int) c) != 4)
     73         break;
     74       w_pos += 4;
     75     }
     76     r_pos++;
     77   }
     78 
     79   if (len != r_pos)
     80   {   /* not full string is printed */
     81       /* enough space for "..." ? */
     82     if (w_pos + 3 > buf_size)
     83       w_pos = buf_size - 4;
     84     buf[w_pos++] = '.';
     85     buf[w_pos++] = '.';
     86     buf[w_pos++] = '.';
     87   }
     88   buf[w_pos] = 0;
     89   return buf;
     90 }
     91 
     92 
     93 #define TEST_BIN_MAX_SIZE (2 * 1024)
     94 
     95 /* return zero if succeed, number of failures otherwise */
     96 static unsigned int
     97 expect_decoded_n (const char *const hex, const size_t hex_len,
     98                   const uint8_t *const bin, const size_t bin_size,
     99                   const unsigned int line_num)
    100 {
    101   static const char fill_chr = '#';
    102   static char buf[TEST_BIN_MAX_SIZE];
    103   size_t res_size;
    104   unsigned int ret;
    105 
    106   mhd_assert (NULL != hex);
    107   mhd_assert (NULL != bin);
    108   mhd_assert (TEST_BIN_MAX_SIZE > bin_size + 1);
    109   mhd_assert (TEST_BIN_MAX_SIZE > hex_len + 1);
    110   mhd_assert (hex_len >= bin_size);
    111   mhd_assert (1 >= hex_len || hex_len > bin_size);
    112 
    113   ret = 0;
    114 
    115   /* check MHD_hex_to_bin() */
    116   if (1)
    117   {
    118     unsigned int check_res = 0;
    119 
    120     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    121     res_size = MHD_hex_to_bin (hex, hex_len, buf);
    122     if (res_size != bin_size)
    123     {
    124       check_res = 1;
    125       fprintf (stderr,
    126                "'MHD_hex_to_bin ()' FAILED: "
    127                "Wrong returned value:\n");
    128     }
    129     else
    130     {
    131       if ((0 != bin_size) &&
    132           (0 != memcmp (buf, bin, bin_size)))
    133       {
    134         check_res = 1;
    135         fprintf (stderr,
    136                  "'MHD_hex_to_bin ()' FAILED: "
    137                  "Wrong output data:\n");
    138       }
    139     }
    140     if (((0 == res_size) && (fill_chr != buf[bin_size]))
    141         || ((0 != res_size) && (fill_chr != buf[res_size])))
    142     {
    143       check_res = 1;
    144       fprintf (stderr,
    145                "'MHD_hex_to_bin ()' FAILED: "
    146                "A char written outside the buffer:\n");
    147     }
    148     if (0 != check_res)
    149     {
    150       ret++;
    151       fprintf (stderr,
    152                "\tRESULT  : MHD_hex_to_bin (\"%s\", %u, "
    153                "->\"%s\") -> %u\n",
    154                n_prnt (hex, hex_len), (unsigned) hex_len,
    155                n_prnt (buf, res_size),
    156                (unsigned) res_size);
    157       fprintf (stderr,
    158                "\tEXPECTED: MHD_hex_to_bin (\"%s\", %u, "
    159                "->\"%s\") -> %u\n",
    160                n_prnt (hex, hex_len), (unsigned) hex_len,
    161                n_prnt ((const char *) bin, bin_size),
    162                (unsigned) bin_size);
    163     }
    164   }
    165 
    166   /* check MHD_bin_to_hex() */
    167   if (0 == hex_len % 2)
    168   {
    169     unsigned int check_res = 0;
    170 
    171     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    172     res_size = MHD_bin_to_hex_z (bin, bin_size, buf);
    173 
    174     if (res_size != hex_len)
    175     {
    176       check_res = 1;
    177       fprintf (stderr,
    178                "'MHD_bin_to_hex ()' FAILED: "
    179                "Wrong returned value:\n");
    180     }
    181     else
    182     {
    183       if ((0 != hex_len) &&
    184           (! MHD_str_equal_caseless_bin_n_ (buf, hex, hex_len)))
    185       {
    186         check_res = 1;
    187         fprintf (stderr,
    188                  "'MHD_bin_to_hex ()' FAILED: "
    189                  "Wrong output string:\n");
    190       }
    191     }
    192     if (fill_chr != buf[res_size + 1])
    193     {
    194       check_res = 1;
    195       fprintf (stderr,
    196                "'MHD_bin_to_hex ()' FAILED: "
    197                "A char written outside the buffer:\n");
    198     }
    199     if (0 != buf[res_size])
    200     {
    201       check_res = 1;
    202       fprintf (stderr,
    203                "'MHD_bin_to_hex ()' FAILED: "
    204                "The result is not zero-terminated:\n");
    205     }
    206     if (0 != check_res)
    207     {
    208       ret++;
    209       fprintf (stderr,
    210                "\tRESULT  : MHD_bin_to_hex (\"%s\", %u, "
    211                "->\"%s\") -> %u\n",
    212                n_prnt ((const char *) bin, bin_size), (unsigned) bin_size,
    213                n_prnt (buf, res_size),
    214                (unsigned) res_size);
    215       fprintf (stderr,
    216                "\tEXPECTED: MHD_bin_to_hex (\"%s\", %u, "
    217                "->(lower case)\"%s\") -> %u\n",
    218                n_prnt ((const char *) bin, bin_size), (unsigned) bin_size,
    219                n_prnt (hex, hex_len),
    220                (unsigned) bin_size);
    221     }
    222   }
    223 
    224   if (0 != ret)
    225   {
    226     fprintf (stderr,
    227              "The check is at line: %u\n\n", line_num);
    228   }
    229   return ret;
    230 }
    231 
    232 
    233 #define expect_decoded_arr(h,a) \
    234         expect_decoded_n(h,MHD_STATICSTR_LEN_(h),\
    235                          a,(sizeof(a)/sizeof(a[0])), \
    236                          __LINE__)
    237 
    238 static unsigned int
    239 check_decode_bin (void)
    240 {
    241   unsigned int r = 0; /**< The number of errors */
    242 
    243   if (1)
    244   {
    245     static const uint8_t bin[256] =
    246     {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe,
    247      0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
    248      0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
    249      0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
    250      0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
    251      0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
    252      0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
    253      0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
    254      0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
    255      0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
    256      0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
    257      0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
    258      0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
    259      0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
    260      0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
    261      0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2,
    262      0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
    263      0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
    264      0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
    265      0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2,
    266      0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
    267      0xff };
    268     /* The lower case */
    269     r += expect_decoded_arr ("000102030405060708090a0b0c0d0e" \
    270                              "0f101112131415161718191a1b1c1d" \
    271                              "1e1f202122232425262728292a2b2c" \
    272                              "2d2e2f303132333435363738393a3b" \
    273                              "3c3d3e3f404142434445464748494a" \
    274                              "4b4c4d4e4f50515253545556575859" \
    275                              "5a5b5c5d5e5f606162636465666768" \
    276                              "696a6b6c6d6e6f7071727374757677" \
    277                              "78797a7b7c7d7e7f80818283848586" \
    278                              "8788898a8b8c8d8e8f909192939495" \
    279                              "969798999a9b9c9d9e9fa0a1a2a3a4" \
    280                              "a5a6a7a8a9aaabacadaeafb0b1b2b3" \
    281                              "b4b5b6b7b8b9babbbcbdbebfc0c1c2" \
    282                              "c3c4c5c6c7c8c9cacbcccdcecfd0d1" \
    283                              "d2d3d4d5d6d7d8d9dadbdcdddedfe0" \
    284                              "e1e2e3e4e5e6e7e8e9eaebecedeeef" \
    285                              "f0f1f2f3f4f5f6f7f8f9fafbfcfdfe" \
    286                              "ff", bin);
    287   }
    288 
    289   if (1)
    290   {
    291     static const uint8_t bin[256] =
    292     {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe,
    293      0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
    294      0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
    295      0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
    296      0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
    297      0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
    298      0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
    299      0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
    300      0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
    301      0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
    302      0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
    303      0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
    304      0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
    305      0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
    306      0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
    307      0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2,
    308      0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
    309      0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
    310      0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
    311      0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2,
    312      0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
    313      0xff };
    314     /* The upper case */
    315     r += expect_decoded_arr ("000102030405060708090A0B0C0D0E" \
    316                              "0F101112131415161718191A1B1C1D" \
    317                              "1E1F202122232425262728292A2B2C" \
    318                              "2D2E2F303132333435363738393A3B" \
    319                              "3C3D3E3F404142434445464748494A" \
    320                              "4B4C4D4E4F50515253545556575859" \
    321                              "5A5B5C5D5E5F606162636465666768" \
    322                              "696A6B6C6D6E6F7071727374757677" \
    323                              "78797A7B7C7D7E7F80818283848586" \
    324                              "8788898A8B8C8D8E8F909192939495" \
    325                              "969798999A9B9C9D9E9FA0A1A2A3A4" \
    326                              "A5A6A7A8A9AAABACADAEAFB0B1B2B3" \
    327                              "B4B5B6B7B8B9BABBBCBDBEBFC0C1C2" \
    328                              "C3C4C5C6C7C8C9CACBCCCDCECFD0D1" \
    329                              "D2D3D4D5D6D7D8D9DADBDCDDDEDFE0" \
    330                              "E1E2E3E4E5E6E7E8E9EAEBECEDEEEF" \
    331                              "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" \
    332                              "FF", bin);
    333   }
    334   if (1)
    335   {
    336     static const uint8_t bin[3] =
    337     {0x1, 0x2, 0x3};
    338     r += expect_decoded_arr ("010203", bin);
    339   }
    340   if (1)
    341   {
    342     static const uint8_t bin[3] =
    343     {0x1, 0x2, 0x3};
    344     r += expect_decoded_arr ("10203", bin);
    345   }
    346   if (1)
    347   {
    348     static const uint8_t bin[1] =
    349     {0x1};
    350     r += expect_decoded_arr ("01", bin);
    351   }
    352   if (1)
    353   {
    354     static const uint8_t bin[1] =
    355     {0x1};
    356     r += expect_decoded_arr ("1", bin);
    357   }
    358 
    359   return r;
    360 }
    361 
    362 
    363 /* return zero if succeed, number of failures otherwise */
    364 static unsigned int
    365 expect_failed_n (const char *const hex, const size_t hex_len,
    366                  const unsigned int line_num)
    367 {
    368   static const char fill_chr = '#';
    369   static char buf[TEST_BIN_MAX_SIZE];
    370   size_t res_size;
    371   unsigned int ret;
    372 
    373   mhd_assert (NULL != hex);
    374   mhd_assert (TEST_BIN_MAX_SIZE > hex_len + 1);
    375 
    376   ret = 0;
    377 
    378   /* check MHD_hex_to_bin() */
    379   if (1)
    380   {
    381     unsigned int check_res = 0;
    382 
    383     memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */
    384     res_size = MHD_hex_to_bin (hex, hex_len, buf);
    385     if (res_size != 0)
    386     {
    387       check_res = 1;
    388       fprintf (stderr,
    389                "'MHD_hex_to_bin ()' FAILED: "
    390                "Wrong returned value:\n");
    391     }
    392     if (0 != check_res)
    393     {
    394       ret++;
    395       fprintf (stderr,
    396                "\tRESULT  : MHD_hex_to_bin (\"%s\", %u, "
    397                "->\"%s\") -> %u\n",
    398                n_prnt (hex, hex_len), (unsigned) hex_len,
    399                n_prnt (buf, res_size),
    400                (unsigned) res_size);
    401       fprintf (stderr,
    402                "\tEXPECTED: MHD_hex_to_bin (\"%s\", %u, "
    403                "->(not defined)) -> 0\n",
    404                n_prnt (hex, hex_len), (unsigned) hex_len);
    405     }
    406   }
    407 
    408   if (0 != ret)
    409   {
    410     fprintf (stderr,
    411              "The check is at line: %u\n\n", line_num);
    412   }
    413   return ret;
    414 }
    415 
    416 
    417 #define expect_failed(h) \
    418         expect_failed_n(h,MHD_STATICSTR_LEN_(h), \
    419                          __LINE__)
    420 
    421 
    422 static unsigned int
    423 check_broken_str (void)
    424 {
    425   unsigned int r = 0; /**< The number of errors */
    426 
    427   r += expect_failed ("abcx");
    428   r += expect_failed ("X");
    429   r += expect_failed ("!");
    430   r += expect_failed ("01z");
    431   r += expect_failed ("0z");
    432   r += expect_failed ("00z");
    433   r += expect_failed ("000Y");
    434 
    435   return r;
    436 }
    437 
    438 
    439 int
    440 main (int argc, char *argv[])
    441 {
    442   unsigned int errcount = 0;
    443   (void) argc; (void) argv; /* Unused. Silent compiler warning. */
    444   errcount += check_decode_bin ();
    445   errcount += check_broken_str ();
    446   if (0 == errcount)
    447     printf ("All tests have been passed without errors.\n");
    448   return errcount == 0 ? 0 : 1;
    449 }