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