Restrict Latin Small Letter Thorn (U+00FE) to Icelandic domains

This character (þ) can be confused with both b and p when used in a domain
name. IDN spoof checker doesn't have a good way of flagging a character as
confusable with multiple characters, so it can't catch spoofs containing
this character. As a practical fix, this CL restricts this character to
domains under Iceland's ccTLD (.is). With this change, a domain name containing
"þ" with a non-.is TLD will be displayed in punycode in the UI.

This change affects less than 10 real world domains with limited popularity.

Bug: 798892, 843352, 904327, 1017707
Change-Id: Ib07190dcde406bf62ce4413688a4fb4859a51030
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1879992
Commit-Queue: Mustafa Emre Acer <meacer@chromium.org>
Reviewed-by: Christopher Thompson <cthomp@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709309}
 bool IDNToUnicodeOneComponent(const base::char16* comp,
                               size_t comp_len,
                              base::StringPiece top_level_domain,
                               bool enable_spoof_checks,
                               base::string16* out,
                               bool* has_idn_component) {
  DCHECK(out);
  DCHECK(has_idn_component);
  *has_idn_component = false;
  if (comp_len == 0)
    return false;

  static const base::char16 kIdnPrefix[] = {'x', 'n', '-', '-'};
  if (comp_len <= base::size(kIdnPrefix) ||
      memcmp(comp, kIdnPrefix, sizeof(kIdnPrefix)) != 0) {
    out->append(comp, comp_len);
    return false;
  }

  UIDNA* uidna = g_uidna.Get().value;
  DCHECK(uidna != nullptr);
  size_t original_length = out->length();
  int32_t output_length = 64;
  UIDNAInfo info = UIDNA_INFO_INITIALIZER;
  UErrorCode status;
  do {
    out->resize(original_length + output_length);
    status = U_ZERO_ERROR;
    output_length = uidna_labelToUnicode(
        uidna, comp, static_cast<int32_t>(comp_len), &(*out)[original_length],
        output_length, &info, &status);
  } while ((status == U_BUFFER_OVERFLOW_ERROR && info.errors == 0));

  if (U_SUCCESS(status) && info.errors == 0) {
    *has_idn_component = true;
    out->resize(original_length + output_length);
    if (!enable_spoof_checks) {
      return true;
    }
     if (IsIDNComponentSafe(
             base::StringPiece16(out->data() + original_length,
                                 base::checked_cast<size_t>(output_length)),
            top_level_domain)) {
       return true;
     }
   }

  out->resize(original_length);
  out->append(comp, comp_len);
  return false;
}

 bool IDNToUnicodeOneComponent(const base::char16* comp,
                               size_t comp_len,
                              bool is_tld_ascii,
                               bool enable_spoof_checks,
                               base::string16* out,
                               bool* has_idn_component) {
  DCHECK(out);
  DCHECK(has_idn_component);
  *has_idn_component = false;
  if (comp_len == 0)
    return false;

  static const base::char16 kIdnPrefix[] = {'x', 'n', '-', '-'};
  if (comp_len <= base::size(kIdnPrefix) ||
      memcmp(comp, kIdnPrefix, sizeof(kIdnPrefix)) != 0) {
    out->append(comp, comp_len);
    return false;
  }

  UIDNA* uidna = g_uidna.Get().value;
  DCHECK(uidna != nullptr);
  size_t original_length = out->length();
  int32_t output_length = 64;
  UIDNAInfo info = UIDNA_INFO_INITIALIZER;
  UErrorCode status;
  do {
    out->resize(original_length + output_length);
    status = U_ZERO_ERROR;
    output_length = uidna_labelToUnicode(
        uidna, comp, static_cast<int32_t>(comp_len), &(*out)[original_length],
        output_length, &info, &status);
  } while ((status == U_BUFFER_OVERFLOW_ERROR && info.errors == 0));

  if (U_SUCCESS(status) && info.errors == 0) {
    *has_idn_component = true;
    out->resize(original_length + output_length);
    if (!enable_spoof_checks) {
      return true;
    }
     if (IsIDNComponentSafe(
             base::StringPiece16(out->data() + original_length,
                                 base::checked_cast<size_t>(output_length)),
            is_tld_ascii)) {
       return true;
     }
   }

  out->resize(original_length);
  out->append(comp, comp_len);
  return false;
}
