aboutsummaryrefslogtreecommitdiff
path: root/test/punycode_test.c
diff options
context:
space:
mode:
authorEnji Cooper <ngie@FreeBSD.org>2025-05-07 21:18:24 +0000
committerEnji Cooper <ngie@FreeBSD.org>2025-05-07 22:37:22 +0000
commit29536654cc41bf41b92dc836c47496dc6fe0b00c (patch)
tree368a3c5b14e610bb5f6b71657f61a41e373eaf97 /test/punycode_test.c
parent1c34280346af8284acdc0eae39496811d37df25d (diff)
Diffstat (limited to 'test/punycode_test.c')
-rw-r--r--test/punycode_test.c108
1 files changed, 91 insertions, 17 deletions
diff --git a/test/punycode_test.c b/test/punycode_test.c
index 9d8171346caa..00a21bb78e5b 100644
--- a/test/punycode_test.c
+++ b/test/punycode_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -12,6 +12,7 @@
#include "crypto/punycode.h"
#include "internal/nelem.h"
+#include "internal/packet.h"
#include "testutil.h"
@@ -19,6 +20,11 @@ static const struct puny_test {
unsigned int raw[50];
const char *encoded;
} puny_cases[] = {
+ { /* Test of 4 byte codepoint using smileyface emoji */
+ { 0x1F600
+ },
+ "e28h"
+ },
/* Test cases from RFC 3492 */
{ /* Arabic (Egyptian) */
{ 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643, 0x0644,
@@ -163,34 +169,53 @@ static int test_punycode(int n)
return 1;
}
+static const struct bad_decode_test {
+ size_t outlen;
+ const char input[20];
+} bad_decode_tests[] = {
+ { 20, "xn--e-*" }, /* bad digit '*' */
+ { 10, "xn--e-999" }, /* loop > enc_len */
+ { 20, "xn--e-999999999" }, /* Too big */
+ { 20, {'x', 'n', '-', '-', (char)0x80, '-' } }, /* Not basic */
+ { 20, "xn--e-Oy65t" }, /* codepoint > 0x10FFFF */
+};
+
+static int test_a2ulabel_bad_decode(int tst)
+{
+ char out[20];
+
+ return TEST_int_eq(ossl_a2ulabel(bad_decode_tests[tst].input, out, bad_decode_tests[tst].outlen), -1);
+}
+
static int test_a2ulabel(void)
{
char out[50];
- size_t outlen;
+ char in[530] = { 0 };
/*
- * Test that no buffer correctly returns the true length.
* The punycode being passed in and parsed is malformed but we're not
* verifying that behaviour here.
*/
- if (!TEST_int_eq(ossl_a2ulabel("xn--a.b.c", NULL, &outlen), 0)
- || !TEST_size_t_eq(outlen, 7)
- || !TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, &outlen), 1))
- return 0;
- /* Test that a short input length returns the true length */
- outlen = 1;
- if (!TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, &outlen), 0)
- || !TEST_size_t_eq(outlen, 7)
- || !TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, &outlen), 1)
- || !TEST_str_eq(out,"\xc2\x80.b.c"))
+ if (!TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, 1), 0)
+ || !TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, 7), 1))
return 0;
/* Test for an off by one on the buffer size works */
- outlen = 6;
- if (!TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, &outlen), 0)
- || !TEST_size_t_eq(outlen, 7)
- || !TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, &outlen), 1)
+ if (!TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, 6), 0)
+ || !TEST_int_eq(ossl_a2ulabel("xn--a.b.c", out, 7), 1)
|| !TEST_str_eq(out,"\xc2\x80.b.c"))
return 0;
+
+ /* Test 4 byte smiley face */
+ if (!TEST_int_eq(ossl_a2ulabel("xn--e28h.com", out, 10), 1))
+ return 0;
+
+ /* Test that we dont overflow the fixed internal buffer of 512 bytes when the starting bytes are copied */
+ strcpy(in, "xn--");
+ memset(in + 4, 'e', 513);
+ memcpy(in + 517, "-3ya", 4);
+ if (!TEST_int_eq(ossl_a2ulabel(in, out, 50), -1))
+ return 0;
+
return 1;
}
@@ -211,10 +236,59 @@ static int test_puny_overrun(void)
return 1;
}
+static int test_dotted_overflow(void)
+{
+ static const char string[] = "a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a";
+ const size_t num_reps = OSSL_NELEM(string) / 2;
+ WPACKET p;
+ BUF_MEM *in;
+ char *out = NULL;
+ size_t i;
+ int res = 0;
+
+ /* Create out input punycode string */
+ if (!TEST_ptr(in = BUF_MEM_new()))
+ return 0;
+ if (!TEST_true(WPACKET_init_len(&p, in, 0))) {
+ BUF_MEM_free(in);
+ return 0;
+ }
+ for (i = 0; i < num_reps; i++) {
+ if (i > 1 && !TEST_true(WPACKET_put_bytes_u8(&p, '.')))
+ goto err;
+ if (!TEST_true(WPACKET_memcpy(&p, "xn--a", sizeof("xn--a") - 1)))
+ goto err;
+ }
+ if (!TEST_true(WPACKET_put_bytes_u8(&p, '\0')))
+ goto err;
+ if (!TEST_ptr(out = OPENSSL_malloc(in->length)))
+ goto err;
+
+ /* Test the decode into an undersized buffer */
+ memset(out, 0x7f, in->length - 1);
+ if (!TEST_int_le(ossl_a2ulabel(in->data, out, num_reps), 0)
+ || !TEST_int_eq(out[num_reps], 0x7f))
+ goto err;
+
+ /* Test the decode works into a full size buffer */
+ if (!TEST_int_gt(ossl_a2ulabel(in->data, out, in->length), 0)
+ || !TEST_size_t_eq(strlen(out), num_reps * 3))
+ goto err;
+
+ res = 1;
+ err:
+ WPACKET_cleanup(&p);
+ BUF_MEM_free(in);
+ OPENSSL_free(out);
+ return res;
+}
+
int setup_tests(void)
{
ADD_ALL_TESTS(test_punycode, OSSL_NELEM(puny_cases));
+ ADD_TEST(test_dotted_overflow);
ADD_TEST(test_a2ulabel);
ADD_TEST(test_puny_overrun);
+ ADD_ALL_TESTS(test_a2ulabel_bad_decode, OSSL_NELEM(bad_decode_tests));
return 1;
}