diff options
author | Florian Weimer <fweimer@redhat.com> | 2017-06-21 13:09:08 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2017-06-21 13:09:08 +0200 |
commit | 60149b28590be28051f99d0a343d7fbe002f2a8c (patch) | |
tree | 3eb9b2d7016cedd4178a193fe6c0146ec847f7ee /resolv/tst-inet_pton.c | |
parent | 965d5c391c86eb3a812ce308411c32754f12a9d2 (diff) | |
download | glibc-60149b28590be28051f99d0a343d7fbe002f2a8c.tar.gz glibc-60149b28590be28051f99d0a343d7fbe002f2a8c.tar.xz glibc-60149b28590be28051f99d0a343d7fbe002f2a8c.zip |
__inet_pton_length: Implement new internal helper function
Diffstat (limited to 'resolv/tst-inet_pton.c')
-rw-r--r-- | resolv/tst-inet_pton.c | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/resolv/tst-inet_pton.c b/resolv/tst-inet_pton.c new file mode 100644 index 0000000000..7fffb24cdf --- /dev/null +++ b/resolv/tst-inet_pton.c @@ -0,0 +1,549 @@ +/* Test inet_pton functions. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <arpa/inet.h> +#include <resolv/resolv-internal.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <support/check.h> +#include <support/xunistd.h> +#include <sys/mman.h> +#include <sys/param.h> +#include <unistd.h> + +/* Memory region created by next_to_fault_allocate. */ +struct next_to_fault +{ + /* The user data. */ + char *buffer; + size_t length; + + /* The entire allocated region. */ + void *region_start; + size_t region_size; +}; + +/* Allocate a buffer of SIZE bytes just before a page which is mapped + with PROT_NONE (so that overrunning the buffer will cause a + fault). */ +static struct next_to_fault +next_to_fault_allocate (size_t size) +{ + long page_size = sysconf (_SC_PAGE_SIZE); + TEST_VERIFY_EXIT (page_size > 0); + struct next_to_fault result; + result.region_size = roundup (size, page_size) + page_size; + TEST_VERIFY_EXIT (size + page_size > size); + TEST_VERIFY_EXIT (result.region_size > size); + result.region_start + = xmmap (NULL, result.region_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1); + /* Unmap the page after the allocation. */ + xmprotect (result.region_start + (result.region_size - page_size), + page_size, PROT_NONE); + /* Align the allocation within the region so that it ends just + before the PROT_NONE page. */ + result.buffer = result.region_start + result.region_size - page_size - size; + result.length = size; + return result; +} + +/* Deallocate the memory region allocated by + next_to_fault_allocate. */ +static void +next_to_fault_free (struct next_to_fault *ntf) +{ + xmunmap (ntf->region_start, ntf->region_size); + *ntf = (struct next_to_fault) { NULL, }; +} + +struct test_case +{ + /* The input data. */ + const char *input; + + /* True if AF_INET parses successfully. */ + bool ipv4_ok; + + /* True if AF_INET6 parses successfully. */ + bool ipv6_ok; + + /* Expected result for AF_INET. */ + unsigned char ipv4_expected[4]; + + /* Expected result for AF_INET6. */ + unsigned char ipv6_expected[16]; +}; + +static void +check_result (const char *what, const struct test_case *t, int family, + void *result_buffer, int inet_ret) +{ + TEST_VERIFY_EXIT (inet_ret >= -1); + TEST_VERIFY_EXIT (inet_ret <= 1); + + int ok; + const unsigned char *expected; + size_t result_size; + switch (family) + { + case AF_INET: + ok = t->ipv4_ok; + expected = t->ipv4_expected; + result_size = 4; + break; + case AF_INET6: + ok = t->ipv6_ok; + expected = t->ipv6_expected; + result_size = 16; + break; + default: + FAIL_EXIT1 ("invalid address family %d", family); + } + + if (inet_ret != ok) + { + support_record_failure (); + printf ("error: %s return value mismatch for [[%s]], family %d\n" + " expected: %d\n" + " actual: %d\n", + what, t->input, family, ok, inet_ret); + return; + } + if (memcmp (result_buffer, expected, result_size) != 0) + { + support_record_failure (); + printf ("error: %s result mismatch for [[%s]], family %d\n", + what, t->input, family); + } +} + +static void +run_one_test (const struct test_case *t) +{ + size_t test_len = strlen (t->input); + + struct next_to_fault ntf_out4 = next_to_fault_allocate (4); + struct next_to_fault ntf_out6 = next_to_fault_allocate (16); + + /* inet_pton requires NUL termination. */ + { + struct next_to_fault ntf_in = next_to_fault_allocate (test_len + 1); + memcpy (ntf_in.buffer, t->input, test_len + 1); + memset (ntf_out4.buffer, 0, 4); + check_result ("inet_pton", t, AF_INET, ntf_out4.buffer, + inet_pton (AF_INET, ntf_in.buffer, ntf_out4.buffer)); + memset (ntf_out6.buffer, 0, 16); + check_result ("inet_pton", t, AF_INET6, ntf_out6.buffer, + inet_pton (AF_INET6, ntf_in.buffer, ntf_out6.buffer)); + next_to_fault_free (&ntf_in); + } + + /* __inet_pton_length does not require NUL termination. */ + { + struct next_to_fault ntf_in = next_to_fault_allocate (test_len); + memcpy (ntf_in.buffer, t->input, test_len); + memset (ntf_out4.buffer, 0, 4); + check_result ("__inet_pton_length", t, AF_INET, ntf_out4.buffer, + __inet_pton_length (AF_INET, ntf_in.buffer, ntf_in.length, + ntf_out4.buffer)); + memset (ntf_out6.buffer, 0, 16); + check_result ("__inet_pton_length", t, AF_INET6, ntf_out6.buffer, + __inet_pton_length (AF_INET6, ntf_in.buffer, ntf_in.length, + ntf_out6.buffer)); + next_to_fault_free (&ntf_in); + } + + next_to_fault_free (&ntf_out4); + next_to_fault_free (&ntf_out6); +} + +/* The test cases were manually crafted and the set enhanced with + American Fuzzy Lop. */ +const struct test_case test_cases[] = + { + {.input = ".:", }, + {.input = "0.0.0.0", + .ipv4_ok = true, + .ipv4_expected = {0, 0, 0, 0}, + }, + {.input = "0.:", }, + {.input = "00", }, + {.input = "0000000", }, + {.input = "00000000000000000", }, + {.input = "092.", }, + {.input = "10.0.301.2", }, + {.input = "127.0.0.1", + .ipv4_ok = true, + .ipv4_expected = {127, 0, 0, 1}, + }, + {.input = "19..", }, + {.input = "192.0.2.-1", }, + {.input = "192.0.2.01", }, + {.input = "192.0.2.1.", }, + {.input = "192.0.2.1192.", }, + {.input = "192.0.2.192.\377..", }, + {.input = "192.0.2.256", }, + {.input = "192.0.2.27", + .ipv4_ok = true, + .ipv4_expected = {192, 0, 2, 27}, + }, + {.input = "192.0.201.", }, + {.input = "192.0.261.", }, + {.input = "192.0.2\256", }, + {.input = "192.0.\262.", }, + {.input = "192.062.", }, + {.input = "192.092.\256", }, + {.input = "192.0\2562.", }, + {.input = "192.192.0.2661\031", }, + {.input = "192.192.00n2.1.", }, + {.input = "192.192.2.190.", }, + {.input = "192.255.255.2555", }, + {.input = "192.92.219\023.", }, + {.input = "192.\260.2.", }, + {.input = "1:1::1:1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1 + }, + }, + {.input = "2", }, + {.input = "2.", }, + {.input = "2001:db8:00001::f", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x1, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf + }, + }, + {.input = "2001:db8:10000::f", }, + {.input = "2001:db8:1234:5678:abcd:ef01:2345:67", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x12, 0x34, 0x56, 0x78, + 0xab, 0xcd, 0xef, 0x1, 0x23, 0x45, 0x0, 0x67 + }, + }, + {.input = "2001:db8:1234:5678:abcd:ef01:2345:6789:1", }, + {.input = "2001:db8:1234:5678:abcd:ef01:2345::6789", }, + {.input = "2001:db8::0", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + }, + }, + {.input = "2001:db8::00", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + }, + }, + {.input = "2001:db8::1", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 + }, + }, + {.input = "2001:db8::10", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10 + }, + }, + {.input = "2001:db8::19", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19 + }, + }, + {.input = "2001:db8::1::\012", }, + {.input = "2001:db8::1::2\012", }, + {.input = "2001:db8::2", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 + }, + }, + {.input = "2001:db8::3", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3 + }, + }, + {.input = "2001:db8::4", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4 + }, + }, + {.input = "2001:db8::5", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5 + }, + }, + {.input = "2001:db8::6", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6 + }, + }, + {.input = "2001:db8::7", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7 + }, + }, + {.input = "2001:db8::8", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8 + }, + }, + {.input = "2001:db8::9", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9 + }, + }, + {.input = "2001:db8::A", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa + }, + }, + {.input = "2001:db8::B", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb + }, + }, + {.input = "2001:db8::C", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc + }, + }, + {.input = "2001:db8::D", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd + }, + }, + {.input = "2001:db8::E", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe + }, + }, + {.input = "2001:db8::F", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf + }, + }, + {.input = "2001:db8::a", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa + }, + }, + {.input = "2001:db8::b", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb + }, + }, + {.input = "2001:db8::c", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc + }, + }, + {.input = "2001:db8::d", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd + }, + }, + {.input = "2001:db8::e", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe + }, + }, + {.input = "2001:db8::f", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf + }, + }, + {.input = "2001:db8::ff", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff + }, + }, + {.input = "2001:db8::ffff:2\012", }, + {.input = "22", }, + {.input = "2222@", }, + {.input = "255.255.255.255", + .ipv4_ok = true, + .ipv4_expected = {255, 255, 255, 255}, + }, + {.input = "255.255.255.255\001", }, + {.input = "255.255.255.25555", }, + {.input = "2:", }, + {.input = "2:a:8:EEEE::EEEE:F:EEE8:EEEE\034*:", }, + {.input = "2:ff:1:1:7:ff:1:1:7.", }, + {.input = "2f:0000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000000" + "0G01", + }, + {.input = "429495", }, + {.input = "5::5::", }, + {.input = "6.6.", }, + {.input = "992.", }, + {.input = "::", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + }, + }, + {.input = "::00001", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 + }, + }, + {.input = "::1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 + }, + }, + {.input = "::10000", }, + {.input = "::1:1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1 + }, + }, + {.input = "::ff:1:1:7.0.0.1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0x0, 0x1, 0x0, 0x1, 0x7, 0x0, 0x0, 0x1 + }, + }, + {.input = "::ff:1:1:7:ff:1:1:7.", }, + {.input = "::ff:1:1:7ff:1:8:7.0.0.1", }, + {.input = "::ff:1:1:7ff:1:8f:1:1:71", }, + {.input = "::ffff:02fff:127.0.S1", }, + {.input = "::ffff:127.0.0.1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x1 + }, + }, + {.input = "::ffff:1:7.0.0.1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0x0, 0x1, 0x7, 0x0, 0x0, 0x1 + }, + }, + {.input = ":\272", }, + {.input = "A:f:ff:1:1:D:ff:1:1::7.", }, + {.input = "AAAAA.", }, + {.input = "D:::", }, + {.input = "DF8F", }, + {.input = "F::", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + }, + }, + {.input = "F:A:8:EEEE:8:EEEE\034*:", }, + {.input = "F:a:8:EEEE:8:EEEE\034*:", }, + {.input = "F:ff:100:7ff:1:8:7.0.10.1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0xf, 0x0, 0xff, 0x1, 0x0, 0x7, 0xff, + 0x0, 0x1, 0x0, 0x8, 0x7, 0x0, 0xa, 0x1 + }, + }, + {.input = "d92.", }, + {.input = "ff:00000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000001", + }, + {.input = "fff2:2::ff2:2:f7", + .ipv6_ok = true, + .ipv6_expected = { + 0xff, 0xf2, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xf2, 0x0, 0x2, 0x0, 0xf7 + }, + }, + {.input = "ffff:ff:ff:fff:ff:ff:ff:", }, + {.input = "\272:", }, + {NULL} + }; + +static int +do_test (void) +{ + for (size_t i = 0; test_cases[i].input != NULL; ++i) + run_one_test (test_cases + i); + return 0; +} + +#include <support/test-driver.c> |