/* Allow a single terminating '.' used rarely to indicate domains
* are FQDNs rather than relative. */
- last_label = (char *)smartlist_get(components, smartlist_len(components) - 1);
+ last_label = (char *)smartlist_get(components,
+ smartlist_len(components) - 1);
has_trailing_dot = (last_label[0] == '\0');
if (has_trailing_dot) {
smartlist_pop_last(components);
break;
}
- if (c_sl_idx == c_sl_len - 1) {
+ if (c_sl_idx == c_sl_len - 1) { // TLD validation.
+ int is_punycode = (strlen(c) > 4 &&
+ (c[0] == 'X' || c[0] == 'x') &&
+ (c[1] == 'N' || c[1] == 'n') &&
+ c[2] == '-' && c[3] == '-');
+
+ if (is_punycode)
+ c += 4;
+
do {
- result = TOR_ISALPHA(*c);
+ result = is_punycode ? TOR_ISALNUM(*c) : TOR_ISALPHA(*c);
c++;
} while (result && *c);
- } else {
+ } else { // Regular hostname label validation.
do {
result = (TOR_ISALNUM(*c) || (*c == '-') || (*c == '_'));
c++;
tt_assert(!string_is_valid_hostname("luck.y13"));
tt_assert(!string_is_valid_hostname("luck.y13."));
+ // We allow punycode TLDs. For examples, see
+ // http://data.iana.org/TLD/tlds-alpha-by-domain.txt
+ tt_assert(string_is_valid_hostname("example.xn--l1acc"));
+
done:
return;
}