Bug 1329237 - Avoid non-smart string IDL types in nsISiteSecurityService.idl. r=keeler draft
authorCykesiopka <cykesiopka.bmo@gmail.com>
Sat, 14 Jan 2017 13:10:06 +0800
changeset 460969 a24101d876d1120bd3b6c757fc48a2b76a8b489f
parent 460968 6b716be52be01188cd7c5f82538c55f83d9dad27
child 542176 7066cc512d60bc77779a43f8b99b66d77f4e6c84
push id41531
push usercykesiopka.bmo@gmail.com
push dateSat, 14 Jan 2017 05:11:53 +0000
reviewerskeeler
bugs1329237
milestone53.0a1
Bug 1329237 - Avoid non-smart string IDL types in nsISiteSecurityService.idl. r=keeler Smart string IDL types give us nsA[C]String in C++ code, which is safer than raw char strings. MozReview-Commit-ID: KJ3Z4qK9i61
netwerk/protocol/http/nsHttpChannel.cpp
security/manager/ssl/ContentSignatureVerifier.cpp
security/manager/ssl/ContentSignatureVerifier.h
security/manager/ssl/PublicKeyPinningService.cpp
security/manager/ssl/SSLServerCertVerification.cpp
security/manager/ssl/nsISiteSecurityService.idl
security/manager/ssl/nsSecurityHeaderParser.cpp
security/manager/ssl/nsSecurityHeaderParser.h
security/manager/ssl/nsSiteSecurityService.cpp
security/manager/ssl/nsSiteSecurityService.h
security/manager/ssl/tests/gtest/STSParserTest.cpp
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -1576,17 +1576,17 @@ nsHttpChannel::ProcessSingleSecurityHead
     nsAutoCString securityHeader;
     nsresult rv = mResponseHead->GetHeader(atom, securityHeader);
     if (NS_SUCCEEDED(rv)) {
         nsISiteSecurityService* sss = gHttpHandler->GetSSService();
         NS_ENSURE_TRUE(sss, NS_ERROR_OUT_OF_MEMORY);
         // Process header will now discard the headers itself if the channel
         // wasn't secure (whereas before it had to be checked manually)
         uint32_t failureResult;
-        rv = sss->ProcessHeader(aType, mURI, securityHeader.get(), aSSLStatus,
+        rv = sss->ProcessHeader(aType, mURI, securityHeader, aSSLStatus,
                                 aFlags, nullptr, nullptr, &failureResult);
         if (NS_FAILED(rv)) {
             nsAutoString consoleErrorCategory;
             nsAutoString consoleErrorTag;
             switch (aType) {
                 case nsISiteSecurityService::HEADER_HSTS:
                     GetSTSConsoleErrorTag(failureResult, consoleErrorTag);
                     consoleErrorCategory = NS_LITERAL_STRING("Invalid HSTS Headers");
--- a/security/manager/ssl/ContentSignatureVerifier.cpp
+++ b/security/manager/ssl/ContentSignatureVerifier.cpp
@@ -13,16 +13,17 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/Casting.h"
 #include "mozilla/Unused.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsISupportsPriority.h"
 #include "nsIURI.h"
 #include "nsNSSComponent.h"
+#include "nsPromiseFlatString.h"
 #include "nsSecurityHeaderParser.h"
 #include "nsStreamUtils.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsXPCOMStrings.h"
 #include "nssb64.h"
 #include "pkix/pkix.h"
 #include "pkix/pkixtypes.h"
 #include "secerr.h"
@@ -428,17 +429,18 @@ nsresult
 ContentSignatureVerifier::ParseContentSignatureHeader(
   const nsACString& aContentSignatureHeader)
 {
   MOZ_ASSERT(NS_IsMainThread());
   // We only support p384 ecdsa according to spec
   NS_NAMED_LITERAL_CSTRING(signature_var, "p384ecdsa");
   NS_NAMED_LITERAL_CSTRING(certChainURL_var, "x5u");
 
-  nsSecurityHeaderParser parser(aContentSignatureHeader.BeginReading());
+  const nsCString& flatHeader = PromiseFlatCString(aContentSignatureHeader);
+  nsSecurityHeaderParser parser(flatHeader);
   nsresult rv = parser.Parse();
   if (NS_FAILED(rv)) {
     CSVerifier_LOG(("CSVerifier: could not parse ContentSignature header\n"));
     return NS_ERROR_FAILURE;
   }
   LinkedList<nsSecurityHeaderDirective>* directives = parser.GetDirectives();
 
   for (nsSecurityHeaderDirective* directive = directives->getFirst();
--- a/security/manager/ssl/ContentSignatureVerifier.h
+++ b/security/manager/ssl/ContentSignatureVerifier.h
@@ -8,16 +8,17 @@
 #ifndef ContentSignatureVerifier_h
 #define ContentSignatureVerifier_h
 
 #include "cert.h"
 #include "CSTrustDomain.h"
 #include "nsIContentSignatureVerifier.h"
 #include "nsIStreamListener.h"
 #include "nsNSSShutDown.h"
+#include "nsString.h"
 #include "ScopedNSSTypes.h"
 
 // 45a5fe2f-c350-4b86-962d-02d5aaaa955a
 #define NS_CONTENTSIGNATUREVERIFIER_CID \
   { 0x45a5fe2f, 0xc350, 0x4b86, \
     { 0x96, 0x2d, 0x02, 0xd5, 0xaa, 0xaa, 0x95, 0x5a } }
 #define NS_CONTENTSIGNATUREVERIFIER_CONTRACTID \
     "@mozilla.org/security/contentsignatureverifier;1"
--- a/security/manager/ssl/PublicKeyPinningService.cpp
+++ b/security/manager/ssl/PublicKeyPinningService.cpp
@@ -4,16 +4,17 @@
 
 #include "PublicKeyPinningService.h"
 
 #include "RootCertificateTelemetryUtils.h"
 #include "mozilla/Base64.h"
 #include "mozilla/Casting.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Telemetry.h"
+#include "nsDependentString.h"
 #include "nsISiteSecurityService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsSiteSecurityService.h"
 #include "nssb64.h"
 #include "pkix/pkixtypes.h"
 #include "seccomon.h"
 #include "sechash.h"
 
@@ -176,18 +177,18 @@ FindPinningInformation(const char* hostn
   while (!foundEntry && (evalPart = strchr(evalHost, '.'))) {
     MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
            ("pkpin: Querying pinsets for host: '%s'\n", evalHost));
     // Attempt dynamic pins first
     nsresult rv;
     bool found;
     bool includeSubdomains;
     nsTArray<nsCString> pinArray;
-    rv = sssService->GetKeyPinsForHostname(evalHost, time, pinArray,
-                                           &includeSubdomains, &found);
+    rv = sssService->GetKeyPinsForHostname(nsDependentCString(evalHost), time,
+                                           pinArray, &includeSubdomains, &found);
     if (NS_FAILED(rv)) {
       return rv;
     }
     if (found && (evalHost == hostname || includeSubdomains)) {
       MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug,
              ("pkpin: Found dyn match for host: '%s'\n", evalHost));
       dynamicFingerprints = pinArray;
       return NS_OK;
--- a/security/manager/ssl/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/SSLServerCertVerification.cpp
@@ -507,28 +507,28 @@ CertErrorRunnable::CheckCertOverrides()
   if (!sss) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
            ("[%p][%p] couldn't get nsISiteSecurityService to check for HSTS/HPKP\n",
             mFdForLogging, this));
     return new SSLServerCertVerificationResult(mInfoObject,
                                                mDefaultErrorCodeToReport);
   }
   nsresult nsrv = sss->IsSecureHost(nsISiteSecurityService::HEADER_HSTS,
-                                    mInfoObject->GetHostNameRaw(),
+                                    mInfoObject->GetHostName(),
                                     mProviderFlags,
                                     nullptr,
                                     &strictTransportSecurityEnabled);
   if (NS_FAILED(nsrv)) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
            ("[%p][%p] checking for HSTS failed\n", mFdForLogging, this));
     return new SSLServerCertVerificationResult(mInfoObject,
                                                mDefaultErrorCodeToReport);
   }
   nsrv = sss->IsSecureHost(nsISiteSecurityService::HEADER_HPKP,
-                           mInfoObject->GetHostNameRaw(),
+                           mInfoObject->GetHostName(),
                            mProviderFlags,
                            nullptr,
                            &hasPinningInformation);
   if (NS_FAILED(nsrv)) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
            ("[%p][%p] checking for HPKP failed\n", mFdForLogging, this));
     return new SSLServerCertVerificationResult(mInfoObject,
                                                mDefaultErrorCodeToReport);
--- a/security/manager/ssl/nsISiteSecurityService.idl
+++ b/security/manager/ssl/nsISiteSecurityService.idl
@@ -55,45 +55,45 @@ interface nsISiteSecurityService : nsISu
      * upgraded to HTTPS.
      * The format of the HPKP header is defined by the HPKP specification:
      * https://tools.ietf.org/html/rfc7469
      * and allows a host to specify a subset of trusted anchors to be used
      * in future HTTPS connections.
      *
      * @param aType the type of security header in question.
      * @param aSourceURI the URI of the resource with the HTTP header.
-     * @param aSSLStatus the SSLStatus of the current channel
      * @param aHeader the HTTP response header specifying security data.
+     * @param aSSLStatus the SSLStatus of the current channel.
      * @param aFlags  options for this request as defined in nsISocketProvider:
      *                  NO_PERMANENT_STORAGE
      * @param aMaxAge the parsed max-age directive of the header.
      * @param aIncludeSubdomains the parsed includeSubdomains directive.
      * @param aFailureResult a more specific failure result if NS_ERROR_FAILURE
                              was returned.
      * @return NS_OK            if it succeeds
      *         NS_ERROR_FAILURE if it can't be parsed
      *         NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
      *                          if there are unrecognized tokens in the header.
      */
     void processHeader(in uint32_t aType,
                        in nsIURI aSourceURI,
-                       in string aHeader,
+                       in ACString aHeader,
                        in nsISSLStatus aSSLStatus,
                        in uint32_t aFlags,
                        [optional] out unsigned long long aMaxAge,
                        [optional] out boolean aIncludeSubdomains,
                        [optional] out uint32_t aFailureResult);
 
     /**
      * Same as processHeader but without checking for the security properties
      * of the connection. Use ONLY for testing.
      */
     void unsafeProcessHeader(in uint32_t aType,
                              in nsIURI aSourceURI,
-                             in string aHeader,
+                             in ACString aHeader,
                              in uint32_t aFlags,
                              [optional] out unsigned long long aMaxAge,
                              [optional] out boolean aIncludeSubdomains,
                              [optional] out uint32_t aFailureResult);
 
     /**
      * Given a header type, removes state relating to that header of a host,
      * including the includeSubdomains state that would affect subdomains.
@@ -114,17 +114,17 @@ interface nsISiteSecurityService : nsISu
      * @param aType the type of security state in question.
      * @param aHost the hostname (punycode) to query for state.
      * @param aFlags  options for this request as defined in nsISocketProvider:
      *                  NO_PERMANENT_STORAGE
      * @param aCached true if we have cached information regarding whether or not
      *                  the host is HSTS, false otherwise.
      */
     boolean isSecureHost(in uint32_t aType,
-                         in string aHost,
+                         in ACString aHost,
                          in uint32_t aFlags,
                          [optional] out boolean aCached);
 
     /**
      * Checks whether or not the URI's hostname has a given security state set.
      * For example, for HSTS:
      * The URI is an HSTS URI if either the host has the HSTS state set, or one
      * of its super-domains has the HSTS "includeSubdomains" flag set.
@@ -154,24 +154,24 @@ interface nsISiteSecurityService : nsISu
     void clearPreloads();
 
     /**
      * Returns an array of sha256-hashed key pins for the given domain, if any.
      * If these pins also apply to subdomains of the given domain,
      * aIncludeSubdomains will be true. Pins returned are only for non-built-in
      * pin entries.
      *
-     * @param aHostname the hosname (punycode) to be queried about
-     * @param the time at which the pins should be valid. This is in
+     * @param aHostname the hostname (punycode) to be queried about
+     * @param evalTime the time at which the pins should be valid. This is in
               mozilla::pkix::Time which uses internally seconds since 0 AD.
      * @param aPinArray the set of sha256-hashed key pins for the given domain
      * @param aIncludeSubdomains true if the pins apply to subdomains of the
      *        given domain
      */
-    [noscript] boolean getKeyPinsForHostname(in string aHostname,
+    [noscript] boolean getKeyPinsForHostname(in ACString aHostname,
                                              in mozillaPkixTime evalTime,
                                              out nsCStringTArrayRef aPinArray,
                                              out boolean aIncludeSubdomains);
 
     /**
      * Set public-key pins for a host. The resulting pins will be permanent
      * and visible from private and non-private contexts. These pins replace
      * any already set by this mechanism or those built-in to Gecko.
@@ -179,32 +179,32 @@ interface nsISiteSecurityService : nsISu
      * @param aHost the hostname (punycode) that pins will apply to
      * @param aIncludeSubdomains whether these pins also apply to subdomains
      * @param aExpires the time this pin should expire (millis since epoch)
      * @param aPinCount number of keys being pinnned
      * @param aSha256Pins array of hashed key fingerprints (SHA-256, base64)
      * @param aIsPreload are these key pins for a preload entry? (false by
      *        default)
      */
-     boolean setKeyPins(in string aHost, in boolean aIncludeSubdomains,
+     boolean setKeyPins(in ACString aHost, in boolean aIncludeSubdomains,
                         in int64_t aExpires, in unsigned long aPinCount,
                         [array, size_is(aPinCount)] in string aSha256Pins,
                         [optional] in boolean aIsPreload);
 
     /**
      * Set an HSTS preload entry for a host. The resulting entries will be
      * permanent and visible from private and non-private contexts. These
      * entries replace any already set by this mechanism or those built-in to
      * Gecko.
      *
      * @param aHost the hostname (punycode) that the entry applies to
      * @param aIncludeSubdomains whether this entry also applies to subdomains
      * @param aExpires the time this entry should expire (millis since epoch)
      */
-     boolean setHSTSPreload(in string aHost, in boolean aIncludesSubdomains,
+     boolean setHSTSPreload(in ACString aHost, in boolean aIncludesSubdomains,
                             in int64_t aExpires);
 
     /**
      * Mark a host as declining to provide a given security state so that features
      * such as HSTS priming will not flood a server with requests.
      *
      * @param aURI the nsIURI that this applies to
      * @param aMaxAge lifetime (in seconds) of this negative cache
--- a/security/manager/ssl/nsSecurityHeaderParser.cpp
+++ b/security/manager/ssl/nsSecurityHeaderParser.cpp
@@ -45,18 +45,18 @@ bool
 IsQuotedPairSymbol(signed char chr) {
   return (chr >= 0);
 }
 
 static mozilla::LazyLogModule sSHParserLog("nsSecurityHeaderParser");
 
 #define SHPARSERLOG(args) MOZ_LOG(sSHParserLog, mozilla::LogLevel::Debug, args)
 
-nsSecurityHeaderParser::nsSecurityHeaderParser(const char *aHeader)
-  : mCursor(aHeader)
+nsSecurityHeaderParser::nsSecurityHeaderParser(const nsCString& aHeader)
+  : mCursor(aHeader.get())
   , mError(false)
 {
 }
 
 nsSecurityHeaderParser::~nsSecurityHeaderParser() {
   nsSecurityHeaderDirective *directive;
   while ((directive = mDirectives.popFirst())) {
     delete directive;
--- a/security/manager/ssl/nsSecurityHeaderParser.h
+++ b/security/manager/ssl/nsSecurityHeaderParser.h
@@ -1,18 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef nsSecurityHeaderParser_h__
-#define nsSecurityHeaderParser_h__
+#ifndef nsSecurityHeaderParser_h
+#define nsSecurityHeaderParser_h
 
-#include "nsString.h"
 #include "mozilla/LinkedList.h"
 #include "nsCOMPtr.h"
+#include "nsString.h"
 
 // Utility class for handing back parsed directives and (optional) values
 class nsSecurityHeaderDirective : public mozilla::LinkedListElement<nsSecurityHeaderDirective> {
 public:
   nsCString mName;
   nsCString mValue;
 };
 
@@ -31,17 +31,19 @@ public:
 //
 //   token          = <token, defined in [RFC2616], Section 2.2>
 //   quoted-string  = <quoted-string, defined in [RFC2616], Section 2.2>/
 //
 // For further reference, see [RFC6797], Section 6.1
 
 class nsSecurityHeaderParser {
 public:
-  explicit nsSecurityHeaderParser(const char *aHeader);
+  // The input to this class must be null-terminated, and must have a lifetime
+  // greater than or equal to the lifetime of the created nsSecurityHeaderParser.
+  explicit nsSecurityHeaderParser(const nsCString& aHeader);
   ~nsSecurityHeaderParser();
 
   // Only call Parse once.
   nsresult Parse();
   // The caller does not take ownership of the memory returned here.
   mozilla::LinkedList<nsSecurityHeaderDirective> *GetDirectives();
 
 private:
@@ -66,9 +68,9 @@ private:
   mozilla::LinkedList<nsSecurityHeaderDirective> mDirectives;
   const char *mCursor;
   nsSecurityHeaderDirective *mDirective;
 
   nsCString mOutput;
   bool mError;
 };
 
-#endif /* nsSecurityHeaderParser_h__ */
+#endif // nsSecurityHeaderParser_h
--- a/security/manager/ssl/nsSiteSecurityService.cpp
+++ b/security/manager/ssl/nsSiteSecurityService.cpp
@@ -16,21 +16,20 @@
 #include "mozilla/Preferences.h"
 #include "nsCRTGlue.h"
 #include "nsISSLStatus.h"
 #include "nsISocketProvider.h"
 #include "nsIURI.h"
 #include "nsIX509Cert.h"
 #include "nsNSSComponent.h"
 #include "nsNetUtil.h"
+#include "nsPromiseFlatString.h"
 #include "nsSecurityHeaderParser.h"
-#include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
-#include "pkix/pkixtypes.h"
 #include "plstr.h"
 #include "prnetdb.h"
 #include "prprf.h"
 
 // A note about the preload list:
 // When a site specifically disables HSTS by sending a header with
 // 'max-age: 0', we keep a "knockout" value that means "we have no information
 // regarding the HSTS state of this host" (any ancestor of "this host" can still
@@ -431,71 +430,76 @@ nsSiteSecurityService::RemoveState(uint3
                                    uint32_t aFlags)
 {
   nsAutoCString hostname;
   GetHost(aURI, hostname);
   return RemoveStateInternal(aType, hostname, aFlags, false);
 }
 
 static bool
-HostIsIPAddress(const char *hostname)
+HostIsIPAddress(const nsCString& hostname)
 {
   PRNetAddr hostAddr;
-  return (PR_StringToNetAddr(hostname, &hostAddr) == PR_SUCCESS);
+  PRErrorCode prv = PR_StringToNetAddr(hostname.get(), &hostAddr);
+  return (prv == PR_SUCCESS);
 }
 
 NS_IMETHODIMP
 nsSiteSecurityService::ProcessHeader(uint32_t aType,
                                      nsIURI* aSourceURI,
-                                     const char* aHeader,
+                                     const nsACString& aHeader,
                                      nsISSLStatus* aSSLStatus,
                                      uint32_t aFlags,
                                      uint64_t* aMaxAge,
                                      bool* aIncludeSubdomains,
                                      uint32_t* aFailureResult)
 {
-   // Child processes are not allowed direct access to this.
-   if (!XRE_IsParentProcess()) {
-     MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::ProcessHeader");
-   }
+  // Child processes are not allowed direct access to this.
+  if (!XRE_IsParentProcess()) {
+    MOZ_CRASH("Child process: no direct access to "
+              "nsISiteSecurityService::ProcessHeader");
+  }
 
   if (aFailureResult) {
     *aFailureResult = nsISiteSecurityService::ERROR_UNKNOWN;
   }
   NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS ||
                  aType == nsISiteSecurityService::HEADER_HPKP,
                  NS_ERROR_NOT_IMPLEMENTED);
 
   NS_ENSURE_ARG(aSSLStatus);
-  return ProcessHeaderInternal(aType, aSourceURI, aHeader, aSSLStatus, aFlags,
-                               aMaxAge, aIncludeSubdomains, aFailureResult);
+  return ProcessHeaderInternal(aType, aSourceURI, PromiseFlatCString(aHeader),
+                               aSSLStatus, aFlags, aMaxAge, aIncludeSubdomains,
+                               aFailureResult);
 }
 
 NS_IMETHODIMP
 nsSiteSecurityService::UnsafeProcessHeader(uint32_t aType,
                                            nsIURI* aSourceURI,
-                                           const char* aHeader,
+                                           const nsACString& aHeader,
                                            uint32_t aFlags,
                                            uint64_t* aMaxAge,
                                            bool* aIncludeSubdomains,
                                            uint32_t* aFailureResult)
 {
-   // Child processes are not allowed direct access to this.
-   if (!XRE_IsParentProcess()) {
-     MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::UnsafeProcessHeader");
-   }
+  // Child processes are not allowed direct access to this.
+  if (!XRE_IsParentProcess()) {
+    MOZ_CRASH("Child process: no direct access to "
+              "nsISiteSecurityService::UnsafeProcessHeader");
+  }
 
-  return ProcessHeaderInternal(aType, aSourceURI, aHeader, nullptr, aFlags,
-                               aMaxAge, aIncludeSubdomains, aFailureResult);
+  return ProcessHeaderInternal(aType, aSourceURI, PromiseFlatCString(aHeader),
+                               nullptr, aFlags, aMaxAge, aIncludeSubdomains,
+                               aFailureResult);
 }
 
 nsresult
 nsSiteSecurityService::ProcessHeaderInternal(uint32_t aType,
                                              nsIURI* aSourceURI,
-                                             const char* aHeader,
+                                             const nsCString& aHeader,
                                              nsISSLStatus* aSSLStatus,
                                              uint32_t aFlags,
                                              uint64_t* aMaxAge,
                                              bool* aIncludeSubdomains,
                                              uint32_t* aFailureResult)
 {
   if (aFailureResult) {
     *aFailureResult = nsISiteSecurityService::ERROR_UNKNOWN;
@@ -535,17 +539,17 @@ nsSiteSecurityService::ProcessHeaderInte
        }
       return NS_ERROR_FAILURE;
     }
   }
 
   nsAutoCString host;
   nsresult rv = GetHost(aSourceURI, host);
   NS_ENSURE_SUCCESS(rv, rv);
-  if (HostIsIPAddress(host.get())) {
+  if (HostIsIPAddress(host)) {
     /* Don't process headers if a site is accessed by IP address. */
     return NS_OK;
   }
 
   switch (aType) {
     case nsISiteSecurityService::HEADER_HSTS:
       rv = ProcessSTSHeader(aSourceURI, aHeader, aFlags, aMaxAge,
                             aIncludeSubdomains, aFailureResult);
@@ -557,17 +561,17 @@ nsSiteSecurityService::ProcessHeaderInte
     default:
       MOZ_CRASH("unexpected header type");
   }
   return rv;
 }
 
 static uint32_t
 ParseSSSHeaders(uint32_t aType,
-                const char* aHeader,
+                const nsCString& aHeader,
                 bool& foundIncludeSubdomains,
                 bool& foundMaxAge,
                 bool& foundUnrecognizedDirective,
                 uint64_t& maxAge,
                 nsTArray<nsCString>& sha256keys)
 {
   // Strict transport security and Public Key Pinning have very similar
   // Header formats.
@@ -698,27 +702,27 @@ ParseSSSHeaders(uint32_t aType,
       foundUnrecognizedDirective = true;
     }
   }
   return nsISiteSecurityService::Success;
 }
 
 nsresult
 nsSiteSecurityService::ProcessPKPHeader(nsIURI* aSourceURI,
-                                        const char* aHeader,
+                                        const nsCString& aHeader,
                                         nsISSLStatus* aSSLStatus,
                                         uint32_t aFlags,
                                         uint64_t* aMaxAge,
                                         bool* aIncludeSubdomains,
                                         uint32_t* aFailureResult)
 {
   if (aFailureResult) {
     *aFailureResult = nsISiteSecurityService::ERROR_UNKNOWN;
   }
-  SSSLOG(("SSS: processing HPKP header '%s'", aHeader));
+  SSSLOG(("SSS: processing HPKP header '%s'", aHeader.get()));
   NS_ENSURE_ARG(aSSLStatus);
 
   const uint32_t aType = nsISiteSecurityService::HEADER_HPKP;
   bool foundMaxAge = false;
   bool foundIncludeSubdomains = false;
   bool foundUnrecognizedDirective = false;
   uint64_t maxAge = 0;
   nsTArray<nsCString> sha256keys;
@@ -872,26 +876,26 @@ nsSiteSecurityService::ProcessPKPHeader(
 
   return foundUnrecognizedDirective
            ? NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
            : NS_OK;
 }
 
 nsresult
 nsSiteSecurityService::ProcessSTSHeader(nsIURI* aSourceURI,
-                                        const char* aHeader,
+                                        const nsCString& aHeader,
                                         uint32_t aFlags,
                                         uint64_t* aMaxAge,
                                         bool* aIncludeSubdomains,
                                         uint32_t* aFailureResult)
 {
   if (aFailureResult) {
     *aFailureResult = nsISiteSecurityService::ERROR_UNKNOWN;
   }
-  SSSLOG(("SSS: processing HSTS header '%s'", aHeader));
+  SSSLOG(("SSS: processing HSTS header '%s'", aHeader.get()));
 
   const uint32_t aType = nsISiteSecurityService::HEADER_HSTS;
   bool foundMaxAge = false;
   bool foundIncludeSubdomains = false;
   bool foundUnrecognizedDirective = false;
   uint64_t maxAge = 0;
   nsTArray<nsCString> unusedSHA256keys; // Required for sane internal interface
 
@@ -960,22 +964,22 @@ nsSiteSecurityService::IsSecureURI(uint3
   NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS ||
                  aType == nsISiteSecurityService::HEADER_HPKP,
                  NS_ERROR_NOT_IMPLEMENTED);
 
   nsAutoCString hostname;
   nsresult rv = GetHost(aURI, hostname);
   NS_ENSURE_SUCCESS(rv, rv);
   /* An IP address never qualifies as a secure URI. */
-  if (HostIsIPAddress(hostname.get())) {
+  if (HostIsIPAddress(hostname)) {
     *aResult = false;
     return NS_OK;
   }
 
-  return IsSecureHost(aType, hostname.get(), aFlags, aCached, aResult);
+  return IsSecureHost(aType, hostname, aFlags, aCached, aResult);
 }
 
 int STSPreloadCompare(const void *key, const void *entry)
 {
   const char *keyStr = (const char *)key;
   const nsSTSPreload *preloadEntry = (const nsSTSPreload *)entry;
   return strcmp(keyStr, &kSTSHostTable[preloadEntry->mHostIndex]);
 }
@@ -1104,61 +1108,64 @@ nsSiteSecurityService::HostHasHSTSEntry(
     }
     return true;
   }
 
   return false;
 }
 
 NS_IMETHODIMP
-nsSiteSecurityService::IsSecureHost(uint32_t aType, const char* aHost,
+nsSiteSecurityService::IsSecureHost(uint32_t aType, const nsACString& aHost,
                                     uint32_t aFlags, bool* aCached,
                                     bool* aResult)
 {
-   // Child processes are not allowed direct access to this.
-   if (!XRE_IsParentProcess() && aType != nsISiteSecurityService::HEADER_HSTS) {
-     MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::IsSecureHost for non-HSTS entries");
-   }
+  // Child processes are not allowed direct access to this.
+  if (!XRE_IsParentProcess() && aType != nsISiteSecurityService::HEADER_HSTS) {
+    MOZ_CRASH("Child process: no direct access to "
+              "nsISiteSecurityService::IsSecureHost for non-HSTS entries");
+  }
 
-  NS_ENSURE_ARG(aHost);
   NS_ENSURE_ARG(aResult);
 
   // Only HSTS and HPKP are supported at the moment.
   NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS ||
                  aType == nsISiteSecurityService::HEADER_HPKP,
                  NS_ERROR_NOT_IMPLEMENTED);
 
   // set default in case if we can't find any STS information
   *aResult = false;
   if (aCached) {
     *aCached = false;
   }
 
   /* An IP address never qualifies as a secure URI. */
-  if (HostIsIPAddress(aHost)) {
+  const nsCString& flatHost = PromiseFlatCString(aHost);
+  if (HostIsIPAddress(flatHost)) {
     return NS_OK;
   }
 
   if (aType == nsISiteSecurityService::HEADER_HPKP) {
     RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
     if (!certVerifier) {
       return NS_ERROR_FAILURE;
     }
     if (certVerifier->mPinningMode ==
         CertVerifier::PinningMode::pinningDisabled) {
       return NS_OK;
     }
     bool enforceTestMode = certVerifier->mPinningMode ==
                            CertVerifier::PinningMode::pinningEnforceTestMode;
-    return PublicKeyPinningService::HostHasPins(aHost, mozilla::pkix::Now(),
+    return PublicKeyPinningService::HostHasPins(flatHost.get(),
+                                                mozilla::pkix::Now(),
                                                 enforceTestMode, *aResult);
   }
 
   // Holepunch chart.apis.google.com and subdomains.
-  nsAutoCString host(PublicKeyPinningService::CanonicalizeHostname(aHost));
+  nsAutoCString host(
+    PublicKeyPinningService::CanonicalizeHostname(flatHost.get()));
   if (host.EqualsLiteral("chart.apis.google.com") ||
       StringEndsWith(host, NS_LITERAL_CSTRING(".chart.apis.google.com"))) {
     if (aCached) {
       *aCached = true;
     }
     return NS_OK;
   }
 
@@ -1222,35 +1229,38 @@ nsSiteSecurityService::ClearPreloads()
 }
 
 bool entryStateNotOK(SiteHPKPState& state, mozilla::pkix::Time& aEvalTime) {
   return state.mState != SecurityPropertySet || state.IsExpired(aEvalTime) ||
          state.mSHA256keys.Length() < 1;
 }
 
 NS_IMETHODIMP
-nsSiteSecurityService::GetKeyPinsForHostname(const char* aHostname,
+nsSiteSecurityService::GetKeyPinsForHostname(const nsACString& aHostname,
                                              mozilla::pkix::Time& aEvalTime,
                                              /*out*/ nsTArray<nsCString>& pinArray,
                                              /*out*/ bool* aIncludeSubdomains,
-                                             /*out*/ bool* afound) {
-   // Child processes are not allowed direct access to this.
-   if (!XRE_IsParentProcess()) {
-     MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::GetKeyPinsForHostname");
-   }
+                                             /*out*/ bool* afound)
+{
+  // Child processes are not allowed direct access to this.
+  if (!XRE_IsParentProcess()) {
+    MOZ_CRASH("Child process: no direct access to "
+              "nsISiteSecurityService::GetKeyPinsForHostname");
+  }
 
   NS_ENSURE_ARG(afound);
-  NS_ENSURE_ARG(aHostname);
 
-  SSSLOG(("Top of GetKeyPinsForHostname for %s", aHostname));
+  const nsCString& flatHostname = PromiseFlatCString(aHostname);
+  SSSLOG(("Top of GetKeyPinsForHostname for %s", flatHostname.get()));
   *afound = false;
   *aIncludeSubdomains = false;
   pinArray.Clear();
 
-  nsAutoCString host(PublicKeyPinningService::CanonicalizeHostname(aHostname));
+  nsAutoCString host(
+    PublicKeyPinningService::CanonicalizeHostname(flatHostname.get()));
   nsAutoCString storageKey;
   SetStorageKey(storageKey, host, nsISiteSecurityService::HEADER_HPKP);
 
   SSSLOG(("storagekey '%s'\n", storageKey.get()));
   mozilla::DataStorageType storageType = mozilla::DataStorage_Persistent;
   nsCString value = mSiteStateStorage->Get(storageKey, storageType);
 
   // decode now
@@ -1274,28 +1284,29 @@ nsSiteSecurityService::GetKeyPinsForHost
   }
   pinArray = foundEntry.mSHA256keys;
   *aIncludeSubdomains = foundEntry.mIncludeSubdomains;
   *afound = true;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSiteSecurityService::SetKeyPins(const char* aHost, bool aIncludeSubdomains,
+nsSiteSecurityService::SetKeyPins(const nsACString& aHost,
+                                  bool aIncludeSubdomains,
                                   int64_t aExpires, uint32_t aPinCount,
                                   const char** aSha256Pins,
                                   bool aIsPreload,
                                   /*out*/ bool* aResult)
 {
-   // Child processes are not allowed direct access to this.
-   if (!XRE_IsParentProcess()) {
-     MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::SetKeyPins");
-   }
+  // Child processes are not allowed direct access to this.
+  if (!XRE_IsParentProcess()) {
+    MOZ_CRASH("Child process: no direct access to "
+              "nsISiteSecurityService::SetKeyPins");
+  }
 
-  NS_ENSURE_ARG_POINTER(aHost);
   NS_ENSURE_ARG_POINTER(aResult);
   NS_ENSURE_ARG_POINTER(aSha256Pins);
 
   SSSLOG(("Top of SetKeyPins"));
 
   nsTArray<nsCString> sha256keys;
   for (unsigned int i = 0; i < aPinCount; i++) {
     nsAutoCString pin(aSha256Pins[i]);
@@ -1303,37 +1314,41 @@ nsSiteSecurityService::SetKeyPins(const 
     if (!stringIsBase64EncodingOf256bitValue(pin)) {
       return NS_ERROR_INVALID_ARG;
     }
     sha256keys.AppendElement(pin);
   }
   SiteHPKPState dynamicEntry(aExpires, SecurityPropertySet,
                              aIncludeSubdomains, sha256keys);
   // we always store data in permanent storage (ie no flags)
-  nsAutoCString host(PublicKeyPinningService::CanonicalizeHostname(aHost));
+  const nsCString& flatHost = PromiseFlatCString(aHost);
+  nsAutoCString host(
+    PublicKeyPinningService::CanonicalizeHostname(flatHost.get()));
   return SetHPKPState(host.get(), dynamicEntry, 0, aIsPreload);
 }
 
 NS_IMETHODIMP
-nsSiteSecurityService::SetHSTSPreload(const char* aHost,
+nsSiteSecurityService::SetHSTSPreload(const nsACString& aHost,
                                       bool aIncludeSubdomains,
                                       int64_t aExpires,
                               /*out*/ bool* aResult)
 {
-   // Child processes are not allowed direct access to this.
-   if (!XRE_IsParentProcess()) {
-     MOZ_CRASH("Child process: no direct access to nsISiteSecurityService::SetHSTSPreload");
-   }
+  // Child processes are not allowed direct access to this.
+  if (!XRE_IsParentProcess()) {
+    MOZ_CRASH("Child process: no direct access to "
+              "nsISiteSecurityService::SetHSTSPreload");
+  }
 
-  NS_ENSURE_ARG_POINTER(aHost);
   NS_ENSURE_ARG_POINTER(aResult);
 
   SSSLOG(("Top of SetHSTSPreload"));
 
-  nsAutoCString host(PublicKeyPinningService::CanonicalizeHostname(aHost));
+  const nsCString& flatHost = PromiseFlatCString(aHost);
+  nsAutoCString host(
+    PublicKeyPinningService::CanonicalizeHostname(flatHost.get()));
   return SetHSTSState(nsISiteSecurityService::HEADER_HSTS, host.get(), aExpires,
                       aIncludeSubdomains, 0, SecurityPropertySet, true);
 }
 
 nsresult
 nsSiteSecurityService::SetHPKPState(const char* aHost, SiteHPKPState& entry,
                                     uint32_t aFlags, bool aIsPreload)
 {
--- a/security/manager/ssl/nsSiteSecurityService.h
+++ b/security/manager/ssl/nsSiteSecurityService.h
@@ -127,24 +127,25 @@ protected:
   virtual ~nsSiteSecurityService();
 
 private:
   nsresult GetHost(nsIURI *aURI, nsACString &aResult);
   nsresult SetHSTSState(uint32_t aType, const char* aHost, int64_t maxage,
                         bool includeSubdomains, uint32_t flags,
                         SecurityPropertyState aHSTSState, bool aIsPreload);
   nsresult ProcessHeaderInternal(uint32_t aType, nsIURI* aSourceURI,
-                                 const char* aHeader, nsISSLStatus* aSSLStatus,
+                                 const nsCString& aHeader,
+                                 nsISSLStatus* aSSLStatus,
                                  uint32_t aFlags, uint64_t* aMaxAge,
                                  bool* aIncludeSubdomains,
                                  uint32_t* aFailureResult);
-  nsresult ProcessSTSHeader(nsIURI* aSourceURI, const char* aHeader,
+  nsresult ProcessSTSHeader(nsIURI* aSourceURI, const nsCString& aHeader,
                             uint32_t flags, uint64_t* aMaxAge,
                             bool* aIncludeSubdomains, uint32_t* aFailureResult);
-  nsresult ProcessPKPHeader(nsIURI* aSourceURI, const char* aHeader,
+  nsresult ProcessPKPHeader(nsIURI* aSourceURI, const nsCString& aHeader,
                             nsISSLStatus* aSSLStatus, uint32_t flags,
                             uint64_t* aMaxAge, bool* aIncludeSubdomains,
                             uint32_t* aFailureResult);
   nsresult SetHPKPState(const char* aHost, SiteHPKPState& entry, uint32_t flags,
                         bool aIsPreload);
   nsresult RemoveStateInternal(uint32_t aType, const nsAutoCString& aHost,
                                uint32_t aFlags, bool aIsPreload);
   bool HostHasHSTSEntry(const nsAutoCString& aHost,
--- a/security/manager/ssl/tests/gtest/STSParserTest.cpp
+++ b/security/manager/ssl/tests/gtest/STSParserTest.cpp
@@ -1,32 +1,34 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdio.h>
 
 #include "gtest/gtest.h"
+#include "nsDependentString.h"
 #include "nsNetUtil.h"
 #include "nsISiteSecurityService.h"
 #include "nsIURI.h"
 
 void
 TestSuccess(const char* hdr, bool extraTokens,
             uint64_t expectedMaxAge, bool expectedIncludeSubdomains,
             nsISiteSecurityService* sss)
 {
   nsCOMPtr<nsIURI> dummyUri;
   nsresult rv = NS_NewURI(getter_AddRefs(dummyUri), "https://foo.com/bar.html");
   ASSERT_TRUE(NS_SUCCEEDED(rv)) << "Failed to create URI";
 
   uint64_t maxAge = 0;
   bool includeSubdomains = false;
   rv = sss->UnsafeProcessHeader(nsISiteSecurityService::HEADER_HSTS, dummyUri,
-                                hdr, 0, &maxAge, &includeSubdomains, nullptr);
+                                nsDependentCString(hdr), 0, &maxAge,
+                                &includeSubdomains, nullptr);
   ASSERT_TRUE(NS_SUCCEEDED(rv)) << "Failed to process valid header: " << hdr;
 
   ASSERT_EQ(maxAge, expectedMaxAge) << "Did not correctly parse maxAge";
   EXPECT_EQ(includeSubdomains, expectedIncludeSubdomains) <<
     "Did not correctly parse presence/absence of includeSubdomains";
 
   if (extraTokens) {
     EXPECT_EQ(rv, NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA) <<
@@ -41,17 +43,18 @@ TestSuccess(const char* hdr, bool extraT
 void TestFailure(const char* hdr,
                  nsISiteSecurityService* sss)
 {
   nsCOMPtr<nsIURI> dummyUri;
   nsresult rv = NS_NewURI(getter_AddRefs(dummyUri), "https://foo.com/bar.html");
   ASSERT_TRUE(NS_SUCCEEDED(rv)) << "Failed to create URI";
 
   rv = sss->UnsafeProcessHeader(nsISiteSecurityService::HEADER_HSTS, dummyUri,
-                                hdr, 0, nullptr, nullptr, nullptr);
+                                nsDependentCString(hdr), 0, nullptr, nullptr,
+                                nullptr);
   ASSERT_TRUE(NS_FAILED(rv)) << "Parsed invalid header: " << hdr;
 
   printf("%s\n", hdr);
 }
 
 TEST(psm_STSParser, Test)
 {
     nsresult rv;