diff options
author | Pauli <pauli@openssl.org> | 2022-11-03 11:55:13 +1100 |
---|---|---|
committer | Pauli <pauli@openssl.org> | 2022-11-11 08:21:28 +1100 |
commit | 709c04b5dd6a24f88459d9e214e85e396b2471fd (patch) | |
tree | 139f3ccba836e13657159fbaf94faf8e1af5f693 /crypto/punycode.c | |
parent | 7abe06cbb52cf4c214f8eac1b5f9f3c6a38ed9fa (diff) |
punycode: update to use WPACKET instead of using custom range checking
Add test for `.' overflows, remove the output size argument from
ossl_a2ulabel() since it was never used and greatly complicated the code.
Convert ossl_a2ulabel() to use WPACKET for building the output string.
Update the documentation to match the new definition of ossl_a2ulabel().
x509: let punycode handle the '\0' string termination. Saves a memset(3)
and some size fiddling. Also update to deal with the modified parameters.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/19591)
(cherry picked from commit 905ba924398f474e647de70345b4ae4089fedba7)
Diffstat (limited to 'crypto/punycode.c')
-rw-r--r-- | crypto/punycode.c | 66 |
1 files changed, 33 insertions, 33 deletions
diff --git a/crypto/punycode.c b/crypto/punycode.c index b9b4e3d785..29e440a6c1 100644 --- a/crypto/punycode.c +++ b/crypto/punycode.c @@ -12,6 +12,8 @@ #include <stdio.h> #include <openssl/e_os2.h> #include "crypto/punycode.h" +#include "internal/cryptlib.h" +#include "internal/packet.h" /* for WPACKET */ static const unsigned int base = 36; static const unsigned int tmin = 1; @@ -239,12 +241,12 @@ static int codepoint2utf8(unsigned char *out, unsigned long utf) /*- * Return values: - * 1 - ok, *outlen contains valid buf length - * 0 - ok but buf was too short, *outlen contains valid buf length - * -1 - bad string passed + * 1 - ok + * 0 - ok but buf was too short + * -1 - bad string passed or other error */ -int ossl_a2ulabel(const char *in, char *out, size_t *outlen) +int ossl_a2ulabel(const char *in, char *out, size_t outlen) { /*- * Domain name has some parts consisting of ASCII chars joined with dot. @@ -252,63 +254,61 @@ int ossl_a2ulabel(const char *in, char *out, size_t *outlen) * If it does not start with xn--, it becomes U-label as is. * Otherwise we try to decode it. */ - char *outptr = out; const char *inptr = in; - size_t size = 0, maxsize; int result = 1; - unsigned int i, j; + unsigned int i; unsigned int buf[LABEL_BUF_SIZE]; /* It's a hostname */ + WPACKET pkt; - if (out == NULL) { - result = 0; - maxsize = 0; - } else { - maxsize = *outlen; - } + /* Internal API, so should not fail */ + if (!ossl_assert(out != NULL)) + return -1; -#define PUSHC(c) \ - do \ - if (size++ < maxsize) \ - *outptr++ = c; \ - else \ - result = 0; \ - while (0) + if (!WPACKET_init_static_len(&pkt, (unsigned char *)out, outlen, 0)) + return -1; while (1) { char *tmpptr = strchr(inptr, '.'); size_t delta = tmpptr != NULL ? (size_t)(tmpptr - inptr) : strlen(inptr); if (strncmp(inptr, "xn--", 4) != 0) { - for (i = 0; i < delta + 1; i++) - PUSHC(inptr[i]); + if (!WPACKET_memcpy(&pkt, inptr, delta)) + result = 0; } else { unsigned int bufsize = LABEL_BUF_SIZE; - if (ossl_punycode_decode(inptr + 4, delta - 4, buf, &bufsize) <= 0) - return -1; + if (ossl_punycode_decode(inptr + 4, delta - 4, buf, &bufsize) <= 0) { + result = -1; + goto end; + } for (i = 0; i < bufsize; i++) { unsigned char seed[6]; size_t utfsize = codepoint2utf8(seed, buf[i]); - if (utfsize == 0) - return -1; + if (utfsize == 0) { + result = -1; + goto end; + } - for (j = 0; j < utfsize; j++) - PUSHC(seed[j]); + if (!WPACKET_memcpy(&pkt, seed, utfsize)) + result = 0; } - - PUSHC(tmpptr != NULL ? '.' : '\0'); } if (tmpptr == NULL) break; + if (!WPACKET_put_bytes_u8(&pkt, '.')) + result = 0; + inptr = tmpptr + 1; } -#undef PUSHC - *outlen = size; + if (!WPACKET_put_bytes_u8(&pkt, '\0')) + result = 0; + end: + WPACKET_cleanup(&pkt); return result; } @@ -325,7 +325,7 @@ int ossl_a2ucompare(const char *a, const char *u) char a_ulabel[LABEL_BUF_SIZE + 1]; size_t a_size = sizeof(a_ulabel); - if (ossl_a2ulabel(a, a_ulabel, &a_size) <= 0) + if (ossl_a2ulabel(a, a_ulabel, a_size) <= 0) return -1; return strcmp(a_ulabel, u) != 0; |