1
0
Fork 0
mirror of https://github.com/gorhill/uMatrix.git synced 2024-05-04 04:13:55 +12:00
uMatrix/src/lib/publicsuffixlist/wasm/publicsuffixlist.wat
Raymond Hill 9b292304d3
Bring uMatrix up to date
Notably:
- Import logger improvements from uBO
- Import CNAME uncloaking from uBO
- Import more improvements from uBO
- Make use of modern JS features

This should un-stall further development of uMatrix.
2019-12-20 12:24:18 -05:00

318 lines
8.9 KiB
Plaintext

;;
;; uBlock Origin - a browser extension to block requests.
;; Copyright (C) 2019-present Raymond Hill
;;
;; License: pick the one which suits you:
;; GPL v3 see <https://www.gnu.org/licenses/gpl.html>
;; APL v2 see <http://www.apache.org/licenses/LICENSE-2.0>
;;
;; Home: https://github.com/gorhill/publicsuffixlist.js
;; File: publicsuffixlist.wat
;;
;; Description: WebAssembly implementation for core lookup method in
;; publicsuffixlist.js
;;
;; How to compile:
;;
;; wat2wasm publicsuffixlist.wat -o publicsuffixlist.wasm
;;
;; The `wat2wasm` tool can be downloaded from an official WebAssembly
;; project:
;; https://github.com/WebAssembly/wabt/releases
(module
;;
;; module start
;;
(memory (import "imports" "memory") 1)
;;
;; Tree encoding in array buffer:
;;
;; Node:
;; + u8: length of char data
;; + u8: flags => bit 0: is_publicsuffix, bit 1: is_exception
;; + u16: length of array of children
;; + u32: char data or offset to char data
;; + u32: offset to array of children
;; = 12 bytes
;;
;; // i32 / i8
;; const HOSTNAME_SLOT = 0; // jshint ignore:line
;; const LABEL_INDICES_SLOT = 256; // -- / 256
;; const RULES_PTR_SLOT = 100; // 100 / 400
;; const CHARDATA_PTR_SLOT = 101; // 101 / 404
;; const EMPTY_STRING = '';
;; const SELFIE_MAGIC = 2;
;;
;;
;; Public functions
;;
;;
;; unsigned int getPublicSuffixPos()
;;
;; Returns an offset to the start of the public suffix.
;;
(func (export "getPublicSuffixPos")
(result i32) ;; result = match index, -1 = miss
(local $iCharData i32) ;; offset to start of character data
(local $iNode i32) ;; offset to current node
(local $iLabel i32) ;; offset to label indices
(local $cursorPos i32) ;; position of cursor within hostname argument
(local $labelBeg i32)
(local $labelLen i32)
(local $nCandidates i32)
(local $iCandidates i32)
(local $iFound i32)
(local $l i32)
(local $r i32)
(local $d i32)
(local $iCandidate i32)
(local $iCandidateNode i32)
(local $candidateLen i32)
(local $iCandidateChar i32)
(local $_1 i32)
(local $_2 i32)
(local $_3 i32)
;;
;; const iCharData = buf32[CHARDATA_PTR_SLOT];
i32.const 404
i32.load
set_local $iCharData
;; let iNode = pslBuffer32[RULES_PTR_SLOT];
i32.const 400
i32.load
i32.const 2
i32.shl
set_local $iNode
;; let iLabel = LABEL_INDICES_SLOT;
i32.const 256
set_local $iLabel
;; let cursorPos = -1;
i32.const -1
set_local $cursorPos
;; label-lookup loop
;; for (;;) {
block $labelLookupDone loop $labelLookup
;; // Extract label indices
;; const labelBeg = buf8[iLabel+1];
;; const labelLen = buf8[iLabel+0] - labelBeg;
get_local $iLabel
i32.load8_u
get_local $iLabel
i32.load8_u offset=1
tee_local $labelBeg
i32.sub
set_local $labelLen
;; // Match-lookup loop: binary search
;; let r = buf32[iNode+0] >>> 16;
;; if ( r === 0 ) { break; }
get_local $iNode
i32.load16_u offset=2
tee_local $r
i32.eqz
br_if $labelLookupDone
;; const iCandidates = buf32[iNode+2];
get_local $iNode
i32.load offset=8
i32.const 2
i32.shl
set_local $iCandidates
;; let l = 0;
;; let iFound = 0;
i32.const 0
tee_local $l
set_local $iFound
;; while ( l < r ) {
block $binarySearchDone loop $binarySearch
get_local $l
get_local $r
i32.ge_u
br_if $binarySearchDone
;; const iCandidate = l + r >>> 1;
get_local $l
get_local $r
i32.add
i32.const 1
i32.shr_u
tee_local $iCandidate
;; const iCandidateNode = iCandidates + iCandidate + (iCandidate << 1);
i32.const 2
i32.shl
tee_local $_1
get_local $_1
i32.const 1
i32.shl
i32.add
get_local $iCandidates
i32.add
tee_local $iCandidateNode
;; const candidateLen = buf32[iCandidateNode+0] & 0x000000FF;
i32.load8_u
set_local $candidateLen
;; let d = labelLen - candidateLen;
get_local $labelLen
get_local $candidateLen
i32.sub
tee_local $d
;; if ( d === 0 ) {
i32.eqz
if
;; const iCandidateChar = candidateLen <= 4
get_local $candidateLen
i32.const 4
i32.le_u
if
;; ? iCandidateNode + 1 << 2
get_local $iCandidateNode
i32.const 4
i32.add
set_local $iCandidateChar
else
;; : buf32[CHARDATA_PTR_SLOT] + buf32[iCandidateNode+1];
get_local $iCharData
get_local $iCandidateNode
i32.load offset=4
i32.add
set_local $iCandidateChar
end
;; for ( let i = 0; i < labelLen; i++ ) {
get_local $labelBeg
tee_local $_1
get_local $labelLen
i32.add
set_local $_3
get_local $iCandidateChar
set_local $_2
block $findDiffDone loop $findDiff
;; d = buf8[labelBeg+i] - buf8[iCandidateChar+i];
;; if ( d !== 0 ) { break; }
get_local $_1
i32.load8_u
get_local $_2
i32.load8_u
i32.sub
tee_local $d
br_if $findDiffDone
get_local $_1
i32.const 1
i32.add
tee_local $_1
get_local $_3
i32.eq
br_if $findDiffDone
get_local $_2
i32.const 1
i32.add
set_local $_2
br $findDiff
;; }
end end
;; }
end
;; if ( d < 0 ) {
;; r = iCandidate;
get_local $d
i32.const 0
i32.lt_s
if
get_local $iCandidate
set_local $r
br $binarySearch
end
;; } else if ( d > 0 ) {
;; l = iCandidate + 1;
get_local $d
i32.const 0
i32.gt_s
if
get_local $iCandidate
i32.const 1
i32.add
set_local $l
br $binarySearch
end
;; } else /* if ( d === 0 ) */ {
;; iFound = iCandidateNode;
;; break;
;; }
get_local $iCandidateNode
set_local $iFound
end end
;; }
;; // 2. If no rules match, the prevailing rule is "*".
;; if ( iFound === 0 ) {
;; if ( buf8[iCandidates + 1 << 2] !== 0x2A /* '*' */ ) { break; }
;; iFound = iCandidates;
;; }
get_local $iFound
i32.eqz
if
get_local $iCandidates
i32.load8_u offset=4
i32.const 0x2A
i32.ne
br_if $labelLookupDone
get_local $iCandidates
set_local $iFound
end
;; iNode = iFound;
get_local $iFound
tee_local $iNode
;; // 5. If the prevailing rule is a exception rule, modify it by
;; // removing the leftmost label.
;; if ( (buf32[iNode+0] & 0x00000200) !== 0 ) {
;; if ( iLabel > LABEL_INDICES_SLOT ) {
;; return iLabel - 2;
;; }
;; break;
;; }
i32.load8_u offset=1
tee_local $_1
i32.const 0x02
i32.and
if
get_local $iLabel
i32.const 256
i32.gt_u
if
get_local $iLabel
i32.const -2
i32.add
return
end
br $labelLookupDone
end
;; if ( (buf32[iNode+0] & 0x00000100) !== 0 ) {
;; cursorPos = labelBeg;
;; }
get_local $_1
i32.const 0x01
i32.and
if
get_local $iLabel
set_local $cursorPos
end
;; if ( labelBeg === 0 ) { break; }
get_local $labelBeg
i32.eqz
br_if $labelLookupDone
;; iLabel += 2;
get_local $iLabel
i32.const 2
i32.add
set_local $iLabel
br $labelLookup
end end
get_local $cursorPos
)
;;
;; module end
;;
)