Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 94912bb

Browse filesBrowse files
aduh95ruyadorno
authored andcommitted
lib: add Promise methods to avoid-prototype-pollution lint rule
PR-URL: #43849 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Paolo Insogna <paolo@cowtech.it>
1 parent a0c5783 commit 94912bb
Copy full SHA for 94912bb

File tree

Expand file treeCollapse file tree

10 files changed

+91
-45
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

10 files changed

+91
-45
lines changed
Open diff view settings
Collapse file

‎lib/internal/debugger/inspect.js‎

Copy file name to clipboardExpand all lines: lib/internal/debugger/inspect.js
+23-16Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ const {
1111
FunctionPrototypeBind,
1212
Number,
1313
Promise,
14-
PromisePrototypeCatch,
1514
PromisePrototypeThen,
1615
PromiseResolve,
1716
Proxy,
@@ -169,12 +168,17 @@ class NodeInspector {
169168
process.once('SIGTERM', exitCodeZero);
170169
process.once('SIGHUP', exitCodeZero);
171170

172-
PromisePrototypeCatch(PromisePrototypeThen(this.run(), async () => {
173-
const repl = await startRepl();
174-
this.repl = repl;
175-
this.repl.on('exit', exitCodeZero);
176-
this.paused = false;
177-
}), (error) => process.nextTick(() => { throw error; }));
171+
(async () => {
172+
try {
173+
await this.run();
174+
const repl = await startRepl();
175+
this.repl = repl;
176+
this.repl.on('exit', exitCodeZero);
177+
this.paused = false;
178+
} catch (error) {
179+
process.nextTick(() => { throw error; });
180+
}
181+
})();
178182
}
179183

180184
suspendReplWhile(fn) {
@@ -183,16 +187,19 @@ class NodeInspector {
183187
}
184188
this.stdin.pause();
185189
this.paused = true;
186-
return PromisePrototypeCatch(PromisePrototypeThen(new Promise((resolve) => {
187-
resolve(fn());
188-
}), () => {
189-
this.paused = false;
190-
if (this.repl) {
191-
this.repl.resume();
192-
this.repl.displayPrompt();
190+
return (async () => {
191+
try {
192+
await fn();
193+
this.paused = false;
194+
if (this.repl) {
195+
this.repl.resume();
196+
this.repl.displayPrompt();
197+
}
198+
this.stdin.resume();
199+
} catch (error) {
200+
process.nextTick(() => { throw error; });
193201
}
194-
this.stdin.resume();
195-
}), (error) => process.nextTick(() => { throw error; }));
202+
})();
196203
}
197204

198205
killChild() {
Collapse file

‎lib/internal/http2/core.js‎

Copy file name to clipboardExpand all lines: lib/internal/http2/core.js
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const {
1717
ObjectDefineProperty,
1818
ObjectPrototypeHasOwnProperty,
1919
Promise,
20-
PromisePrototypeCatch,
20+
PromisePrototypeThen,
2121
Proxy,
2222
ReflectApply,
2323
ReflectGet,
@@ -2456,8 +2456,8 @@ function processHeaders(oldHeaders, options) {
24562456
function onFileUnpipe() {
24572457
const stream = this.sink[kOwner];
24582458
if (stream.ownsFd)
2459-
PromisePrototypeCatch(this.source.close(),
2460-
FunctionPrototypeBind(stream.destroy, stream));
2459+
PromisePrototypeThen(this.source.close(), undefined,
2460+
FunctionPrototypeBind(stream.destroy, stream));
24612461
else
24622462
this.source.releaseFD();
24632463
}
Collapse file

‎lib/internal/main/worker_thread.js‎

Copy file name to clipboardExpand all lines: lib/internal/main/worker_thread.js
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const {
88
ArrayPrototypePushApply,
99
ArrayPrototypeSplice,
1010
ObjectDefineProperty,
11-
PromisePrototypeCatch,
11+
PromisePrototypeThen,
1212
globalThis: { Atomics },
1313
} = primordials;
1414

@@ -185,7 +185,7 @@ port.on('message', (message) => {
185185
evalScript(name, filename);
186186
} else if (doEval === 'module') {
187187
const { evalModule } = require('internal/process/execution');
188-
PromisePrototypeCatch(evalModule(filename), (e) => {
188+
PromisePrototypeThen(evalModule(filename), undefined, (e) => {
189189
workerOnGlobalUncaughtException(e, true);
190190
});
191191
} else {
Collapse file

‎lib/internal/modules/esm/module_job.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/module_job.js
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const {
88
ObjectCreate,
99
ObjectSetPrototypeOf,
1010
PromiseResolve,
11-
PromisePrototypeCatch,
11+
PromisePrototypeThen,
1212
ReflectApply,
1313
RegExpPrototypeExec,
1414
RegExpPrototypeSymbolReplace,
@@ -88,7 +88,7 @@ class ModuleJob {
8888
this.linked = link();
8989
// This promise is awaited later anyway, so silence
9090
// 'unhandled rejection' warnings.
91-
PromisePrototypeCatch(this.linked, noop);
91+
PromisePrototypeThen(this.linked, undefined, noop);
9292

9393
// instantiated == deep dependency jobs wrappers are instantiated,
9494
// and module wrapper is instantiated.
Collapse file

‎lib/internal/per_context/primordials.js‎

Copy file name to clipboardExpand all lines: lib/internal/per_context/primordials.js
-3Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,6 @@ const SafePromise = makeSafe(
409409
}
410410
);
411411

412-
primordials.PromisePrototypeCatch = (thisPromise, onRejected) =>
413-
PromisePrototypeThen(thisPromise, undefined, onRejected);
414-
415412
/**
416413
* Attaches a callback that is invoked when the Promise is settled (fulfilled or
417414
* rejected). The resolved value cannot be modified from the callback.
Collapse file

‎lib/internal/streams/operators.js‎

Copy file name to clipboardExpand all lines: lib/internal/streams/operators.js
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const {
2525
NumberIsNaN,
2626
Promise,
2727
PromiseReject,
28-
PromisePrototypeCatch,
28+
PromisePrototypeThen,
2929
Symbol,
3030
} = primordials;
3131

@@ -113,7 +113,7 @@ function map(fn, options) {
113113
queue.push(kEof);
114114
} catch (err) {
115115
const val = PromiseReject(err);
116-
PromisePrototypeCatch(val, onDone);
116+
PromisePrototypeThen(val, undefined, onDone);
117117
queue.push(val);
118118
} finally {
119119
done = true;
Collapse file

‎lib/internal/webstreams/readablestream.js‎

Copy file name to clipboardExpand all lines: lib/internal/webstreams/readablestream.js
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ const {
1616
ObjectDefineProperties,
1717
ObjectSetPrototypeOf,
1818
Promise,
19-
PromisePrototypeCatch,
2019
PromisePrototypeThen,
2120
PromiseResolve,
2221
PromiseReject,
@@ -1334,7 +1333,7 @@ function readableStreamPipeTo(
13341333
if (stream[kState].state === 'errored')
13351334
action(stream[kState].storedError);
13361335
else
1337-
PromisePrototypeCatch(promise, action);
1336+
PromisePrototypeThen(promise, undefined, action);
13381337
}
13391338

13401339
function watchClosed(stream, promise, action) {
@@ -1503,8 +1502,9 @@ function readableStreamTee(stream, cloneForBranch2) {
15031502
branch2 =
15041503
createTeeReadableStream(nonOpStart, pullAlgorithm, cancel2Algorithm);
15051504

1506-
PromisePrototypeCatch(
1505+
PromisePrototypeThen(
15071506
reader[kState].close.promise,
1507+
undefined,
15081508
(error) => {
15091509
readableStreamDefaultControllerError(branch1[kState].controller, error);
15101510
readableStreamDefaultControllerError(branch2[kState].controller, error);
Collapse file

‎test/parallel/test-eslint-avoid-prototype-pollution.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-eslint-avoid-prototype-pollution.js
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,5 +203,25 @@ new RuleTester({
203203
code: 'new Proxy({}, { ...{ __proto__: null } })',
204204
errors: [{ message: /null-prototype/ }]
205205
},
206+
{
207+
code: 'PromisePrototypeCatch(promise, ()=>{})',
208+
errors: [{ message: /\bPromisePrototypeThen\b/ }]
209+
},
210+
{
211+
code: 'PromiseAll([])',
212+
errors: [{ message: /\bSafePromiseAll\b/ }]
213+
},
214+
{
215+
code: 'PromiseAllSettled([])',
216+
errors: [{ message: /\bSafePromiseAllSettled\b/ }]
217+
},
218+
{
219+
code: 'PromiseAny([])',
220+
errors: [{ message: /\bSafePromiseAny\b/ }]
221+
},
222+
{
223+
code: 'PromiseRace([])',
224+
errors: [{ message: /\bSafePromiseRace\b/ }]
225+
},
206226
]
207227
});
Collapse file

‎test/parallel/test-primordials-promise.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-primordials-promise.js
+8-10Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const common = require('../common');
55
const assert = require('assert');
66

77
const {
8-
PromisePrototypeCatch,
98
PromisePrototypeThen,
109
SafePromiseAll,
1110
SafePromiseAllSettled,
@@ -14,16 +13,15 @@ const {
1413
SafePromiseRace,
1514
} = require('internal/test/binding').primordials;
1615

17-
Array.prototype[Symbol.iterator] = common.mustNotCall();
18-
Promise.all = common.mustNotCall();
19-
Promise.allSettled = common.mustNotCall();
20-
Promise.any = common.mustNotCall();
21-
Promise.race = common.mustNotCall();
22-
Promise.prototype.catch = common.mustNotCall();
23-
Promise.prototype.finally = common.mustNotCall();
24-
Promise.prototype.then = common.mustNotCall();
16+
Array.prototype[Symbol.iterator] = common.mustNotCall('%Array.prototype%[@@iterator]');
17+
Promise.all = common.mustNotCall('%Promise%.all');
18+
Promise.allSettled = common.mustNotCall('%Promise%.allSettled');
19+
Promise.any = common.mustNotCall('%Promise%.any');
20+
Promise.race = common.mustNotCall('%Promise%.race');
21+
Promise.prototype.catch = common.mustNotCall('%Promise.prototype%.catch');
22+
Promise.prototype.finally = common.mustNotCall('%Promise.prototype%.finally');
23+
Promise.prototype.then = common.mustNotCall('%Promise.prototype%.then');
2524

26-
assertIsPromise(PromisePrototypeCatch(Promise.reject(), common.mustCall()));
2725
assertIsPromise(PromisePrototypeThen(test(), common.mustCall()));
2826
assertIsPromise(SafePromisePrototypeFinally(test(), common.mustCall()));
2927

Collapse file

‎tools/eslint-rules/avoid-prototype-pollution.js‎

Copy file name to clipboardExpand all lines: tools/eslint-rules/avoid-prototype-pollution.js
+28-4Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ module.exports = {
109109
testRange.start = testRange.start + 'RegexpPrototype'.length;
110110
testRange.end = testRange.start + 'Test'.length;
111111
return [
112-
fixer.replaceTextRange(node.range, 'Exec'),
112+
fixer.replaceTextRange(testRange, 'Exec'),
113113
fixer.insertTextAfter(node, ' !== null'),
114114
];
115115
}
116-
}]
116+
}],
117117
});
118118
},
119119
[`${CallExpression}[expression.callee.name=${/^RegExpPrototypeSymbol(Match|MatchAll|Search)$/}]`](node) {
@@ -142,9 +142,33 @@ module.exports = {
142142
}
143143
context.report({
144144
node,
145-
message: 'Proxy handler must be a null-prototype object'
145+
message: 'Proxy handler must be a null-prototype object',
146146
});
147-
}
147+
},
148+
149+
[`${CallExpression}[expression.callee.name=PromisePrototypeCatch]`](node) {
150+
context.report({
151+
node,
152+
message: '%Promise.prototype.catch% look up the `then` property of ' +
153+
'the `this` argument, use PromisePrototypeThen instead',
154+
});
155+
},
156+
157+
[`${CallExpression}[expression.callee.name=PromisePrototypeFinally]`](node) {
158+
context.report({
159+
node,
160+
message: '%Promise.prototype.finally% look up the `then` property of ' +
161+
'the `this` argument, use SafePromisePrototypeFinally or ' +
162+
'try/finally instead',
163+
});
164+
},
165+
166+
[`${CallExpression}[expression.callee.name=${/^Promise(All(Settled)?|Any|Race)/}]`](node) {
167+
context.report({
168+
node,
169+
message: `Use Safe${node.expression.callee.name} instead of ${node.expression.callee.name}`,
170+
});
171+
},
148172
};
149173
},
150174
};

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.