diff options
author | Enji Cooper <ngie@FreeBSD.org> | 2025-05-07 21:18:24 +0000 |
---|---|---|
committer | Enji Cooper <ngie@FreeBSD.org> | 2025-05-07 22:37:22 +0000 |
commit | 29536654cc41bf41b92dc836c47496dc6fe0b00c (patch) | |
tree | 368a3c5b14e610bb5f6b71657f61a41e373eaf97 /test/punycode_test.c | |
parent | 1c34280346af8284acdc0eae39496811d37df25d (diff) |
Diffstat (limited to 'test/punycode_test.c')
-rw-r--r-- | test/punycode_test.c | 108 |
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; } |