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