Bug 1233610 - IDN service should return NS_ERROR_MALFORMED_URI instead of NS_ERROR_FAILURE r?mcmanus draft
authorValentin Gosu <valentin.gosu@gmail.com>
Thu, 07 Jan 2016 14:31:22 +0100
changeset 319586 2b202bb72ec21fc4fa6c440fe2d3d0133bee4300
parent 318937 29258f59e5456a1a518ccce6b473b50c1173477e
child 512623 b98050f0705937a617bb58f71ba02be392c96c25
push id9064
push uservalentin.gosu@gmail.com
push dateThu, 07 Jan 2016 13:33:14 +0000
reviewersmcmanus
bugs1233610
milestone46.0a1
Bug 1233610 - IDN service should return NS_ERROR_MALFORMED_URI instead of NS_ERROR_FAILURE r?mcmanus
netwerk/dns/nsIDNService.cpp
--- a/netwerk/dns/nsIDNService.cpp
+++ b/netwerk/dns/nsIDNService.cpp
@@ -168,24 +168,28 @@ nsIDNService::IDNA2008ToUnicode(const ns
   int32_t inLen = inputStr.Length();
   int32_t outMaxLen = inLen - kACEPrefixLen + 1;
   UChar outputBuffer[kMaxDNSNodeLen + 1];
 
   int32_t outLen = uidna_labelToUnicode(mIDNA, (const UChar*)inputStr.get(),
                                         inLen, outputBuffer, outMaxLen,
                                         &info, &errorCode);
   if (info.errors != 0) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_MALFORMED_URI;
   }
 
   if (U_SUCCESS(errorCode)) {
     ICUUtils::AssignUCharArrayToString(outputBuffer, outLen, output);
   }
 
-  return ICUUtils::UErrorToNsResult(errorCode);
+  nsresult rv = ICUUtils::UErrorToNsResult(errorCode);
+  if (rv == NS_ERROR_FAILURE) {
+    rv = NS_ERROR_MALFORMED_URI;
+  }
+  return rv;
 }
 
 nsresult
 nsIDNService::IDNA2008StringPrep(const nsAString& input,
                                  nsAString& output,
                                  stringPrepFlag flag)
 {
   UIDNAInfo info = UIDNA_INFO_INITIALIZER;
@@ -193,30 +197,33 @@ nsIDNService::IDNA2008StringPrep(const n
   int32_t inLen = input.Length();
   int32_t outMaxLen = kMaxDNSNodeLen + 1;
   UChar outputBuffer[kMaxDNSNodeLen + 1];
 
   int32_t outLen =
     uidna_labelToUnicode(mIDNA, (const UChar*)PromiseFlatString(input).get(),
                          inLen, outputBuffer, outMaxLen, &info, &errorCode);
   nsresult rv = ICUUtils::UErrorToNsResult(errorCode);
+  if (rv == NS_ERROR_FAILURE) {
+    rv = NS_ERROR_MALFORMED_URI;
+  }
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Output the result of nameToUnicode even if there were errors
   ICUUtils::AssignUCharArrayToString(outputBuffer, outLen, output);
 
   if (flag == eStringPrepIgnoreErrors) {
     return NS_OK;
   }
 
   if (info.errors != 0) {
     if (flag == eStringPrepForDNS) {
       output.Truncate();
     }
-    rv = NS_ERROR_FAILURE;
+    rv = NS_ERROR_MALFORMED_URI;
   }
 
   return rv;
 }
 #endif
 
 NS_IMETHODIMP nsIDNService::ConvertUTF8toACE(const nsACString & input, nsACString & ace)
 {
@@ -467,17 +474,17 @@ static nsresult utf16ToUcs4(const nsAStr
       out[i] = SURROGATE_TO_UCS4(curChar, *start);
       ++start;
     }
     else
       out[i] = curChar;
 
     i++;
     if (i >= outBufLen)
-      return NS_ERROR_FAILURE;
+      return NS_ERROR_MALFORMED_URI;
   }
   out[i] = (uint32_t)'\0';
   *outLen = i;
   return NS_OK;
 }
 
 #ifndef IDNA2008
 static void ucs4toUtf16(const uint32_t *in, nsAString& out)
@@ -510,17 +517,17 @@ static nsresult punycode(const nsAString
   enum punycode_status status = punycode_encode(ucs4Len,
                                                 ucs4Buf,
                                                 nullptr,
                                                 &encodedLength,
                                                 encodedBuf);
 
   if (punycode_success != status ||
       encodedLength >= kEncodedBufSize)
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_MALFORMED_URI;
 
   encodedBuf[encodedLength] = '\0';
   out.Assign(nsDependentCString(kACEPrefix) + nsDependentCString(encodedBuf));
 
   return rv;
 }
 
 // RFC 3454
@@ -559,54 +566,54 @@ nsresult nsIDNService::stringPrep(const 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // map
   idn_result_t idn_err;
 
   uint32_t namePrepBuf[kMaxDNSNodeLen * 3];   // map up to three characters
   idn_err = idn_nameprep_map(mNamePrepHandle, (const uint32_t *) ucs4Buf,
 		                     (uint32_t *) namePrepBuf, kMaxDNSNodeLen * 3);
-  NS_ENSURE_TRUE(idn_err == idn_success, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(idn_err == idn_success, NS_ERROR_MALFORMED_URI);
 
   nsAutoString namePrepStr;
   ucs4toUtf16(namePrepBuf, namePrepStr);
   if (namePrepStr.Length() >= kMaxDNSNodeLen)
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_MALFORMED_URI;
 
   // normalize
   nsAutoString normlizedStr;
   rv = mNormalizer->NormalizeUnicodeNFKC(namePrepStr, normlizedStr);
   if (normlizedStr.Length() >= kMaxDNSNodeLen)
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_MALFORMED_URI;
 
   // set the result string
   out.Assign(normlizedStr);
 
   if (flag == eStringPrepIgnoreErrors) {
     return NS_OK;
   }
 
   // prohibit
   const uint32_t *found = nullptr;
   idn_err = idn_nameprep_isprohibited(mNamePrepHandle,
                                       (const uint32_t *) ucs4Buf, &found);
   if (idn_err != idn_success || found) {
-    rv = NS_ERROR_FAILURE;
+    rv = NS_ERROR_MALFORMED_URI;
   } else {
     // check bidi
     idn_err = idn_nameprep_isvalidbidi(mNamePrepHandle,
                                        (const uint32_t *) ucs4Buf, &found);
     if (idn_err != idn_success || found) {
-      rv = NS_ERROR_FAILURE;
+      rv = NS_ERROR_MALFORMED_URI;
     } else  if (flag == eStringPrepForUI) {
       // check unassigned code points
       idn_err = idn_nameprep_isunassigned(mNamePrepHandle,
                                           (const uint32_t *) ucs4Buf, &found);
       if (idn_err != idn_success || found) {
-        rv = NS_ERROR_FAILURE;
+        rv = NS_ERROR_MALFORMED_URI;
       }
     }
   }
 
   if (flag == eStringPrepForDNS && NS_FAILED(rv)) {
     out.Truncate();
   }
 
@@ -618,17 +625,17 @@ nsresult nsIDNService::stringPrepAndACE(
                                         stringPrepFlag flag)
 {
   nsresult rv = NS_OK;
 
   out.Truncate();
 
   if (in.Length() > kMaxDNSNodeLen) {
     NS_WARNING("IDN node too large");
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_MALFORMED_URI;
   }
 
   if (IsASCII(in)) {
     LossyCopyUTF16toASCII(in, out);
     return NS_OK;
   }
 
   nsAutoString strPrep;
@@ -652,17 +659,17 @@ nsresult nsIDNService::stringPrepAndACE(
   // of a DNS node per RFC 1034.
   // This test isn't necessary in the code paths above where the input
   // is ASCII (since the output will be the same length as the input) or
   // where we convert to UTF-8 (since the output is only used for
   // display in the UI and not passed to DNS and can legitimately be
   // longer than the limit).
   if (out.Length() > kMaxDNSNodeLen) {
     NS_WARNING("IDN node too large");
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_MALFORMED_URI;
   }
 
   return rv;
 }
 
 // RFC 3490
 // 1) Whenever dots are used as label separators, the following characters
 //    MUST be recognized as dots: U+002E (full stop), U+3002 (ideographic full
@@ -714,17 +721,17 @@ nsresult nsIDNService::decodeACE(const n
 
   enum punycode_status status = punycode_decode(in.Length() - kACEPrefixLen,
                                                 PromiseFlatCString(in).get() + kACEPrefixLen,
                                                 &output_length,
                                                 output,
                                                 nullptr);
   if (status != punycode_success) {
     delete [] output;
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_MALFORMED_URI;
   }
 
   // UCS4 -> UTF8
   output[output_length] = 0;
   ucs4toUtf16(output, utf16);
   delete [] output;
 #endif
   if (flag != eStringPrepForUI || isLabelSafe(utf16)) {
@@ -736,17 +743,17 @@ nsresult nsIDNService::decodeACE(const n
 
   // Validation: encode back to ACE and compare the strings
   nsAutoCString ace;
   nsresult rv = UTF8toACE(out, ace, flag);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (flag == eStringPrepForDNS &&
       !ace.Equals(in, nsCaseInsensitiveCStringComparator())) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_MALFORMED_URI;
   }
 
   return NS_OK;
 }
 
 bool nsIDNService::isInWhitelist(const nsACString &host)
 {
   if (mIDNUseWhitelist && mIDNWhitelistPrefBranch) {