浏览代码

Chore: improve reject hosts robustness

SukkaW 2 年之前
父节点
当前提交
37b01ff016
共有 3 个文件被更改,包括 49 次插入17 次删除
  1. 4 0
      Build/lib/cached-tld-parse.ts
  2. 33 0
      Build/lib/is-fast-ip.ts
  3. 12 17
      Build/lib/parse-filter.ts

+ 4 - 0
Build/lib/cached-tld-parse.ts

@@ -5,8 +5,12 @@ import type { PublicSuffixList } from 'gorhill-publicsuffixlist';
 const cache = createCache('cached-tld-parse', true);
 
 const sharedConfig = { allowPrivateDomains: true };
+const sharedConfig2 = { allowPrivateDomains: true, detectIp: false };
 
+/** { allowPrivateDomains: true } */
 export const parse = (domain: string) => cache.sync(domain, () => tldts.parse(domain, sharedConfig));
+/** { allowPrivateDomains: true, detectIp: false } */
+export const parse2 = (domain: string) => cache.sync(domain, () => tldts.parse(domain, sharedConfig2));
 
 let gothillGetDomainCache: ReturnType<typeof createCache> | null = null;
 export const createCachedGorhillGetDomain = (gorhill: PublicSuffixList) => {

+ 33 - 0
Build/lib/is-fast-ip.ts

@@ -0,0 +1,33 @@
+/**
+ * Check if a hostname is an IP. You should be aware that this only works
+ * because `hostname` is already garanteed to be a valid hostname!
+ */
+export function isProbablyIpv4(hostname: string): boolean {
+  // Cannot be shorted than 1.1.1.1
+  if (hostname.length < 7) {
+    return false;
+  }
+
+  // Cannot be longer than: 255.255.255.255
+  if (hostname.length > 15) {
+    return false;
+  }
+
+  let numberOfDots = 0;
+
+  for (let i = 0; i < hostname.length; i += 1) {
+    const code = hostname.charCodeAt(i);
+
+    if (code === 46 /* '.' */) {
+      numberOfDots += 1;
+    } else if (code < 48 /* '0' */ || code > 57 /* '9' */) {
+      return false;
+    }
+  }
+
+  return (
+    numberOfDots === 3
+    && hostname.charCodeAt(0) !== 46
+    && /* '.' */ hostname.charCodeAt(hostname.length - 1) !== 46 /* '.' */
+  );
+}

+ 12 - 17
Build/lib/parse-filter.ts

@@ -6,6 +6,7 @@ import { NetworkFilter } from '@cliqz/adblocker';
 import { processLine } from './process-line';
 import { getGorhillPublicSuffixPromise } from './get-gorhill-publicsuffix';
 import type { PublicSuffixList } from 'gorhill-publicsuffixlist';
+import { isProbablyIpv4 } from './is-fast-ip';
 
 const DEBUG_DOMAIN_TO_FIND: string | null = null; // example.com | null
 let foundDebugDomain = false;
@@ -22,19 +23,16 @@ const warnOnce = (url: string, isWhite: boolean, ...message: any[]) => {
 
 const normalizeDomain = (domain: string) => {
   if (!domain) return null;
+  if (isProbablyIpv4(domain)) return null;
 
-  const parsed = tldts.parse(domain);
+  const parsed = tldts.parse2(domain);
   if (parsed.isIp) return null;
+  if (!parsed.isIcann && !parsed.isPrivate) return null;
 
-  if (parsed.isIcann || parsed.isPrivate) {
-    const h = parsed.hostname;
+  const h = parsed.hostname;
+  if (!h) return null;
 
-    if (h === null) return null;
-
-    return h[0] === '.' ? h.slice(1) : h;
-  }
-
-  return null;
+  return h[0] === '.' ? h.slice(1) : h;
 };
 
 export async function processDomainLists(domainListsUrl: string | URL, includeAllSubDomain = false) {
@@ -89,6 +87,7 @@ export async function processHosts(hostsUrl: string | URL, includeAllSubDomain =
     }
 
     const domain = skipDomainCheck ? _domain : normalizeDomain(_domain);
+
     if (domain) {
       if (includeAllSubDomain) {
         domainSets.add(`.${domain}`);
@@ -301,19 +300,15 @@ function parse($line: string, gorhill: PublicSuffixList): null | [hostname: stri
       // && (!filter.isRegex()) // isPlain() === !isRegex()
       && (!filter.isFullRegex())
     ) {
-      if (!gorhill.getDomain(filter.hostname)) {
-        return null;
-      }
       const hostname = normalizeDomain(filter.hostname);
       if (!hostname) {
+        console.log('      * [parse-filter E0000] invalid domain:', filter.hostname);
         return null;
       }
 
-      // console.log({
-      //   '||': filter.isHostnameAnchor(),
-      //   '|': filter.isLeftAnchor(),
-      //   '|https://': !filter.isHostnameAnchor() && (filter.fromHttps() || filter.fromHttp())
-      // });
+      //  |: filter.isHostnameAnchor(),
+      //  |: filter.isLeftAnchor(),
+      //  |https://: !filter.isHostnameAnchor() && (filter.fromHttps() || filter.fromHttp())
       const isIncludeAllSubDomain = filter.isHostnameAnchor();
 
       if (filter.isException() || filter.isBadFilter()) {