test_str_bin_hex.c (21511B)
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 <stdlib.h> 30 #include "mhd_str.h" 31 #include "mhd_assert.h" 32 33 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this 34 test into a marked, classifiable test error (TESTING.md, P5). */ 35 #include "mhd_panic_tripwire.h" 36 37 #ifndef MHD_STATICSTR_LEN_ 38 /** 39 * Determine length of static string / macro strings at compile time. 40 */ 41 #define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) 42 #endif /* ! MHD_STATICSTR_LEN_ */ 43 44 45 static char tmp_bufs[4][4 * 1024]; /* should be enough for testing */ 46 static size_t buf_idx = 0; 47 48 /* print non-printable chars as char codes */ 49 static char * 50 n_prnt (const char *str, size_t len) 51 { 52 static char *buf; /* should be enough for testing */ 53 static const size_t buf_size = sizeof(tmp_bufs[0]); 54 size_t r_pos = 0; 55 size_t w_pos = 0; 56 if (++buf_idx >= (sizeof(tmp_bufs) / sizeof(tmp_bufs[0]))) 57 buf_idx = 0; 58 buf = tmp_bufs[buf_idx]; 59 60 while (len > r_pos && w_pos + 1 < buf_size) 61 { 62 const unsigned char c = (unsigned char) str[r_pos]; 63 if ((c == '\\') || (c == '"') ) 64 { 65 if (w_pos + 2 >= buf_size) 66 break; 67 buf[w_pos++] = '\\'; 68 buf[w_pos++] = (char) c; 69 } 70 else if ((c >= 0x20) && (c <= 0x7E) ) 71 buf[w_pos++] = (char) c; 72 else 73 { 74 if (w_pos + 4 >= buf_size) 75 break; 76 if (snprintf (buf + w_pos, buf_size - w_pos, "\\x%02hX", (short unsigned 77 int) c) != 4) 78 break; 79 w_pos += 4; 80 } 81 r_pos++; 82 } 83 84 if (len != r_pos) 85 { /* not full string is printed */ 86 /* enough space for "..." ? */ 87 if (w_pos + 3 > buf_size) 88 w_pos = buf_size - 4; 89 buf[w_pos++] = '.'; 90 buf[w_pos++] = '.'; 91 buf[w_pos++] = '.'; 92 } 93 buf[w_pos] = 0; 94 return buf; 95 } 96 97 98 #define TEST_BIN_MAX_SIZE (2 * 1024) 99 100 /* return zero if succeed, number of failures otherwise */ 101 static unsigned int 102 expect_decoded_n (const char *const hex, const size_t hex_len, 103 const uint8_t *const bin, const size_t bin_size, 104 const unsigned int line_num) 105 { 106 static const char fill_chr = '#'; 107 static char buf[TEST_BIN_MAX_SIZE]; 108 size_t res_size; 109 unsigned int ret; 110 111 mhd_assert (NULL != hex); 112 mhd_assert (NULL != bin); 113 mhd_assert (TEST_BIN_MAX_SIZE > bin_size + 1); 114 mhd_assert (TEST_BIN_MAX_SIZE > hex_len + 1); 115 mhd_assert (hex_len >= bin_size); 116 mhd_assert (1 >= hex_len || hex_len > bin_size); 117 118 ret = 0; 119 120 /* check MHD_hex_to_bin() */ 121 if (1) 122 { 123 unsigned int check_res = 0; 124 125 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 126 res_size = MHD_hex_to_bin (hex, hex_len, buf); 127 if (res_size != bin_size) 128 { 129 check_res = 1; 130 fprintf (stderr, 131 "'MHD_hex_to_bin ()' FAILED: " 132 "Wrong returned value:\n"); 133 } 134 else 135 { 136 if ((0 != bin_size) && 137 (0 != memcmp (buf, bin, bin_size))) 138 { 139 check_res = 1; 140 fprintf (stderr, 141 "'MHD_hex_to_bin ()' FAILED: " 142 "Wrong output data:\n"); 143 } 144 } 145 if (((0 == res_size) && (fill_chr != buf[bin_size])) 146 || ((0 != res_size) && (fill_chr != buf[res_size]))) 147 { 148 check_res = 1; 149 fprintf (stderr, 150 "'MHD_hex_to_bin ()' FAILED: " 151 "A char written outside the buffer:\n"); 152 } 153 if (0 != check_res) 154 { 155 ret++; 156 fprintf (stderr, 157 "\tRESULT : MHD_hex_to_bin (\"%s\", %u, " 158 "->\"%s\") -> %u\n", 159 n_prnt (hex, hex_len), (unsigned) hex_len, 160 n_prnt (buf, res_size), 161 (unsigned) res_size); 162 fprintf (stderr, 163 "\tEXPECTED: MHD_hex_to_bin (\"%s\", %u, " 164 "->\"%s\") -> %u\n", 165 n_prnt (hex, hex_len), (unsigned) hex_len, 166 n_prnt ((const char *) bin, bin_size), 167 (unsigned) bin_size); 168 } 169 } 170 171 /* check MHD_bin_to_hex() */ 172 if (0 == hex_len % 2) 173 { 174 unsigned int check_res = 0; 175 176 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 177 res_size = MHD_bin_to_hex_z (bin, bin_size, buf); 178 179 if (res_size != hex_len) 180 { 181 check_res = 1; 182 fprintf (stderr, 183 "'MHD_bin_to_hex ()' FAILED: " 184 "Wrong returned value:\n"); 185 } 186 else 187 { 188 if ((0 != hex_len) && 189 (! MHD_str_equal_caseless_bin_n_ (buf, hex, hex_len))) 190 { 191 check_res = 1; 192 fprintf (stderr, 193 "'MHD_bin_to_hex ()' FAILED: " 194 "Wrong output string:\n"); 195 } 196 } 197 if (fill_chr != buf[res_size + 1]) 198 { 199 check_res = 1; 200 fprintf (stderr, 201 "'MHD_bin_to_hex ()' FAILED: " 202 "A char written outside the buffer:\n"); 203 } 204 if (0 != buf[res_size]) 205 { 206 check_res = 1; 207 fprintf (stderr, 208 "'MHD_bin_to_hex ()' FAILED: " 209 "The result is not zero-terminated:\n"); 210 } 211 if (0 != check_res) 212 { 213 ret++; 214 fprintf (stderr, 215 "\tRESULT : MHD_bin_to_hex (\"%s\", %u, " 216 "->\"%s\") -> %u\n", 217 n_prnt ((const char *) bin, bin_size), (unsigned) bin_size, 218 n_prnt (buf, res_size), 219 (unsigned) res_size); 220 fprintf (stderr, 221 "\tEXPECTED: MHD_bin_to_hex (\"%s\", %u, " 222 "->(lower case)\"%s\") -> %u\n", 223 n_prnt ((const char *) bin, bin_size), (unsigned) bin_size, 224 n_prnt (hex, hex_len), 225 (unsigned) bin_size); 226 } 227 } 228 229 if (0 != ret) 230 { 231 fprintf (stderr, 232 "The check is at line: %u\n\n", line_num); 233 } 234 return ret; 235 } 236 237 238 #define expect_decoded_arr(h,a) \ 239 expect_decoded_n(h,MHD_STATICSTR_LEN_(h),\ 240 a,(sizeof(a)/sizeof(a[0])), \ 241 __LINE__) 242 243 static unsigned int 244 check_decode_bin (void) 245 { 246 unsigned int r = 0; /**< The number of errors */ 247 248 if (1) 249 { 250 static const uint8_t bin[256] = 251 {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 252 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 253 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 254 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 255 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 256 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 257 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 258 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 259 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 260 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 261 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 262 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 263 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 264 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 265 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 266 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 267 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 268 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 269 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 270 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 271 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 272 0xff }; 273 /* The lower case */ 274 r += expect_decoded_arr ("000102030405060708090a0b0c0d0e" \ 275 "0f101112131415161718191a1b1c1d" \ 276 "1e1f202122232425262728292a2b2c" \ 277 "2d2e2f303132333435363738393a3b" \ 278 "3c3d3e3f404142434445464748494a" \ 279 "4b4c4d4e4f50515253545556575859" \ 280 "5a5b5c5d5e5f606162636465666768" \ 281 "696a6b6c6d6e6f7071727374757677" \ 282 "78797a7b7c7d7e7f80818283848586" \ 283 "8788898a8b8c8d8e8f909192939495" \ 284 "969798999a9b9c9d9e9fa0a1a2a3a4" \ 285 "a5a6a7a8a9aaabacadaeafb0b1b2b3" \ 286 "b4b5b6b7b8b9babbbcbdbebfc0c1c2" \ 287 "c3c4c5c6c7c8c9cacbcccdcecfd0d1" \ 288 "d2d3d4d5d6d7d8d9dadbdcdddedfe0" \ 289 "e1e2e3e4e5e6e7e8e9eaebecedeeef" \ 290 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfe" \ 291 "ff", bin); 292 } 293 294 if (1) 295 { 296 static const uint8_t bin[256] = 297 {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 298 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 299 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 300 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 301 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 302 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 303 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 304 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 305 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 306 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 307 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 308 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 309 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 310 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 311 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 312 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 313 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 314 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 315 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 316 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 317 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 318 0xff }; 319 /* The upper case */ 320 r += expect_decoded_arr ("000102030405060708090A0B0C0D0E" \ 321 "0F101112131415161718191A1B1C1D" \ 322 "1E1F202122232425262728292A2B2C" \ 323 "2D2E2F303132333435363738393A3B" \ 324 "3C3D3E3F404142434445464748494A" \ 325 "4B4C4D4E4F50515253545556575859" \ 326 "5A5B5C5D5E5F606162636465666768" \ 327 "696A6B6C6D6E6F7071727374757677" \ 328 "78797A7B7C7D7E7F80818283848586" \ 329 "8788898A8B8C8D8E8F909192939495" \ 330 "969798999A9B9C9D9E9FA0A1A2A3A4" \ 331 "A5A6A7A8A9AAABACADAEAFB0B1B2B3" \ 332 "B4B5B6B7B8B9BABBBCBDBEBFC0C1C2" \ 333 "C3C4C5C6C7C8C9CACBCCCDCECFD0D1" \ 334 "D2D3D4D5D6D7D8D9DADBDCDDDEDFE0" \ 335 "E1E2E3E4E5E6E7E8E9EAEBECEDEEEF" \ 336 "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFE" \ 337 "FF", bin); 338 } 339 if (1) 340 { 341 static const uint8_t bin[3] = 342 {0x1, 0x2, 0x3}; 343 r += expect_decoded_arr ("010203", bin); 344 } 345 if (1) 346 { 347 static const uint8_t bin[3] = 348 {0x1, 0x2, 0x3}; 349 r += expect_decoded_arr ("10203", bin); 350 } 351 if (1) 352 { 353 static const uint8_t bin[1] = 354 {0x1}; 355 r += expect_decoded_arr ("01", bin); 356 } 357 if (1) 358 { 359 static const uint8_t bin[1] = 360 {0x1}; 361 r += expect_decoded_arr ("1", bin); 362 } 363 364 return r; 365 } 366 367 368 /* return zero if succeed, number of failures otherwise */ 369 static unsigned int 370 expect_failed_n (const char *const hex, const size_t hex_len, 371 const unsigned int line_num) 372 { 373 static const char fill_chr = '#'; 374 static char buf[TEST_BIN_MAX_SIZE]; 375 size_t res_size; 376 unsigned int ret; 377 378 mhd_assert (NULL != hex); 379 mhd_assert (TEST_BIN_MAX_SIZE > hex_len + 1); 380 381 ret = 0; 382 383 /* check MHD_hex_to_bin() */ 384 if (1) 385 { 386 unsigned int check_res = 0; 387 388 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 389 res_size = MHD_hex_to_bin (hex, hex_len, buf); 390 if (res_size != 0) 391 { 392 check_res = 1; 393 fprintf (stderr, 394 "'MHD_hex_to_bin ()' FAILED: " 395 "Wrong returned value:\n"); 396 } 397 if (0 != check_res) 398 { 399 ret++; 400 fprintf (stderr, 401 "\tRESULT : MHD_hex_to_bin (\"%s\", %u, " 402 "->\"%s\") -> %u\n", 403 n_prnt (hex, hex_len), (unsigned) hex_len, 404 n_prnt (buf, res_size), 405 (unsigned) res_size); 406 fprintf (stderr, 407 "\tEXPECTED: MHD_hex_to_bin (\"%s\", %u, " 408 "->(not defined)) -> 0\n", 409 n_prnt (hex, hex_len), (unsigned) hex_len); 410 } 411 } 412 413 if (0 != ret) 414 { 415 fprintf (stderr, 416 "The check is at line: %u\n\n", line_num); 417 } 418 return ret; 419 } 420 421 422 #define expect_failed(h) \ 423 expect_failed_n(h,MHD_STATICSTR_LEN_(h), \ 424 __LINE__) 425 426 427 static unsigned int 428 check_broken_str (void) 429 { 430 unsigned int r = 0; /**< The number of errors */ 431 432 r += expect_failed ("abcx"); 433 r += expect_failed ("X"); 434 r += expect_failed ("!"); 435 r += expect_failed ("01z"); 436 r += expect_failed ("0z"); 437 r += expect_failed ("00z"); 438 r += expect_failed ("000Y"); 439 440 return r; 441 } 442 443 444 /** 445 * The maximum length of the hexadecimal input used by the exact-sized 446 * output buffer checks. 447 */ 448 #define TEST_EXACT_MAX_HEX_LEN 320 449 450 /** 451 * The number of the guard bytes placed right after the output buffer. 452 */ 453 #define TEST_GUARD_SIZE 8 454 455 /** 456 * The value used to fill the guard bytes. 457 */ 458 #define TEST_GUARD_CHR 0x5A 459 460 /** 461 * Check that MHD_hex_to_bin() writes no more than the documented number of 462 * the output bytes, which is ((@a hex_len + 1) / 2). 463 * 464 * Every caller of MHD_hex_to_bin() must size the output buffer by that 465 * formula. A caller that sizes the buffer by the expected size of the 466 * decoded value instead (like the digest authentication 'response' check 467 * used to do) can be overflown by simply sending a longer hexadecimal 468 * string, therefore this contract is checked here with buffers that have 469 * no slack at all: 470 * - an exactly-sized heap allocation, so that a run-time memory checker 471 * (ASAN, valgrind) traps any out-of-bounds write immediately, and 472 * - an allocation with a known guard pattern right after the output area, 473 * so that the overflow is detected even without any such tool. 474 * 475 * @param hex the input string with hexadecimal digits 476 * @param hex_len the length of @a hex 477 * @param must_succeed non-zero if the decoding is expected to succeed 478 * @param line_num the line number to report in case of failure 479 * @return zero if succeed, number of failures otherwise 480 */ 481 static unsigned int 482 expect_exact_dest_n (const char *const hex, 483 const size_t hex_len, 484 const int must_succeed, 485 const unsigned int line_num) 486 { 487 const size_t max_out_size = (hex_len + 1) / 2; 488 const size_t expected_size = must_succeed ? max_out_size : 0; 489 uint8_t *buf; 490 size_t res_size; 491 size_t i; 492 unsigned int ret; 493 494 ret = 0; 495 496 /* (1) The exactly-sized output buffer. */ 497 buf = (uint8_t *) malloc (0 != max_out_size ? max_out_size : 1); 498 if (NULL == buf) 499 { 500 fprintf (stderr, "malloc() failed. Line: %u\n", line_num); 501 return 1; 502 } 503 res_size = MHD_hex_to_bin (hex, hex_len, buf); 504 free (buf); 505 if (res_size != expected_size) 506 { 507 ret++; 508 fprintf (stderr, 509 "'MHD_hex_to_bin ()' FAILED: " 510 "Wrong returned value with the exactly-sized buffer:\n"); 511 fprintf (stderr, 512 "\tRESULT : MHD_hex_to_bin (\"%s\", %u, ...) -> %u\n", 513 n_prnt (hex, hex_len), (unsigned) hex_len, 514 (unsigned) res_size); 515 fprintf (stderr, 516 "\tEXPECTED: MHD_hex_to_bin (\"%s\", %u, ...) -> %u\n", 517 n_prnt (hex, hex_len), (unsigned) hex_len, 518 (unsigned) expected_size); 519 } 520 521 /* (2) The output buffer followed by the guard bytes. */ 522 buf = (uint8_t *) malloc (max_out_size + TEST_GUARD_SIZE); 523 if (NULL == buf) 524 { 525 fprintf (stderr, "malloc() failed. Line: %u\n", line_num); 526 return ret + 1; 527 } 528 memset (buf, TEST_GUARD_CHR, max_out_size + TEST_GUARD_SIZE); 529 res_size = MHD_hex_to_bin (hex, hex_len, buf); 530 if (res_size > max_out_size) 531 { 532 ret++; 533 fprintf (stderr, 534 "'MHD_hex_to_bin ()' FAILED: " 535 "Returned value is larger than the documented maximum " 536 "output size: %u > %u\n", 537 (unsigned) res_size, (unsigned) max_out_size); 538 } 539 for (i = 0; i < TEST_GUARD_SIZE; ++i) 540 { 541 if (TEST_GUARD_CHR != buf[max_out_size + i]) 542 { 543 ret++; 544 fprintf (stderr, 545 "'MHD_hex_to_bin ()' FAILED: " 546 "The guard byte number %u (of %u) after the output buffer " 547 "has been overwritten:\n", 548 (unsigned) i, (unsigned) TEST_GUARD_SIZE); 549 fprintf (stderr, 550 "\tINPUT : MHD_hex_to_bin (\"%s\", %u, ...), " 551 "the maximum output size is %u\n", 552 n_prnt (hex, hex_len), (unsigned) hex_len, 553 (unsigned) max_out_size); 554 break; 555 } 556 } 557 free (buf); 558 559 if (0 != ret) 560 { 561 fprintf (stderr, 562 "The check is at line: %u\n\n", line_num); 563 } 564 return ret; 565 } 566 567 568 #define expect_exact_dest(h,ms) \ 569 expect_exact_dest_n (h, MHD_STATICSTR_LEN_ (h), ms, __LINE__) 570 571 572 /** 573 * Check the output size contract of MHD_hex_to_bin() for every input length 574 * up to #TEST_EXACT_MAX_HEX_LEN, for valid and for broken input. 575 * 576 * @return zero if succeed, number of failures otherwise 577 */ 578 static unsigned int 579 check_exact_dest_buffer (void) 580 { 581 static const char hex_digits[] = "0123456789abcdefABCDEF"; 582 static char hex[TEST_EXACT_MAX_HEX_LEN + 1]; 583 unsigned int r = 0; /**< The number of errors */ 584 size_t len; 585 586 for (len = 0; len < sizeof(hex) - 1; ++len) 587 hex[len] = hex_digits[len % (sizeof(hex_digits) - 1)]; 588 hex[sizeof(hex) - 1] = 0; 589 590 /* Valid input of every length, including the odd lengths for which 591 an extra leading zero is assumed and therefore one more byte is 592 written than (hex_len / 2). */ 593 for (len = 0; len <= TEST_EXACT_MAX_HEX_LEN; ++len) 594 r += expect_exact_dest_n (hex, len, 1, __LINE__); 595 596 /* Broken input: a non-hexadecimal character at every possible position. 597 The decoding fails, but the bytes decoded before the broken character 598 have already been written and must still fit into the output buffer. */ 599 for (len = 1; len <= 64; ++len) 600 { 601 size_t pos; 602 603 for (pos = 0; pos < len; ++pos) 604 { 605 const char saved = hex[pos]; 606 607 hex[pos] = 'z'; 608 r += expect_exact_dest_n (hex, len, 0, __LINE__); 609 hex[pos] = saved; 610 } 611 } 612 613 /* The lengths that matter for the HTTP Digest authentication code: 614 twice the digest size is the largest input any caller may accept. */ 615 r += expect_exact_dest ("00112233445566778899aabbccddeeff", 1); /* MD5 */ 616 r += expect_exact_dest ("00112233445566778899aabbccddeeff" 617 "00112233445566778899aabbccddeeff", 1); /* SHA-256 */ 618 /* Twice as long as the largest supported digest: a caller that sizes the 619 output buffer by the digest size only would be overflown here. */ 620 r += expect_exact_dest ("00112233445566778899aabbccddeeff" 621 "00112233445566778899aabbccddeeff" 622 "00112233445566778899aabbccddeeff" 623 "00112233445566778899aabbccddeeff", 1); 624 625 return r; 626 } 627 628 629 int 630 main (int argc, char *argv[]) 631 { 632 unsigned int errcount = 0; 633 (void) argc; (void) argv; /* Unused. Silent compiler warning. */ 634 errcount += check_decode_bin (); 635 errcount += check_broken_str (); 636 errcount += check_exact_dest_buffer (); 637 if (0 == errcount) 638 printf ("All tests have been passed without errors.\n"); 639 return errcount == 0 ? 0 : 1; 640 }