Remove memory allocations from _utf8_to_utf32()

Reported-by: https://github.com/daurnimator
This commit is contained in:
Tim Rühsen 2016-09-22 11:03:45 +02:00
parent b2fcafcfdd
commit 9e1ca81be4
1 changed files with 12 additions and 24 deletions

View File

@ -524,56 +524,44 @@ static enum punycode_status punycode_encode(
return punycode_success; return punycode_success;
} }
static ssize_t _utf8_to_utf32(const char *in, const size_t inlen, punycode_uint *out, size_t outlen) static ssize_t _utf8_to_utf32(const char *in, size_t inlen, punycode_uint *out, size_t outlen)
{ {
size_t n = 0; size_t n = 0;
unsigned char *s; const unsigned char *s = (void *)in;
void *m; const unsigned char *e = (void *)(in + inlen);
if (!outlen) if (!outlen)
return -1; return -1;
outlen--; outlen--;
if (inlen < 1024) { while (n < outlen) {
s = alloca(inlen + 1); size_t inleft = e - s;
m = NULL;
} else
s = m = malloc(inlen + 1);
if (!s) if (inleft >= 1 && (*s & 0x80) == 0) { /* 0xxxxxxx ASCII char */
return -1;
memcpy(s, in, inlen);
s[inlen] = 0;
while (*s && n < outlen) {
if ((*s & 0x80) == 0) { /* 0xxxxxxx ASCII char */
out[n++] = *s; out[n++] = *s;
s++; s++;
} else if ((*s & 0xE0) == 0xC0) /* 110xxxxx 10xxxxxx */ { } else if (inleft >= 2 && (*s & 0xE0) == 0xC0) /* 110xxxxx 10xxxxxx */ {
if ((s[1] & 0xC0) != 0x80) if ((s[1] & 0xC0) != 0x80)
return -1; return -1;
out[n++] = ((*s & 0x1F) << 6) | (s[1] & 0x3F); out[n++] = ((*s & 0x1F) << 6) | (s[1] & 0x3F);
s += 2; s += 2;
} else if ((*s & 0xF0) == 0xE0) /* 1110xxxx 10xxxxxx 10xxxxxx */ { } else if (inleft >= 3 && (*s & 0xF0) == 0xE0) /* 1110xxxx 10xxxxxx 10xxxxxx */ {
if ((s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80) if ((s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80)
return -1; return -1;
out[n++] = ((*s & 0x0F) << 12) | ((s[1] & 0x3F) << 6) | (s[2] & 0x3F); out[n++] = ((*s & 0x0F) << 12) | ((s[1] & 0x3F) << 6) | (s[2] & 0x3F);
s += 3; s += 3;
} else if ((*s & 0xF8) == 0xF0) /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ { } else if (inleft >= 4 && (*s & 0xF8) == 0xF0) /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ {
if ((s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80 || (s[3] & 0xC0) != 0x80) if ((s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80 || (s[3] & 0xC0) != 0x80)
return -1; return -1;
out[n++] = ((*s & 0x07) << 18) | ((s[1] & 0x3F) << 12) | ((s[1] & 0x3F) << 6) | (s[2] & 0x3F); out[n++] = ((*s & 0x07) << 18) | ((s[1] & 0x3F) << 12) | ((s[1] & 0x3F) << 6) | (s[2] & 0x3F);
s += 4; s += 4;
} else { } else if (!inleft) {
free(m); break;
} else
return -1; return -1;
}
} }
free(m);
return n; return n;
} }