aboutsummaryrefslogtreecommitdiff
path: root/resolv/tst-ns_name.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2017-04-13 11:56:28 +0200
committerFlorian Weimer <fweimer@redhat.com>2017-04-13 11:56:28 +0200
commitc803cb9b24c6cea15698768e4301e963b98e742c (patch)
tree8b1dfb346ea50ccd7f1da044c65b60bb4b9aee27 /resolv/tst-ns_name.c
parenta7ff1da8239a5f0e1927db9d5310f53cfea97fc2 (diff)
downloadglibc-c803cb9b24c6cea15698768e4301e963b98e742c.zip
glibc-c803cb9b24c6cea15698768e4301e963b98e742c.tar.gz
glibc-c803cb9b24c6cea15698768e4301e963b98e742c.tar.bz2
resolv: Support an exactly sized buffer in ns_name_pack [BZ #21359]
This bug did not affect name resolution because those functions indirectly call ns_name_pack with a buffer which is always larger than the generated query packet, even in the case of the longest-possible domain name.
Diffstat (limited to 'resolv/tst-ns_name.c')
-rw-r--r--resolv/tst-ns_name.c139
1 files changed, 137 insertions, 2 deletions
diff --git a/resolv/tst-ns_name.c b/resolv/tst-ns_name.c
index 66d9a66..65eea4c 100644
--- a/resolv/tst-ns_name.c
+++ b/resolv/tst-ns_name.c
@@ -195,6 +195,7 @@ print_hex (const char *label, struct buffer buffer)
static void
run_test_case (struct test_case *t)
{
+ /* Test ns_name_unpack. */
unsigned char *unpacked = xmalloc (NS_MAXCDNAME);
int consumed = ns_name_unpack
(t->input.data, t->input.data + t->input.length,
@@ -211,16 +212,19 @@ run_test_case (struct test_case *t)
}
if (consumed != -1)
{
- if (memcmp (unpacked, t->unpack_output.data, consumed) != 0)
+ if (memcmp (unpacked, t->unpack_output.data,
+ t->unpack_output.length) != 0)
{
support_record_failure ();
printf ("%s:%zu: error: wrong data from ns_name_unpack\n",
t->path, t->lineno);
print_hex ("expected:", t->unpack_output);
- print_hex ("actual: ", (struct buffer) { unpacked, consumed });
+ print_hex ("actual: ",
+ (struct buffer) { unpacked, t->unpack_output.length });
return;
}
+ /* Test ns_name_ntop. */
char *text = xmalloc (NS_MAXDNAME);
int ret = ns_name_ntop (unpacked, text, NS_MAXDNAME);
if (ret != t->ntop_result)
@@ -243,6 +247,137 @@ run_test_case (struct test_case *t)
printf (" actual: \"%s\"\n", text);
return;
}
+
+ /* Test ns_name_pton. Unpacking does not check the
+ NS_MAXCDNAME limit, but packing does, so we need to
+ adjust the expected result. */
+ int expected;
+ if (t->unpack_output.length > NS_MAXCDNAME)
+ expected = -1;
+ else if (strcmp (text, ".") == 0)
+ /* The root domain is fully qualified. */
+ expected = 1;
+ else
+ /* The domain name is never fully qualified. */
+ expected = 0;
+ unsigned char *repacked = xmalloc (NS_MAXCDNAME);
+ ret = ns_name_pton (text, repacked, NS_MAXCDNAME);
+ if (ret != expected)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong result from ns_name_pton\n"
+ " expected: %d\n"
+ " actual: %d\n",
+ t->path, t->lineno, expected, ret);
+ return;
+ }
+ if (ret >= 0
+ && memcmp (repacked, unpacked, t->unpack_output.length) != 0)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong data from ns_name_pton\n",
+ t->path, t->lineno);
+ print_hex ("expected:", t->unpack_output);
+ print_hex ("actual: ",
+ (struct buffer) { repacked, t->unpack_output.length });
+ return;
+ }
+
+ /* Test ns_name_compress, no compression case. */
+ if (t->unpack_output.length > NS_MAXCDNAME)
+ expected = -1;
+ else
+ expected = t->unpack_output.length;
+ memset (repacked, '$', NS_MAXCDNAME);
+ {
+ enum { ptr_count = 5 };
+ const unsigned char *dnptrs[ptr_count] = { repacked, };
+ ret = ns_name_compress (text, repacked, NS_MAXCDNAME,
+ dnptrs, dnptrs + ptr_count);
+ if (ret != expected)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong result from ns_name_compress\n"
+ " expected: %d\n"
+ " actual: %d\n",
+ t->path, t->lineno, expected, ret);
+ return;
+ }
+ if (ret < 0)
+ {
+ TEST_VERIFY (dnptrs[0] == repacked);
+ TEST_VERIFY (dnptrs[1] == NULL);
+ }
+ else
+ {
+ if (memcmp (repacked, unpacked, t->unpack_output.length) != 0)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong data from ns_name_compress\n",
+ t->path, t->lineno);
+ print_hex ("expected:", t->unpack_output);
+ print_hex ("actual: ", (struct buffer) { repacked, ret });
+ return;
+ }
+ TEST_VERIFY (dnptrs[0] == repacked);
+ if (unpacked[0] == '\0')
+ /* The root domain is not a compression target. */
+ TEST_VERIFY (dnptrs[1] == NULL);
+ else
+ {
+ TEST_VERIFY (dnptrs[1] == repacked);
+ TEST_VERIFY (dnptrs[2] == NULL);
+ }
+ }
+ }
+
+ /* Test ns_name_compress, full compression case. Skip this
+ test for invalid names and the root domain. */
+ if (expected >= 0 && unpacked[0] != '\0')
+ {
+ /* The destination buffer needs additional room for the
+ offset, the initial name, and the compression
+ reference. */
+ enum { name_offset = 259 };
+ size_t target_offset = name_offset + t->unpack_output.length;
+ size_t repacked_size = target_offset + 2;
+ repacked = xrealloc (repacked, repacked_size);
+ memset (repacked, '@', repacked_size);
+ memcpy (repacked + name_offset,
+ t->unpack_output.data, t->unpack_output.length);
+ enum { ptr_count = 5 };
+ const unsigned char *dnptrs[ptr_count]
+ = { repacked, repacked + name_offset, };
+ ret = ns_name_compress
+ (text, repacked + target_offset, NS_MAXCDNAME,
+ dnptrs, dnptrs + ptr_count);
+ if (ret != 2)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong result from ns_name_compress"
+ " (2)\n"
+ " expected: 2\n"
+ " actual: %d\n",
+ t->path, t->lineno, ret);
+ return;
+ }
+ if (memcmp (repacked + target_offset, "\xc1\x03", 2) != 0)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong data from ns_name_compress"
+ " (2)\n"
+ " expected: C103\n",
+ t->path, t->lineno);
+ print_hex ("actual: ",
+ (struct buffer) { repacked + target_offset, ret });
+ return;
+ }
+ TEST_VERIFY (dnptrs[0] == repacked);
+ TEST_VERIFY (dnptrs[1] == repacked + name_offset);
+ TEST_VERIFY (dnptrs[2] == NULL);
+ }
+
+ free (repacked);
}
free (text);
}