summaryrefslogtreecommitdiffstats
path: root/crypto/punycode.c
diff options
context:
space:
mode:
authorPauli <pauli@openssl.org>2022-11-03 11:55:13 +1100
committerPauli <pauli@openssl.org>2022-11-11 08:21:28 +1100
commit709c04b5dd6a24f88459d9e214e85e396b2471fd (patch)
tree139f3ccba836e13657159fbaf94faf8e1af5f693 /crypto/punycode.c
parent7abe06cbb52cf4c214f8eac1b5f9f3c6a38ed9fa (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.c66
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;