| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 0bb84b0 commit ac9599a
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -27,7 +27,7 @@ const { | |||
| 27 | 27 | ArrayPrototypePush, | |
| 28 | 28 | JSONParse, | |
| 29 | 29 | ObjectCreate, | |
| 30 | - StringPrototypeReplace, | ||
| 30 | + RegExpPrototypeSymbolReplace, | ||
| 31 | 31 | } = primordials; | |
| 32 | 32 | ||
| 33 | 33 | const { | |
@@ -134,21 +134,21 @@ function translatePeerCertificate(c) { | |||
| 134 | 134 | c.infoAccess = ObjectCreate(null); | |
| 135 | 135 | ||
| 136 | 136 | // XXX: More key validation? | |
| 137 | - StringPrototypeReplace(info, /([^\n:]*):([^\n]*)(?:\n|$)/g, | ||
| 138 | - (all, key, val) => { | ||
| 139 | - if (val.charCodeAt(0) === 0x22) { | ||
| 140 | - // The translatePeerCertificate function is only | ||
| 141 | - // used on internally created legacy certificate | ||
| 142 | - // objects, and any value that contains a quote | ||
| 143 | - // will always be a valid JSON string literal, | ||
| 144 | - // so this should never throw. | ||
| 145 | - val = JSONParse(val); | ||
| 146 | - } | ||
| 147 | - if (key in c.infoAccess) | ||
| 148 | - ArrayPrototypePush(c.infoAccess[key], val); | ||
| 149 | - else | ||
| 150 | - c.infoAccess[key] = [val]; | ||
| 151 | - }); | ||
| 137 | + RegExpPrototypeSymbolReplace(/([^\n:]*):([^\n]*)(?:\n|$)/g, info, | ||
| 138 | + (all, key, val) => { | ||
| 139 | + if (val.charCodeAt(0) === 0x22) { | ||
| 140 | + // The translatePeerCertificate function is only | ||
| 141 | + // used on internally created legacy certificate | ||
| 142 | + // objects, and any value that contains a quote | ||
| 143 | + // will always be a valid JSON string literal, | ||
| 144 | + // so this should never throw. | ||
| 145 | + val = JSONParse(val); | ||
| 146 | + } | ||
| 147 | + if (key in c.infoAccess) | ||
| 148 | + ArrayPrototypePush(c.infoAccess[key], val); | ||
| 149 | + else | ||
| 150 | + c.infoAccess[key] = [val]; | ||
| 151 | + }); | ||
| 152 | 152 | } | |
| 153 | 153 | return c; | |
| 154 | 154 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -535,7 +535,7 @@ function REPLServer(prompt, | |||
| 535 | 535 | ||
| 536 | 536 | // This will set the values from `savedRegExMatches` to corresponding | |
| 537 | 537 | // predefined RegExp properties `RegExp.$1`, `RegExp.$2` ... `RegExp.$9` | |
| 538 | - RegExpPrototypeTest(regExMatcher, | ||
| 538 | + RegExpPrototypeExec(regExMatcher, | ||
| 539 | 539 | ArrayPrototypeJoin(savedRegExMatches, sep)); | |
| 540 | 540 | ||
| 541 | 541 | let finished = false; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -143,5 +143,45 @@ new RuleTester({ | |||
| 143 | 143 | code: 'ReflectDefineProperty({}, "key", { enumerable: true })', | |
| 144 | 144 | errors: [{ message: /null-prototype/ }], | |
| 145 | 145 | }, | |
| 146 | + { | ||
| 147 | + code: 'RegExpPrototypeTest(/some regex/, "some string")', | ||
| 148 | + errors: [{ message: /looks up the "exec" property/ }], | ||
| 149 | + }, | ||
| 150 | + { | ||
| 151 | + code: 'RegExpPrototypeSymbolMatch(/some regex/, "some string")', | ||
| 152 | + errors: [{ message: /looks up the "exec" property/ }], | ||
| 153 | + }, | ||
| 154 | + { | ||
| 155 | + code: 'RegExpPrototypeSymbolMatchAll(/some regex/, "some string")', | ||
| 156 | + errors: [{ message: /looks up the "exec" property/ }], | ||
| 157 | + }, | ||
| 158 | + { | ||
| 159 | + code: 'RegExpPrototypeSymbolSearch(/some regex/, "some string")', | ||
| 160 | + errors: [{ message: /looks up the "exec" property/ }], | ||
| 161 | + }, | ||
| 162 | + { | ||
| 163 | + code: 'StringPrototypeMatch("some string", /some regex/)', | ||
| 164 | + errors: [{ message: /looks up the Symbol\.match property/ }], | ||
| 165 | + }, | ||
| 166 | + { | ||
| 167 | + code: 'StringPrototypeMatchAll("some string", /some regex/)', | ||
| 168 | + errors: [{ message: /looks up the Symbol\.matchAll property/ }], | ||
| 169 | + }, | ||
| 170 | + { | ||
| 171 | + code: 'StringPrototypeReplace("some string", /some regex/, "some replacement")', | ||
| 172 | + errors: [{ message: /looks up the Symbol\.replace property/ }], | ||
| 173 | + }, | ||
| 174 | + { | ||
| 175 | + code: 'StringPrototypeReplaceAll("some string", /some regex/, "some replacement")', | ||
| 176 | + errors: [{ message: /looks up the Symbol\.replace property/ }], | ||
| 177 | + }, | ||
| 178 | + { | ||
| 179 | + code: 'StringPrototypeSearch("some string", /some regex/)', | ||
| 180 | + errors: [{ message: /looks up the Symbol\.search property/ }], | ||
| 181 | + }, | ||
| 182 | + { | ||
| 183 | + code: 'StringPrototypeSplit("some string", /some regex/)', | ||
| 184 | + errors: [{ message: /looks up the Symbol\.split property/ }], | ||
| 185 | + }, | ||
| 146 | 186 | ] | |
| 147 | 187 | }); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -63,6 +63,17 @@ function checkPropertyDescriptor(context, node) { | |||
| 63 | 63 | }); | |
| 64 | 64 | } | |
| 65 | 65 | ||
| 66 | + function createUnsafeStringMethodReport(context, name, lookedUpProperty) { | ||
| 67 | + return { | ||
| 68 | + [`${CallExpression}[expression.callee.name=${JSON.stringify(name)}]`](node) { | ||
| 69 | + context.report({ | ||
| 70 | + node, | ||
| 71 | + message: `${name} looks up the ${lookedUpProperty} property on the first argument`, | ||
| 72 | + }); | ||
| 73 | + } | ||
| 74 | + }; | ||
| 75 | + } | ||
| 76 | + | ||
| 66 | 77 | const CallExpression = 'ExpressionStatement[expression.type="CallExpression"]'; | |
| 67 | 78 | module.exports = { | |
| 68 | 79 | meta: { hasSuggestions: true }, | |
@@ -87,6 +98,36 @@ module.exports = { | |||
| 87 | 98 | [`${CallExpression}[expression.callee.name="ObjectCreate"][expression.arguments.length=2]`](node) { | |
| 88 | 99 | checkProperties(context, node.expression.arguments[1]); | |
| 89 | 100 | }, | |
| 101 | + [`${CallExpression}[expression.callee.name="RegExpPrototypeTest"]`](node) { | ||
| 102 | + context.report({ | ||
| 103 | + node, | ||
| 104 | + message: '%RegExp.prototype.test% looks up the "exec" property of `this` value', | ||
| 105 | + suggest: [{ | ||
| 106 | + desc: 'Use RegexpPrototypeExec instead', | ||
| 107 | + fix(fixer) { | ||
| 108 | + const testRange = { ...node.range }; | ||
| 109 | + testRange.start = testRange.start + 'RegexpPrototype'.length; | ||
| 110 | + testRange.end = testRange.start + 'Test'.length; | ||
| 111 | + return [ | ||
| 112 | + fixer.replaceTextRange(node.range, 'Exec'), | ||
| 113 | + fixer.insertTextAfter(node, ' !== null'), | ||
| 114 | + ]; | ||
| 115 | + } | ||
| 116 | + }] | ||
| 117 | + }); | ||
| 118 | + }, | ||
| 119 | + [`${CallExpression}[expression.callee.name=${/^RegExpPrototypeSymbol(Match|MatchAll|Search)$/}]`](node) { | ||
| 120 | + context.report({ | ||
| 121 | + node, | ||
| 122 | + message: node.expression.callee.name + ' looks up the "exec" property of `this` value', | ||
| 123 | + }); | ||
| 124 | + }, | ||
| 125 | + ...createUnsafeStringMethodReport(context, 'StringPrototypeMatch', 'Symbol.match'), | ||
| 126 | + ...createUnsafeStringMethodReport(context, 'StringPrototypeMatchAll', 'Symbol.matchAll'), | ||
| 127 | + ...createUnsafeStringMethodReport(context, 'StringPrototypeReplace', 'Symbol.replace'), | ||
| 128 | + ...createUnsafeStringMethodReport(context, 'StringPrototypeReplaceAll', 'Symbol.replace'), | ||
| 129 | + ...createUnsafeStringMethodReport(context, 'StringPrototypeSearch', 'Symbol.search'), | ||
| 130 | + ...createUnsafeStringMethodReport(context, 'StringPrototypeSplit', 'Symbol.split'), | ||
| 90 | 131 | }; | |
| 91 | 132 | }, | |
| 92 | 133 | }; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments