Bug 1358225: Validate characters with a cached lookup array. About 10-15% improvement on TestStandardURL.Perf gtest. r=valentin.gosu
authorMilan Sreckovic <milan@mozilla.com>
Mon, 15 May 2017 11:53:40 -0400
changeset 358475 ddd4f6f93fabc7f90771a53f93f9444acc7534f3
parent 358474 e37f91d106108cb96d9492b4084e956821a7e805
child 358476 b733db3d681b1f9dd3e72773188ec565d0beaeb8
push id31827
push usercbook@mozilla.com
push dateTue, 16 May 2017 10:34:19 +0000
treeherdermozilla-central@49365d675cbb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvalentin.gosu
bugs1358225
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1358225: Validate characters with a cached lookup array. About 10-15% improvement on TestStandardURL.Perf gtest. r=valentin.gosu MozReview-Commit-ID: KMABJ3X6IZ1
netwerk/base/nsStandardURL.cpp
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim:set ts=4 sw=4 sts=4 et cindent: */
 /* 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 "IPCMessageUtils.h"
 
+#include "nsASCIIMask.h"
 #include "nsStandardURL.h"
 #include "nsCRT.h"
 #include "nsEscape.h"
 #include "nsIFile.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
@@ -137,16 +138,35 @@ namespace net {
 
 static NS_DEFINE_CID(kThisImplCID, NS_THIS_STANDARDURL_IMPL_CID);
 static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
 
 nsIIDNService *nsStandardURL::gIDN = nullptr;
 bool nsStandardURL::gInitialized = false;
 char nsStandardURL::gHostLimitDigits[] = { '/', '\\', '?', '#', 0 };
 
+// Invalid host characters
+// We still allow % because it is in the ID of addons.
+// Any percent encoded ASCII characters that are not allowed in the
+// hostname are not percent decoded, and will be parsed just fine.
+//
+// Note that the array below will be initialized at compile time,
+// so we do not need to "optimize" TestForInvalidHostCharacters.
+//
+constexpr bool TestForInvalidHostCharacters(char c)
+{
+    // Testing for these:
+    // CONTROL_CHARACTERS " #/:?@[\\]*<>|\"";
+    return (c > 0 && c < 32) || // The control characters are [1, 31]
+           c == ' ' || c == '#' || c == '/' || c == ':' || c == '?' ||
+           c == '@' || c == '[' || c == '\\' || c == ']' || c == '*' ||
+           c == '<' || c == '>' || c == '|' || c == '"';
+}
+constexpr ASCIIMaskArray sInvalidHostChars = CreateASCIIMask(TestForInvalidHostCharacters);
+
 //----------------------------------------------------------------------------
 
 #define ENSURE_MUTABLE() \
   PR_BEGIN_MACRO \
     if (!mMutable) { \
         NS_WARNING("attempt to modify an immutable nsStandardURL"); \
         return NS_ERROR_ABORT; \
     } \
@@ -685,24 +705,23 @@ nsStandardURL::ValidIPv6orHostname(const
         return net_IsValidIPv6Addr(host + 1, length - 2);
     }
 
     if (openBracket || closeBracket) {
         // Fail if only one of the brackets is present
         return false;
     }
 
-    const char *end = host + length;
-    if (end != net_FindCharInSet(host, end, CONTROL_CHARACTERS " #/:?@[\\]*<>|\"")) {
-        // We still allow % because it is in the ID of addons.
-        // Any percent encoded ASCII characters that are not allowed in the
-        // hostname are not percent decoded, and will be parsed just fine.
-        return false;
+    const char* end = host + length;
+    const char* iter = host;
+    for (; iter != end && *iter; ++iter) {
+        if (ASCIIMask::IsMasked(sInvalidHostChars, *iter)) {
+            return false;
+        }
     }
-
     return true;
 }
 
 void
 nsStandardURL::CoalescePath(netCoalesceFlags coalesceFlag, char *path)
 {
     net_CoalesceDirs(coalesceFlag, path);
     int32_t newLen = strlen(path);