test_str_pct.c (38372B)
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_pct.c 22 * @brief Unit tests for percent (URL) encoded strings 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 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this 33 test into a marked, classifiable test error (TESTING.md, P5). */ 34 #include "mhd_panic_tripwire.h" 35 36 #ifndef MHD_STATICSTR_LEN_ 37 /** 38 * Determine length of static string / macro strings at compile time. 39 */ 40 #define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1) 41 #endif /* ! MHD_STATICSTR_LEN_ */ 42 43 44 static char tmp_bufs[4][4 * 1024]; /* should be enough for testing */ 45 static size_t buf_idx = 0; 46 47 /* print non-printable chars as char codes */ 48 static char * 49 n_prnt (const char *str, size_t len) 50 { 51 static char *buf; /* should be enough for testing */ 52 static const size_t buf_size = sizeof(tmp_bufs[0]); 53 size_t r_pos = 0; 54 size_t w_pos = 0; 55 if (++buf_idx >= (sizeof(tmp_bufs) / sizeof(tmp_bufs[0]))) 56 buf_idx = 0; 57 buf = tmp_bufs[buf_idx]; 58 59 while (len > r_pos && w_pos + 1 < buf_size) 60 { 61 const unsigned char c = (unsigned char) str[r_pos]; 62 if ((c == '\\') || (c == '"') ) 63 { 64 if (w_pos + 2 >= buf_size) 65 break; 66 buf[w_pos++] = '\\'; 67 buf[w_pos++] = (char) c; 68 } 69 else if ((c >= 0x20) && (c <= 0x7E) ) 70 buf[w_pos++] = (char) c; 71 else 72 { 73 if (w_pos + 4 >= buf_size) 74 break; 75 if (snprintf (buf + w_pos, buf_size - w_pos, "\\x%02hX", (short unsigned 76 int) c) != 4) 77 break; 78 w_pos += 4; 79 } 80 r_pos++; 81 } 82 83 if (len != r_pos) 84 { /* not full string is printed */ 85 /* enough space for "..." ? */ 86 if (w_pos + 3 > buf_size) 87 w_pos = buf_size - 4; 88 buf[w_pos++] = '.'; 89 buf[w_pos++] = '.'; 90 buf[w_pos++] = '.'; 91 } 92 buf[w_pos] = 0; 93 return buf; 94 } 95 96 97 #define TEST_BIN_MAX_SIZE 1024 98 99 /* return zero if succeed, number of failures otherwise */ 100 static unsigned int 101 expect_decoded_n (const char *const encoded, const size_t encoded_len, 102 const char *const decoded, const size_t decoded_size, 103 const unsigned int line_num) 104 { 105 static const char fill_chr = '#'; 106 static char buf[TEST_BIN_MAX_SIZE]; 107 size_t res_size; 108 unsigned int ret; 109 110 mhd_assert (NULL != encoded); 111 mhd_assert (NULL != decoded); 112 mhd_assert (TEST_BIN_MAX_SIZE > decoded_size + 1); 113 mhd_assert (TEST_BIN_MAX_SIZE > encoded_len + 1); 114 mhd_assert (encoded_len >= decoded_size); 115 116 ret = 0; 117 118 /* check MHD_str_pct_decode_strict_n_() with small out buffer */ 119 if (1) 120 { 121 unsigned int check_res = 0; 122 123 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 124 res_size = MHD_str_pct_decode_strict_n_ (encoded, encoded_len, buf, 125 decoded_size + 1); 126 if (res_size != decoded_size) 127 { 128 check_res = 1; 129 fprintf (stderr, 130 "'MHD_str_pct_decode_strict_n_ ()' FAILED: " 131 "Wrong returned value:\n"); 132 } 133 else 134 { 135 if (fill_chr != buf[res_size]) 136 { 137 check_res = 1; 138 fprintf (stderr, 139 "'MHD_str_pct_decode_strict_n_ ()' FAILED: " 140 "A char written outside the buffer:\n"); 141 } 142 else 143 { 144 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 145 res_size = MHD_str_pct_decode_strict_n_ (encoded, encoded_len, buf, 146 decoded_size); 147 if (res_size != decoded_size) 148 { 149 check_res = 1; 150 fprintf (stderr, 151 "'MHD_str_pct_decode_strict_n_ ()' FAILED: " 152 "Wrong returned value:\n"); 153 } 154 } 155 if ((res_size == decoded_size) && (0 != decoded_size) && 156 (0 != memcmp (buf, decoded, decoded_size))) 157 { 158 check_res = 1; 159 fprintf (stderr, 160 "'MHD_str_pct_decode_strict_n_ ()' FAILED: " 161 "Wrong output string:\n"); 162 } 163 } 164 if (0 != check_res) 165 { 166 ret++; 167 fprintf (stderr, 168 "\tRESULT : MHD_str_pct_decode_strict_n_ (\"%s\", %u, " 169 "->\"%s\", %u) -> %u\n", 170 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 171 n_prnt (buf, res_size), (unsigned) decoded_size, 172 (unsigned) res_size); 173 fprintf (stderr, 174 "\tEXPECTED: MHD_str_pct_decode_strict_n_ (\"%s\", %u, " 175 "->\"%s\", %u) -> %u\n", 176 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 177 n_prnt (decoded, decoded_size), (unsigned) decoded_size, 178 (unsigned) decoded_size); 179 } 180 } 181 182 /* check MHD_str_pct_decode_strict_n_() with large out buffer */ 183 if (1) 184 { 185 unsigned int check_res = 0; 186 187 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 188 res_size = MHD_str_pct_decode_strict_n_ (encoded, encoded_len, buf, 189 encoded_len + 1); 190 if (res_size != decoded_size) 191 { 192 check_res = 1; 193 fprintf (stderr, 194 "'MHD_str_pct_decode_strict_n_ ()' FAILED: " 195 "Wrong returned value:\n"); 196 } 197 else 198 { 199 if (fill_chr != buf[res_size]) 200 { 201 check_res = 1; 202 fprintf (stderr, 203 "'MHD_str_pct_decode_strict_n_ ()' FAILED: " 204 "A char written outside the buffer:\n"); 205 } 206 if ((res_size == decoded_size) && (0 != decoded_size) && 207 (0 != memcmp (buf, decoded, decoded_size))) 208 { 209 check_res = 1; 210 fprintf (stderr, 211 "'MHD_str_pct_decode_strict_n_ ()' FAILED: " 212 "Wrong output string:\n"); 213 } 214 } 215 if (0 != check_res) 216 { 217 ret++; 218 fprintf (stderr, 219 "\tRESULT : MHD_str_pct_decode_strict_n_ (\"%s\", %u, " 220 "->\"%s\", %u) -> %u\n", 221 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 222 n_prnt (buf, res_size), (unsigned) (encoded_len + 1), 223 (unsigned) res_size); 224 fprintf (stderr, 225 "\tEXPECTED: MHD_str_pct_decode_strict_n_ (\"%s\", %u, " 226 "->\"%s\", %u) -> %u\n", 227 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 228 n_prnt (decoded, decoded_size), (unsigned) (encoded_len + 1), 229 (unsigned) decoded_size); 230 } 231 } 232 233 /* check MHD_str_pct_decode_lenient_n_() with small out buffer */ 234 if (1) 235 { 236 unsigned int check_res = 0; 237 bool is_broken = true; 238 239 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 240 res_size = MHD_str_pct_decode_lenient_n_ (encoded, encoded_len, buf, 241 decoded_size + 1, &is_broken); 242 if (res_size != decoded_size) 243 { 244 check_res = 1; 245 fprintf (stderr, 246 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 247 "Wrong returned value:\n"); 248 } 249 else 250 { 251 if (fill_chr != buf[res_size]) 252 { 253 check_res = 1; 254 fprintf (stderr, 255 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 256 "A char written outside the buffer:\n"); 257 } 258 else 259 { 260 is_broken = true; 261 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 262 res_size = MHD_str_pct_decode_lenient_n_ (encoded, encoded_len, buf, 263 decoded_size, &is_broken); 264 if (res_size != decoded_size) 265 { 266 check_res = 1; 267 fprintf (stderr, 268 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 269 "Wrong returned value:\n"); 270 } 271 } 272 if (is_broken) 273 { 274 check_res = 1; 275 fprintf (stderr, 276 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 277 "Wrong 'broken_encoding' result:\n"); 278 } 279 if ((res_size == decoded_size) && (0 != decoded_size) && 280 (0 != memcmp (buf, decoded, decoded_size))) 281 { 282 check_res = 1; 283 fprintf (stderr, 284 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 285 "Wrong output string:\n"); 286 } 287 } 288 if (0 != check_res) 289 { 290 ret++; 291 fprintf (stderr, 292 "\tRESULT : MHD_str_pct_decode_lenient_n_ (\"%s\", %u, " 293 "->\"%s\", %u, ->%s) -> %u\n", 294 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 295 n_prnt (buf, res_size), (unsigned) decoded_size, 296 is_broken ? "true" : "false", 297 (unsigned) res_size); 298 fprintf (stderr, 299 "\tEXPECTED: MHD_str_pct_decode_lenient_n_ (\"%s\", %u, " 300 "->\"%s\", %u, ->false) -> %u\n", 301 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 302 n_prnt (decoded, decoded_size), (unsigned) decoded_size, 303 (unsigned) decoded_size); 304 } 305 } 306 307 /* check MHD_str_pct_decode_lenient_n_() with large out buffer */ 308 if (1) 309 { 310 unsigned int check_res = 0; 311 bool is_broken = true; 312 313 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 314 res_size = MHD_str_pct_decode_lenient_n_ (encoded, encoded_len, buf, 315 encoded_len + 1, &is_broken); 316 if (res_size != decoded_size) 317 { 318 check_res = 1; 319 fprintf (stderr, 320 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 321 "Wrong returned value:\n"); 322 } 323 else 324 { 325 if (fill_chr != buf[res_size]) 326 { 327 check_res = 1; 328 fprintf (stderr, 329 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 330 "A char written outside the buffer:\n"); 331 } 332 if (is_broken) 333 { 334 check_res = 1; 335 fprintf (stderr, 336 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 337 "Wrong 'broken_encoding' result:\n"); 338 } 339 if ((res_size == decoded_size) && (0 != decoded_size) && 340 (0 != memcmp (buf, decoded, decoded_size))) 341 { 342 check_res = 1; 343 fprintf (stderr, 344 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 345 "Wrong output string:\n"); 346 } 347 } 348 if (0 != check_res) 349 { 350 ret++; 351 fprintf (stderr, 352 "\tRESULT : MHD_str_pct_decode_lenient_n_ (\"%s\", %u, " 353 "->\"%s\", %u, ->%s) -> %u\n", 354 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 355 n_prnt (buf, res_size), (unsigned) (encoded_len + 1), 356 is_broken ? "true" : "false", 357 (unsigned) res_size); 358 fprintf (stderr, 359 "\tEXPECTED: MHD_str_pct_decode_lenient_n_ (\"%s\", %u, " 360 "->\"%s\", %u, ->false) -> %u\n", 361 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 362 n_prnt (decoded, decoded_size), (unsigned) (encoded_len + 1), 363 (unsigned) decoded_size); 364 } 365 } 366 367 if (strlen (encoded) == encoded_len) 368 { 369 /* check MHD_str_pct_decode_in_place_strict_() */ 370 if (1) 371 { 372 unsigned int check_res = 0; 373 374 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 375 memcpy (buf, encoded, encoded_len); 376 buf[encoded_len] = 0; 377 res_size = MHD_str_pct_decode_in_place_strict_ (buf); 378 if (res_size != decoded_size) 379 { 380 check_res = 1; 381 fprintf (stderr, 382 "'MHD_str_pct_decode_in_place_strict_ ()' FAILED: " 383 "Wrong returned value:\n"); 384 } 385 else 386 { 387 if (0 != buf[res_size]) 388 { 389 check_res = 1; 390 fprintf (stderr, 391 "'MHD_str_pct_decode_in_place_strict_ ()' FAILED: " 392 "The result is not zero-terminated:\n"); 393 } 394 if (((res_size + 1) < encoded_len) ? 395 (encoded[res_size + 1] != buf[res_size + 1]) : 396 (fill_chr != buf[res_size + 1])) 397 { 398 check_res = 1; 399 fprintf (stderr, 400 "'MHD_str_pct_decode_in_place_strict_ ()' FAILED: " 401 "A char written outside the buffer:\n"); 402 } 403 if ((res_size == decoded_size) && (0 != decoded_size) && 404 (0 != memcmp (buf, decoded, decoded_size))) 405 { 406 check_res = 1; 407 fprintf (stderr, 408 "'MHD_str_pct_decode_in_place_strict_ ()' FAILED: " 409 "Wrong output string:\n"); 410 } 411 } 412 if (0 != check_res) 413 { 414 ret++; 415 fprintf (stderr, 416 "\tRESULT : MHD_str_pct_decode_in_place_strict_ (\"%s\" " 417 "-> \"%s\") -> %u\n", 418 n_prnt (encoded, encoded_len), 419 n_prnt (buf, res_size), 420 (unsigned) res_size); 421 fprintf (stderr, 422 "\tEXPECTED: MHD_str_pct_decode_in_place_strict_ (\"%s\" " 423 "-> \"%s\") -> %u\n", 424 n_prnt (encoded, encoded_len), 425 n_prnt (decoded, decoded_size), 426 (unsigned) decoded_size); 427 } 428 } 429 430 /* check MHD_str_pct_decode_in_place_lenient_() */ 431 if (1) 432 { 433 unsigned int check_res = 0; 434 bool is_broken = true; 435 436 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 437 memcpy (buf, encoded, encoded_len); 438 buf[encoded_len] = 0; 439 res_size = MHD_str_pct_decode_in_place_lenient_ (buf, &is_broken); 440 if (res_size != decoded_size) 441 { 442 check_res = 1; 443 fprintf (stderr, 444 "'MHD_str_pct_decode_in_place_lenient_ ()' FAILED: " 445 "Wrong returned value:\n"); 446 } 447 else 448 { 449 if (0 != buf[res_size]) 450 { 451 check_res = 1; 452 fprintf (stderr, 453 "'MHD_str_pct_decode_in_place_lenient_ ()' FAILED: " 454 "The result is not zero-terminated:\n"); 455 } 456 if (((res_size + 1) < encoded_len) ? 457 (encoded[res_size + 1] != buf[res_size + 1]) : 458 (fill_chr != buf[res_size + 1])) 459 { 460 check_res = 1; 461 fprintf (stderr, 462 "'MHD_str_pct_decode_in_place_lenient_ ()' FAILED: " 463 "A char written outside the buffer:\n"); 464 } 465 if (is_broken) 466 { 467 check_res = 1; 468 fprintf (stderr, 469 "'MHD_str_pct_decode_in_place_lenient_ ()' FAILED: " 470 "Wrong 'broken_encoding' result:\n"); 471 } 472 if ((res_size == decoded_size) && (0 != decoded_size) && 473 (0 != memcmp (buf, decoded, decoded_size))) 474 { 475 check_res = 1; 476 fprintf (stderr, 477 "'MHD_str_pct_decode_in_place_lenient_ ()' FAILED: " 478 "Wrong output string:\n"); 479 } 480 } 481 if (0 != check_res) 482 { 483 ret++; 484 fprintf (stderr, 485 "\tRESULT : MHD_str_pct_decode_in_place_lenient_ (\"%s\" " 486 "-> \"%s\", ->%s) -> %u\n", 487 n_prnt (encoded, encoded_len), 488 n_prnt (buf, res_size), 489 is_broken ? "true" : "false", 490 (unsigned) res_size); 491 fprintf (stderr, 492 "\tEXPECTED: MHD_str_pct_decode_in_place_lenient_ (\"%s\" " 493 "-> \"%s\", ->false) -> %u\n", 494 n_prnt (encoded, encoded_len), 495 n_prnt (decoded, decoded_size), 496 (unsigned) decoded_size); 497 } 498 } 499 } 500 501 if (0 != ret) 502 { 503 fprintf (stderr, 504 "The check is at line: %u\n\n", line_num); 505 } 506 return ret; 507 } 508 509 510 #define expect_decoded(e,d) \ 511 expect_decoded_n(e,MHD_STATICSTR_LEN_(e),\ 512 d,MHD_STATICSTR_LEN_(d), \ 513 __LINE__) 514 515 static unsigned int 516 check_decode_str (void) 517 { 518 unsigned int r = 0; /**< The number of errors */ 519 520 r += expect_decoded ("", ""); 521 522 /* Base sequences without percent symbol */ 523 r += expect_decoded ("aaa", "aaa"); 524 r += expect_decoded ("bbb", "bbb"); 525 r += expect_decoded ("ccc", "ccc"); 526 r += expect_decoded ("ddd", "ddd"); 527 r += expect_decoded ("lll", "lll"); 528 r += expect_decoded ("mmm", "mmm"); 529 r += expect_decoded ("nnn", "nnn"); 530 r += expect_decoded ("ooo", "ooo"); 531 r += expect_decoded ("www", "www"); 532 r += expect_decoded ("xxx", "xxx"); 533 r += expect_decoded ("yyy", "yyy"); 534 r += expect_decoded ("zzz", "zzz"); 535 r += expect_decoded ("AAA", "AAA"); 536 r += expect_decoded ("GGG", "GGG"); 537 r += expect_decoded ("MMM", "MMM"); 538 r += expect_decoded ("TTT", "TTT"); 539 r += expect_decoded ("ZZZ", "ZZZ"); 540 r += expect_decoded ("012", "012"); 541 r += expect_decoded ("345", "345"); 542 r += expect_decoded ("678", "678"); 543 r += expect_decoded ("901", "901"); 544 r += expect_decoded ("aaaaaa", "aaaaaa"); 545 r += expect_decoded ("bbbbbb", "bbbbbb"); 546 r += expect_decoded ("cccccc", "cccccc"); 547 r += expect_decoded ("dddddd", "dddddd"); 548 r += expect_decoded ("llllll", "llllll"); 549 r += expect_decoded ("mmmmmm", "mmmmmm"); 550 r += expect_decoded ("nnnnnn", "nnnnnn"); 551 r += expect_decoded ("oooooo", "oooooo"); 552 r += expect_decoded ("wwwwww", "wwwwww"); 553 r += expect_decoded ("xxxxxx", "xxxxxx"); 554 r += expect_decoded ("yyyyyy", "yyyyyy"); 555 r += expect_decoded ("zzzzzz", "zzzzzz"); 556 r += expect_decoded ("AAAAAA", "AAAAAA"); 557 r += expect_decoded ("GGGGGG", "GGGGGG"); 558 r += expect_decoded ("MMMMMM", "MMMMMM"); 559 r += expect_decoded ("TTTTTT", "TTTTTT"); 560 r += expect_decoded ("ZZZZZZ", "ZZZZZZ"); 561 r += expect_decoded ("012012", "012012"); 562 r += expect_decoded ("345345", "345345"); 563 r += expect_decoded ("678678", "678678"); 564 r += expect_decoded ("901901", "901901"); 565 r += expect_decoded ("a", "a"); 566 r += expect_decoded ("bc", "bc"); 567 r += expect_decoded ("DEFG", "DEFG"); 568 r += expect_decoded ("123t", "123t"); 569 r += expect_decoded ("12345", "12345"); 570 r += expect_decoded ("TestStr", "TestStr"); 571 r += expect_decoded ("Teststring", "Teststring"); 572 r += expect_decoded ("Teststring.", "Teststring."); 573 r += expect_decoded ("Longerstring", "Longerstring"); 574 r += expect_decoded ("Longerstring.", "Longerstring."); 575 r += expect_decoded ("Longerstring2.", "Longerstring2."); 576 577 /* Simple percent-encoded strings */ 578 r += expect_decoded ("Test%20string", "Test string"); 579 r += expect_decoded ("Test%3Fstring.", "Test?string."); 580 r += expect_decoded ("100%25", "100%"); 581 r += expect_decoded ("a%2C%20b%3Dc%26e%3Dg", "a, b=c&e=g"); 582 r += expect_decoded ("%20%21%23%24%25%26%27%28%29%2A%2B%2C" 583 "%2F%3A%3B%3D%3F%40%5B%5D%09", 584 " !#$%&'()*+,/:;=?@[]\t"); 585 586 return r; 587 } 588 589 590 #define expect_decoded_arr(e,a) \ 591 expect_decoded_n(e,MHD_STATICSTR_LEN_(e),\ 592 (const char *)a,(sizeof(a)/sizeof(a[0])), \ 593 __LINE__) 594 595 static unsigned int 596 check_decode_bin (void) 597 { 598 unsigned int r = 0; /**< The number of errors */ 599 600 if (1) 601 { 602 static const uint8_t bin[256] = 603 {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 604 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 605 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 606 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 607 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 608 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 609 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 610 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 611 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 612 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 613 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 614 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 615 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 616 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 617 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 618 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 619 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 620 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 621 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 622 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 623 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 624 0xff }; 625 /* The lower case */ 626 r += expect_decoded_arr ("%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e" \ 627 "%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d" \ 628 "%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c" \ 629 "%2d%2e%2f%30%31%32%33%34%35%36%37%38%39%3a%3b" \ 630 "%3c%3d%3e%3f%40%41%42%43%44%45%46%47%48%49%4a" \ 631 "%4b%4c%4d%4e%4f%50%51%52%53%54%55%56%57%58%59" \ 632 "%5a%5b%5c%5d%5e%5f%60%61%62%63%64%65%66%67%68" \ 633 "%69%6a%6b%6c%6d%6e%6f%70%71%72%73%74%75%76%77" \ 634 "%78%79%7a%7b%7c%7d%7e%7f%80%81%82%83%84%85%86" \ 635 "%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95" \ 636 "%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4" \ 637 "%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3" \ 638 "%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2" \ 639 "%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1" \ 640 "%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0" \ 641 "%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef" \ 642 "%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe" \ 643 "%ff", bin); 644 } 645 646 if (1) 647 { 648 static const uint8_t bin[256] = 649 {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 650 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 651 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 652 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 653 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 654 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 655 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 656 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 657 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 658 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 659 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 660 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 661 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 662 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 663 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 664 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 665 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 666 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 667 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 668 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 669 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 670 0xff }; 671 /* The upper case */ 672 r += expect_decoded_arr ("%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E" \ 673 "%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D" \ 674 "%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C" \ 675 "%2D%2E%2F%30%31%32%33%34%35%36%37%38%39%3A%3B" \ 676 "%3C%3D%3E%3F%40%41%42%43%44%45%46%47%48%49%4A" \ 677 "%4B%4C%4D%4E%4F%50%51%52%53%54%55%56%57%58%59" \ 678 "%5A%5B%5C%5D%5E%5F%60%61%62%63%64%65%66%67%68" \ 679 "%69%6A%6B%6C%6D%6E%6F%70%71%72%73%74%75%76%77" \ 680 "%78%79%7A%7B%7C%7D%7E%7F%80%81%82%83%84%85%86" \ 681 "%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95" \ 682 "%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4" \ 683 "%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3" \ 684 "%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2" \ 685 "%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1" \ 686 "%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0" \ 687 "%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF" \ 688 "%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE" \ 689 "%FF", bin); 690 } 691 692 return r; 693 } 694 695 696 /* return zero if succeed, number of failures otherwise */ 697 static unsigned int 698 expect_decoded_bad_n (const char *const encoded, const size_t encoded_len, 699 const char *const decoded, const size_t decoded_size, 700 const unsigned int line_num) 701 { 702 static const char fill_chr = '#'; 703 static char buf[TEST_BIN_MAX_SIZE]; 704 size_t res_size; 705 unsigned int ret; 706 707 mhd_assert (NULL != encoded); 708 mhd_assert (NULL != decoded); 709 mhd_assert (TEST_BIN_MAX_SIZE > decoded_size + 1); 710 mhd_assert (TEST_BIN_MAX_SIZE > encoded_len + 1); 711 mhd_assert (encoded_len >= decoded_size); 712 713 ret = 0; 714 715 /* check MHD_str_pct_decode_strict_n_() with small out buffer */ 716 if (1) 717 { 718 unsigned int check_res = 0; 719 720 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 721 res_size = MHD_str_pct_decode_strict_n_ (encoded, encoded_len, buf, 722 decoded_size); 723 if (res_size != 0) 724 { 725 check_res = 1; 726 fprintf (stderr, 727 "'MHD_str_pct_decode_strict_n_ ()' FAILED: " 728 "Wrong returned value:\n"); 729 } 730 if (0 != check_res) 731 { 732 ret++; 733 fprintf (stderr, 734 "\tRESULT : MHD_str_pct_decode_strict_n_ (\"%s\", %u, " 735 "->\"%s\", %u) -> %u\n", 736 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 737 n_prnt (buf, res_size), (unsigned) decoded_size, 738 (unsigned) res_size); 739 fprintf (stderr, 740 "\tEXPECTED: MHD_str_pct_decode_strict_n_ (\"%s\", %u, " 741 "->(not defined), %u) -> 0\n", 742 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 743 (unsigned) decoded_size); 744 } 745 } 746 747 /* check MHD_str_pct_decode_strict_n_() with large out buffer */ 748 if (1) 749 { 750 unsigned int check_res = 0; 751 752 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 753 res_size = MHD_str_pct_decode_strict_n_ (encoded, encoded_len, buf, 754 encoded_len + 1); 755 if (res_size != 0) 756 { 757 check_res = 1; 758 fprintf (stderr, 759 "'MHD_str_pct_decode_strict_n_ ()' FAILED: " 760 "Wrong returned value:\n"); 761 } 762 if (0 != check_res) 763 { 764 ret++; 765 fprintf (stderr, 766 "\tRESULT : MHD_str_pct_decode_strict_n_ (\"%s\", %u, " 767 "->\"%s\", %u) -> %u\n", 768 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 769 n_prnt (buf, res_size), (unsigned) (encoded_len + 1), 770 (unsigned) res_size); 771 fprintf (stderr, 772 "\tEXPECTED: MHD_str_pct_decode_strict_n_ (\"%s\", %u, " 773 "->(not defined), %u) -> 0\n", 774 n_prnt (encoded, encoded_len), (unsigned) (encoded_len + 1), 775 (unsigned) decoded_size); 776 } 777 } 778 779 /* check MHD_str_pct_decode_lenient_n_() with small out buffer */ 780 if (1) 781 { 782 unsigned int check_res = 0; 783 bool is_broken = false; 784 785 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 786 res_size = MHD_str_pct_decode_lenient_n_ (encoded, encoded_len, buf, 787 decoded_size + 1, &is_broken); 788 if (res_size != decoded_size) 789 { 790 check_res = 1; 791 fprintf (stderr, 792 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 793 "Wrong returned value:\n"); 794 } 795 else 796 { 797 if (fill_chr != buf[res_size]) 798 { 799 check_res = 1; 800 fprintf (stderr, 801 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 802 "A char written outside the buffer:\n"); 803 } 804 else 805 { 806 is_broken = false; 807 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 808 res_size = MHD_str_pct_decode_lenient_n_ (encoded, encoded_len, buf, 809 decoded_size, &is_broken); 810 if (res_size != decoded_size) 811 { 812 check_res = 1; 813 fprintf (stderr, 814 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 815 "Wrong returned value:\n"); 816 } 817 } 818 if (! is_broken) 819 { 820 check_res = 1; 821 fprintf (stderr, 822 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 823 "Wrong 'broken_encoding' result:\n"); 824 } 825 if ((res_size == decoded_size) && (0 != decoded_size) && 826 (0 != memcmp (buf, decoded, decoded_size))) 827 { 828 check_res = 1; 829 fprintf (stderr, 830 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 831 "Wrong output string:\n"); 832 } 833 } 834 if (0 != check_res) 835 { 836 ret++; 837 fprintf (stderr, 838 "\tRESULT : MHD_str_pct_decode_lenient_n_ (\"%s\", %u, " 839 "->\"%s\", %u, ->%s) -> %u\n", 840 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 841 n_prnt (buf, res_size), (unsigned) decoded_size, 842 is_broken ? "true" : "false", 843 (unsigned) res_size); 844 fprintf (stderr, 845 "\tEXPECTED: MHD_str_pct_decode_lenient_n_ (\"%s\", %u, " 846 "->\"%s\", %u, ->true) -> %u\n", 847 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 848 n_prnt (decoded, decoded_size), (unsigned) decoded_size, 849 (unsigned) decoded_size); 850 } 851 } 852 853 /* check MHD_str_pct_decode_lenient_n_() with large out buffer */ 854 if (1) 855 { 856 unsigned int check_res = 0; 857 bool is_broken = false; 858 859 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 860 res_size = MHD_str_pct_decode_lenient_n_ (encoded, encoded_len, buf, 861 encoded_len + 1, &is_broken); 862 if (res_size != decoded_size) 863 { 864 check_res = 1; 865 fprintf (stderr, 866 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 867 "Wrong returned value:\n"); 868 } 869 else 870 { 871 if (fill_chr != buf[res_size]) 872 { 873 check_res = 1; 874 fprintf (stderr, 875 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 876 "A char written outside the buffer:\n"); 877 } 878 if (! is_broken) 879 { 880 check_res = 1; 881 fprintf (stderr, 882 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 883 "Wrong 'broken_encoding' result:\n"); 884 } 885 if ((res_size == decoded_size) && (0 != decoded_size) && 886 (0 != memcmp (buf, decoded, decoded_size))) 887 { 888 check_res = 1; 889 fprintf (stderr, 890 "'MHD_str_pct_decode_lenient_n_ ()' FAILED: " 891 "Wrong output string:\n"); 892 } 893 } 894 if (0 != check_res) 895 { 896 ret++; 897 fprintf (stderr, 898 "\tRESULT : MHD_str_pct_decode_lenient_n_ (\"%s\", %u, " 899 "->\"%s\", %u, ->%s) -> %u\n", 900 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 901 n_prnt (buf, res_size), (unsigned) (encoded_len + 1), 902 is_broken ? "true" : "false", 903 (unsigned) res_size); 904 fprintf (stderr, 905 "\tEXPECTED: MHD_str_pct_decode_lenient_n_ (\"%s\", %u, " 906 "->\"%s\", %u, ->true) -> %u\n", 907 n_prnt (encoded, encoded_len), (unsigned) encoded_len, 908 n_prnt (decoded, decoded_size), (unsigned) (encoded_len + 1), 909 (unsigned) decoded_size); 910 } 911 } 912 913 if (strlen (encoded) == encoded_len) 914 { 915 /* check MHD_str_pct_decode_in_place_strict_() */ 916 if (1) 917 { 918 unsigned int check_res = 0; 919 920 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 921 memcpy (buf, encoded, encoded_len); 922 buf[encoded_len] = 0; 923 res_size = MHD_str_pct_decode_in_place_strict_ (buf); 924 if (res_size != 0) 925 { 926 check_res = 1; 927 fprintf (stderr, 928 "'MHD_str_pct_decode_in_place_strict_ ()' FAILED: " 929 "Wrong returned value:\n"); 930 } 931 if (0 != check_res) 932 { 933 ret++; 934 fprintf (stderr, 935 "\tRESULT : MHD_str_pct_decode_in_place_strict_ (\"%s\" " 936 "-> \"%s\") -> %u\n", 937 n_prnt (encoded, encoded_len), 938 n_prnt (buf, res_size), 939 (unsigned) res_size); 940 fprintf (stderr, 941 "\tEXPECTED: MHD_str_pct_decode_in_place_strict_ (\"%s\" " 942 "-> (not defined)) -> 0\n", 943 n_prnt (encoded, encoded_len)); 944 } 945 } 946 947 /* check MHD_str_pct_decode_in_place_lenient_() */ 948 if (1) 949 { 950 unsigned int check_res = 0; 951 bool is_broken = false; 952 953 memset (buf, fill_chr, sizeof(buf)); /* Fill buffer with some character */ 954 memcpy (buf, encoded, encoded_len); 955 buf[encoded_len] = 0; 956 res_size = MHD_str_pct_decode_in_place_lenient_ (buf, &is_broken); 957 if (res_size != decoded_size) 958 { 959 check_res = 1; 960 fprintf (stderr, 961 "'MHD_str_pct_decode_in_place_lenient_ ()' FAILED: " 962 "Wrong returned value:\n"); 963 } 964 else 965 { 966 if (0 != buf[res_size]) 967 { 968 check_res = 1; 969 fprintf (stderr, 970 "'MHD_str_pct_decode_in_place_lenient_ ()' FAILED: " 971 "The result is not zero-terminated:\n"); 972 } 973 if (((res_size + 1) < encoded_len) ? 974 (encoded[res_size + 1] != buf[res_size + 1]) : 975 (fill_chr != buf[res_size + 1])) 976 { 977 check_res = 1; 978 fprintf (stderr, 979 "'MHD_str_pct_decode_in_place_lenient_ ()' FAILED: " 980 "A char written outside the buffer:\n"); 981 } 982 if (! is_broken) 983 { 984 check_res = 1; 985 fprintf (stderr, 986 "'MHD_str_pct_decode_in_place_lenient_ ()' FAILED: " 987 "Wrong 'broken_encoding' result:\n"); 988 } 989 if ((res_size == decoded_size) && (0 != decoded_size) && 990 (0 != memcmp (buf, decoded, decoded_size))) 991 { 992 check_res = 1; 993 fprintf (stderr, 994 "'MHD_str_pct_decode_in_place_lenient_ ()' FAILED: " 995 "Wrong output string:\n"); 996 } 997 } 998 if (0 != check_res) 999 { 1000 ret++; 1001 fprintf (stderr, 1002 "\tRESULT : MHD_str_pct_decode_in_place_lenient_ (\"%s\" " 1003 "-> \"%s\", ->%s) -> %u\n", 1004 n_prnt (encoded, encoded_len), 1005 n_prnt (buf, res_size), 1006 is_broken ? "true" : "false", 1007 (unsigned) res_size); 1008 fprintf (stderr, 1009 "\tEXPECTED: MHD_str_pct_decode_in_place_lenient_ (\"%s\" " 1010 "-> \"%s\", ->true) -> %u\n", 1011 n_prnt (encoded, encoded_len), 1012 n_prnt (decoded, decoded_size), 1013 (unsigned) decoded_size); 1014 } 1015 } 1016 } 1017 1018 if (0 != ret) 1019 { 1020 fprintf (stderr, 1021 "The check is at line: %u\n\n", line_num); 1022 } 1023 return ret; 1024 } 1025 1026 1027 #define expect_decoded_bad(e,d) \ 1028 expect_decoded_bad_n(e,MHD_STATICSTR_LEN_(e),\ 1029 d,MHD_STATICSTR_LEN_(d), \ 1030 __LINE__) 1031 1032 static unsigned int 1033 check_decode_bad_str (void) 1034 { 1035 unsigned int r = 0; /**< The number of errors */ 1036 1037 r += expect_decoded_bad ("50%/50%", "50%/50%"); 1038 r += expect_decoded_bad ("This is 100% incorrect.", 1039 "This is 100% incorrect."); 1040 r += expect_decoded_bad ("Some %%", "Some %%"); 1041 r += expect_decoded_bad ("1 %", "1 %"); 1042 r += expect_decoded_bad ("%", "%"); 1043 r += expect_decoded_bad ("%a", "%a"); 1044 r += expect_decoded_bad ("%0", "%0"); 1045 r += expect_decoded_bad ("%0x", "%0x"); 1046 r += expect_decoded_bad ("%FX", "%FX"); 1047 r += expect_decoded_bad ("Valid%20and%2invalid", "Valid and%2invalid"); 1048 1049 return r; 1050 } 1051 1052 1053 int 1054 main (int argc, char *argv[]) 1055 { 1056 unsigned int errcount = 0; 1057 (void) argc; (void) argv; /* Unused. Silent compiler warning. */ 1058 errcount += check_decode_str (); 1059 errcount += check_decode_bin (); 1060 errcount += check_decode_bad_str (); 1061 if (0 == errcount) 1062 printf ("All tests have been passed without errors.\n"); 1063 return errcount == 0 ? 0 : 1; 1064 }