| @@ -0,0 +1,314 @@ |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| + | * |
| + | * This software is licensed as described in the file COPYING, which |
| + | * you should have received as part of this distribution. The terms |
| + | * are also available at https://curl.se/docs/copyright.html. |
| + | * |
| + | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| + | * copies of the Software, and permit persons to whom the Software is |
| + | * furnished to do so, under the terms of the COPYING file. |
| + | * |
| + | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| + | * KIND, either express or implied. |
| + | * |
| + | * SPDX-License-Identifier: curl |
| + | * |
| + | ***************************************************************************/ |
| + | #include "unitcheck.h" |
| + | #include "urlapi-int.h" |
| + | #include "curlx/dynbuf.h" |
| + | |
| + | static CURLcode test_unit1675(const char *arg) |
| + | { |
| + | (void)arg; |
| + | UNITTEST_BEGIN_SIMPLE |
| + | |
| + | /* Test ipv4_normalize */ |
| + | { |
| + | struct dynbuf host; |
| + | int fails = 0; |
| + | unsigned int i; |
| + | struct ipv4_test { |
| + | const char *in; |
| + | const char *out; |
| + | }; |
| + | const struct ipv4_test tests[] = { |
| + | {"0x.0x.0x.0x", NULL}, /* invalid hex */ |
| + | {"0x.0x.0x", NULL}, /* invalid hex */ |
| + | {"0x.0x", NULL}, /* invalid hex */ |
| + | {"0x", NULL}, /* invalid hex */ |
| + | {"0", "0.0.0.0"}, |
| + | {"00", "0.0.0.0"}, |
| + | {"00000000000", "0.0.0.0"}, |
| + | {"127.0.0.1", "127.0.0.1"}, |
| + | {"0177.0.0.1", "127.0.0.1"}, |
| + | {"00177.0.0.1", "127.0.0.1"}, |
| + | {"0x7f.0.0.1", "127.0.0.1"}, |
| + | {"0x07f.0.0.1", "127.0.0.1"}, |
| + | {"1", "0.0.0.1"}, |
| + | {"010", "0.0.0.8"}, |
| + | {"001", "0.0.0.1"}, |
| + | {"127", "0.0.0.127"}, |
| + | {"127.1", "127.0.0.1"}, |
| + | {"127.0.1", "127.0.0.1"}, |
| + | {"1.16777215", "1.255.255.255"}, |
| + | {"1.16777216", NULL}, /* overflow */ |
| + | {"1.1.65535", "1.1.255.255"}, |
| + | {"1.1.65536", NULL}, /* overflow */ |
| + | {"0x7f000001", "127.0.0.1"}, |
| + | {"0x7F000001", "127.0.0.1"}, |
| + | {"0x7g000001", NULL}, /* bad hex */ |
| + | {"2130706433", "127.0.0.1"}, |
| + | {"017700000001", "127.0.0.1"}, |
| + | {"000000000017700000001", "127.0.0.1"}, |
| + | {"192.168.0.1", "192.168.0.1"}, |
| + | {"0300.0250.0000.0001", "192.168.0.1"}, |
| + | {"0xc0.0xa8.0.1", "192.168.0.1"}, |
| + | {"0xc0a80001", "192.168.0.1"}, |
| + | {"3232235521", "192.168.0.1"}, |
| + | {"4294967294", "255.255.255.254"}, |
| + | {"4294967295", "255.255.255.255"}, |
| + | {"037777777777", "255.255.255.255"}, |
| + | {"0xFFFFFFFF", "255.255.255.255"}, |
| + | {"0xFFFFFfff", "255.255.255.255"}, |
| + | {"1.2.3.4.5", NULL}, /* too many parts */ |
| + | {"256.0.0.1", NULL}, /* overflow */ |
| + | {"1.256.0.1", NULL}, /* overflow */ |
| + | {"1.1.256.1", NULL}, /* overflow */ |
| + | {"1.0.0.256", NULL}, /* overflow */ |
| + | {"0x100.0.0.1", NULL}, /* overflow */ |
| + | {"1.0x100.0.1", NULL}, /* overflow */ |
| + | {"1.1.0x100.1", NULL}, /* overflow */ |
| + | {"1.1.1.0x100", NULL}, /* overflow */ |
| + | {"0400.0.0.1", NULL}, /* overflow */ |
| + | {"4.0400.0.1", NULL}, /* overflow */ |
| + | {"4.4.0400.1", NULL}, /* overflow */ |
| + | {"4.4.4.0400", NULL}, /* overflow */ |
| + | {"4294967296", NULL}, /* overflow */ |
| + | {"040000000000", NULL}, /* overflow */ |
| + | {"0x100000000", NULL}, /* overflow */ |
| + | {"1.2.3.-4", NULL}, /* negative */ |
| + | {"1.2.-3.4", NULL}, /* negative */ |
| + | {"1.-2.3.4", NULL}, /* negative */ |
| + | {"-1.2.3.4", NULL}, /* negative */ |
| + | {"-12", NULL}, /* negative */ |
| + | {"-12.1", NULL}, /* negative */ |
| + | {"-12.2.3", NULL}, /* negative */ |
| + | {" 1.2.3.4", NULL}, /* space */ |
| + | {"1. 2.3.4", NULL}, /* space */ |
| + | {"1.2. 3.4", NULL}, /* space */ |
| + | {"1.2.3. 4", NULL}, /* space */ |
| + | }; |
| + | |
| + | curlx_dyn_init(&host, 256); |
| + | for(i = 0; i < CURL_ARRAYSIZE(tests); i++) { |
| + | int rc; |
| + | curlx_dyn_reset(&host); |
| + | if(curlx_dyn_add(&host, tests[i].in)) { |
| + | return CURLE_OUT_OF_MEMORY; |
| + | } |
| + | rc = ipv4_normalize(&host); |
| + | if(tests[i].out) { |
| + | if((rc != HOST_IPV4) || |
| + | strcmp(curlx_dyn_ptr(&host), tests[i].out)) { |
| + | curl_mfprintf(stderr, "ipv4_normalize('%s') failed: " |
| + | "expected '%s', got '%s'\n", |
| + | tests[i].in, tests[i].out, curlx_dyn_ptr(&host)); |
| + | fails++; |
| + | } |
| + | } |
| + | else { |
| + | if(rc == HOST_IPV4) { |
| + | curl_mfprintf(stderr, "ipv4_normalize('%s') succeeded unexpectedly:" |
| + | " got '%s'\n", |
| + | tests[i].in, curlx_dyn_ptr(&host)); |
| + | fails++; |
| + | } |
| + | } |
| + | } |
| + | curlx_dyn_free(&host); |
| + | abort_if(fails, "ipv4_normalize tests failed"); |
| + | } |
| + | |
| + | /* Test urlencode_str */ |
| + | { |
| + | struct dynbuf out; |
| + | int fails = 0; |
| + | unsigned int i; |
| + | struct urlencode_test { |
| + | const char *in; |
| + | bool relative; |
| + | bool query; |
| + | const char *out; |
| + | }; |
| + | const struct urlencode_test tests[] = { |
| + | {"http://leave\x01/hello\x01world", FALSE, FALSE, |
| + | "http://leave\x01/hello%01world"}, |
| + | {"http://leave/hello\x01world", FALSE, FALSE, |
| + | "http://leave/hello%01world"}, |
| + | {"http://le ave/hello\x01world", FALSE, FALSE, |
| + | "http://le ave/hello%01world"}, |
| + | {"hello\x01world", TRUE, FALSE, "hello%01world"}, |
| + | {"hello\xf0world", TRUE, FALSE, "hello%F0world"}, |
| + | {"hello world", TRUE, FALSE, "hello%20world"}, |
| + | {"hello%20world", TRUE, FALSE, "hello%20world"}, |
| + | {"hello world", TRUE, TRUE, "hello+world"}, |
| + | {"a+b c", TRUE, FALSE, "a+b%20c"}, |
| + | {"a%20b%20c", TRUE, FALSE, "a%20b%20c"}, |
| + | {"a%aab%aac", TRUE, FALSE, "a%AAb%AAc"}, |
| + | {"a%aab%AAc", TRUE, FALSE, "a%AAb%AAc"}, |
| + | {"w%w%x", TRUE, FALSE, "w%w%x"}, |
| + | {"w%wf%xf", TRUE, FALSE, "w%wf%xf"}, |
| + | {"w%fw%fw", TRUE, FALSE, "w%fw%fw"}, |
| + | {"a+b c", TRUE, TRUE, "a+b+c"}, |
| + | {"/foo/bar", TRUE, FALSE, "/foo/bar"}, |
| + | {"/foo/bar", TRUE, TRUE, "/foo/bar"}, |
| + | {"/foo/ bar", TRUE, FALSE, "/foo/%20bar"}, |
| + | {"/foo/ bar", TRUE, TRUE, "/foo/+bar"}, |
| + | {"~-._", TRUE, FALSE, "~-._"}, |
| + | {"~-._", TRUE, TRUE, "~-._"}, |
| + | }; |
| + | |
| + | curlx_dyn_init(&out, 256); |
| + | for(i = 0; i < CURL_ARRAYSIZE(tests); i++) { |
| + | CURLUcode uc; |
| + | curlx_dyn_reset(&out); |
| + | uc = urlencode_str(&out, tests[i].in, strlen(tests[i].in), |
| + | tests[i].relative, tests[i].query); |
| + | if(uc || strcmp(curlx_dyn_ptr(&out), tests[i].out)) { |
| + | curl_mfprintf(stderr, "urlencode_str('%s', query=%d) failed:" |
| + | " expected '%s', got '%s'\n", |
| + | tests[i].in, tests[i].query, tests[i].out, |
| + | uc ? "error" : curlx_dyn_ptr(&out)); |
| + | fails++; |
| + | } |
| + | } |
| + | curlx_dyn_free(&out); |
| + | abort_if(fails, "urlencode_str tests failed"); |
| + | } |
| + | |
| + | /* Test ipv6_parse */ |
| + | { |
| + | struct Curl_URL u; |
| + | int fails = 0; |
| + | unsigned int i; |
| + | struct ipv6_test { |
| + | const char *in; |
| + | const char *out_host; |
| + | const char *out_zone; |
| + | }; |
| + | const struct ipv6_test tests[] = { |
| + | {"[::1]", "[::1]", NULL}, |
| + | {"[fe80::1%eth0]", "[fe80::1]", "eth0"}, |
| + | {"[fe80::1%25eth0]", "[fe80::1]", "eth0"}, |
| + | {"[::1", NULL, NULL}, /* missing bracket */ |
| + | {"[]", NULL, NULL}, /* empty */ |
| + | }; |
| + | |
| + | for(i = 0; i < CURL_ARRAYSIZE(tests); i++) { |
| + | CURLUcode uc; |
| + | char hostname[256]; |
| + | memset(&u, 0, sizeof(u)); |
| + | curlx_strcopy(hostname, sizeof(hostname), |
| + | tests[i].in, strlen(tests[i].in)); |
| + | uc = ipv6_parse(&u, hostname, strlen(hostname)); |
| + | if(tests[i].out_host) { |
| + | if(uc || strcmp(hostname, tests[i].out_host)) { |
| + | curl_mfprintf(stderr, "ipv6_parse('%s') host failed:" |
| + | " expected '%s', got '%s'\n", |
| + | tests[i].in, tests[i].out_host, |
| + | uc ? "error" : hostname); |
| + | fails++; |
| + | } |
| + | if(!uc && tests[i].out_zone) { |
| + | if(!u.zoneid || strcmp(u.zoneid, tests[i].out_zone)) { |
| + | curl_mfprintf(stderr, "ipv6_parse('%s') zone failed:" |
| + | " expected '%s', got '%s'\n", |
| + | tests[i].in, tests[i].out_zone, |
| + | u.zoneid ? u.zoneid : "(null)"); |
| + | fails++; |
| + | } |
| + | } |
| + | } |
| + | else { |
| + | if(!uc) { |
| + | curl_mfprintf(stderr, "ipv6_parse('%s') succeeded unexpectedly\n", |
| + | tests[i].in); |
| + | fails++; |
| + | } |
| + | } |
| + | curlx_free(u.host); |
| + | curlx_free(u.zoneid); |
| + | } |
| + | abort_if(fails, "ipv6_parse tests failed"); |
| + | } |
| + | |
| + | /* Test parse_file */ |
| + | { |
| + | CURLU *u; |
| + | const char *path; |
| + | size_t pathlen; |
| + | int fails = 0; |
| + | unsigned int i; |
| + | struct file_test { |
| + | const char *in; |
| + | const char *out_host; |
| + | const char *out_path; |
| + | bool fine; |
| + | }; |
| + | const struct file_test tests[] = { |
| + | {"file:///etc/hosts", "", "/etc/hosts", TRUE}, |
| + | {"file://localhost/etc/hosts", "", "/etc/hosts", TRUE}, |
| + | {"file://apple/etc/hosts", "", "/etc/hosts", FALSE}, |
| + | #ifdef _WIN32 |
| + | {"file:///c:/windows/system32", "", "c:/windows/system32", TRUE}, |
| + | {"file://localhost/c:/windows/system32", "", |
| + | "c:/windows/system32", TRUE}, |
| + | #endif |
| + | }; |
| + | |
| + | for(i = 0; i < CURL_ARRAYSIZE(tests); i++) { |
| + | CURLUcode uc; |
| + | u = curl_url(); |
| + | if(!u) |
| + | return CURLE_OUT_OF_MEMORY; |
| + | |
| + | uc = parse_file(tests[i].in, strlen(tests[i].in), u, &host, &path, |
| + | &pathlen); |
| + | if(!tests[i].fine && !uc) { |
| + | curl_mfprintf(stderr, "Unexpectedly fine for input '%s'\n", |
| + | tests[i].in); |
| + | fails++; |
| + | } |
| + | else if(tests[i].out_host[0]) { |
| + | /* expecting a hostname output */ |
| + | if(!curlx_dyn_len(&host) || |
| + | strcmp(curlx_dyn_ptr(&host), tests[i].out_host)) |
| + | error = TRUE; |
| + | } |
| + | if(tests[i].fine && |
| + | (uc || |
| + | strncmp(path, tests[i].out_path, pathlen) || |
| + | strlen(tests[i].out_path) != pathlen)) { |
| + | curl_mfprintf(stderr, "parse_file('%s') failed:" |
| + | " expected host '%s', path '%s'; got host '%s'," |
| + | " path '%.*s'\n", |
| + | tests[i].in, tests[i].out_host, tests[i].out_path, |
| + | uc ? "error" : curlx_dyn_ptr(&host), |
| + | (int)pathlen, path); |
| + | fails++; |
| + | } |
| + | curl_url_cleanup(u); |
| + | } |
| + | abort_if(fails, "parse_file tests failed"); |
| + | } |
| + | |
| + | UNITTEST_END_SIMPLE |
| + | } |