File: CVE-2021-3803.patch

package info (click to toggle)
node-nth-check 2.0.0-1%2Bdeb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 728 kB
  • sloc: javascript: 92; makefile: 4
file content (107 lines) | stat: -rw-r--r-- 2,841 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
Description: Replace regex with hand-rolled parser
Author: Felix Böhm <188768+fb55@users.noreply.github.com>
Origin: upstream, https://patch-diff.githubusercontent.com/raw/fb55/nth-check/pull/9.patch
Bug: https://github.com/advisories/GHSA-rp65-9cf3-cjxr
Forwarded: not-needed
Reviewed-By: Yadd <yadd@debian.org>
Last-Update: 2022-02-05

--- a/src/parse.ts
+++ b/src/parse.ts
@@ -1,7 +1,9 @@
 // Following http://www.w3.org/TR/css3-selectors/#nth-child-pseudo
 
-// [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]?
-const RE_NTH_ELEMENT = /^([+-]?\d*n)?\s*(?:([+-]?)\s*(\d+))?$/;
+// Whitespace as per https://www.w3.org/TR/selectors-3/#lex is " \t\r\n\f"
+const whitespace = new Set([9, 10, 12, 13, 32]);
+const ZERO = "0".charCodeAt(0);
+const NINE = "9".charCodeAt(0);
 
 /**
  * Parses an expression.
@@ -19,24 +21,72 @@
         return [2, 1];
     }
 
-    const parsed = formula.match(RE_NTH_ELEMENT);
+    // Parse [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]?
 
-    if (!parsed) {
+    let idx = 0;
+
+    let a = 0;
+    let sign = readSign();
+    let number = readNumber();
+
+    if (idx < formula.length && formula.charAt(idx) === "n") {
+        idx++;
+        a = sign * (number ?? 1);
+
+        skipWhitespace();
+
+        if (idx < formula.length) {
+            sign = readSign();
+            skipWhitespace();
+            number = readNumber();
+        } else {
+            sign = number = 0;
+        }
+    }
+
+    // Throw if there is anything else
+    if (number === null || idx < formula.length) {
         throw new Error(`n-th rule couldn't be parsed ('${formula}')`);
     }
 
-    let a;
+    return [a, sign * number];
 
-    if (parsed[1]) {
-        a = parseInt(parsed[1], 10);
-        if (isNaN(a)) {
-            a = parsed[1].startsWith("-") ? -1 : 1;
+    function readSign() {
+        if (formula.charAt(idx) === "-") {
+            idx++;
+            return -1;
         }
-    } else a = 0;
 
-    const b =
-        (parsed[2] === "-" ? -1 : 1) *
-        (parsed[3] ? parseInt(parsed[3], 10) : 0);
+        if (formula.charAt(idx) === "+") {
+            idx++;
+        }
+
+        return 1;
+    }
 
-    return [a, b];
+    function readNumber() {
+        const start = idx;
+        let value = 0;
+
+        while (
+            idx < formula.length &&
+            formula.charCodeAt(idx) >= ZERO &&
+            formula.charCodeAt(idx) <= NINE
+        ) {
+            value = value * 10 + (formula.charCodeAt(idx) - ZERO);
+            idx++;
+        }
+
+        // Return `null` if we didn't read anything.
+        return idx === start ? null : value;
+    }
+
+    function skipWhitespace() {
+        while (
+            idx < formula.length &&
+            whitespace.has(formula.charCodeAt(idx))
+        ) {
+            idx++;
+        }
+    }
 }