JS: reformulate js/server-crash. Support promises and shorter paths.

This commit is contained in:
Esben Sparre Andreasen
2021-01-13 15:46:34 +01:00
parent 1bc7d68a50
commit 3015dcd310
3 changed files with 302 additions and 191 deletions

View File

@@ -1,48 +1,65 @@
edges
| server-crash.js:5:1:9:1 | functio ... });\\n} | server-crash.js:49:3:49:16 | indirection1() |
| server-crash.js:7:5:7:14 | throw err; | server-crash.js:6:28:8:3 | (err, x ... OK\\n } |
| server-crash.js:10:1:12:1 | functio ... OT OK\\n} | server-crash.js:51:5:51:18 | indirection2() |
| server-crash.js:11:3:11:11 | throw 42; | server-crash.js:10:1:12:1 | functio ... OT OK\\n} |
| server-crash.js:13:1:19:1 | functio ... e) {}\\n} | server-crash.js:54:3:54:16 | indirection3() |
| server-crash.js:16:7:16:16 | throw err; | server-crash.js:15:30:17:5 | (err, x ... K\\n } |
| server-crash.js:20:1:22:1 | functio ... aller\\n} | server-crash.js:56:5:56:18 | indirection4() |
| server-crash.js:23:1:25:1 | functio ... n6();\\n} | server-crash.js:58:3:58:16 | indirection5() |
| server-crash.js:24:3:24:16 | indirection6() | server-crash.js:23:1:25:1 | functio ... n6();\\n} |
| server-crash.js:26:1:30:1 | functio ... });\\n} | server-crash.js:24:3:24:16 | indirection6() |
| server-crash.js:28:5:28:14 | throw err; | server-crash.js:27:28:29:3 | (err, x ... OK\\n } |
| server-crash.js:33:5:33:14 | throw err; | server-crash.js:32:28:34:3 | (err, x ... OK\\n } |
| server-crash.js:49:3:49:16 | indirection1() | server-crash.js:31:25:73:1 | (req, r ... });\\n} |
| server-crash.js:51:5:51:18 | indirection2() | server-crash.js:50:28:52:3 | (err, x ... ();\\n } |
| server-crash.js:54:3:54:16 | indirection3() | server-crash.js:31:25:73:1 | (req, r ... });\\n} |
| server-crash.js:56:5:56:18 | indirection4() | server-crash.js:31:25:73:1 | (req, r ... });\\n} |
| server-crash.js:58:3:58:16 | indirection5() | server-crash.js:31:25:73:1 | (req, r ... });\\n} |
| server-crash.js:15:5:15:14 | throw err; | server-crash.js:14:23:16:3 | (err, x ... OK\\n } |
| server-crash.js:18:1:20:1 | functio ... OT OK\\n} | server-crash.js:59:5:59:18 | indirection2() |
| server-crash.js:19:3:19:11 | throw 42; | server-crash.js:18:1:20:1 | functio ... OT OK\\n} |
| server-crash.js:24:7:24:16 | throw err; | server-crash.js:23:25:25:5 | (err, x ... K\\n } |
| server-crash.js:36:5:36:14 | throw err; | server-crash.js:35:23:37:3 | (err, x ... OK\\n } |
| server-crash.js:41:5:41:14 | throw err; | server-crash.js:40:23:42:3 | (err, x ... OK\\n } |
| server-crash.js:59:5:59:18 | indirection2() | server-crash.js:58:23:60:3 | (err, x ... ();\\n } |
| server-crash.js:88:5:88:14 | throw err; | server-crash.js:87:23:89:3 | (err, x ... OK\\n } |
| server-crash.js:94:5:94:14 | throw "e"; | server-crash.js:93:22:95:3 | () => { ... OK\\n } |
| server-crash.js:102:7:102:16 | throw "e"; | server-crash.js:101:24:103:5 | () => { ... K\\n } |
| server-crash.js:109:9:109:18 | throw "e"; | server-crash.js:108:26:110:7 | () => { ... } |
| server-crash.js:117:9:117:18 | throw "e"; | server-crash.js:116:26:118:7 | () => { ... } |
| server-crash.js:131:7:131:16 | throw err; | server-crash.js:130:25:132:5 | (err, x ... K\\n } |
| server-crash.js:152:3:154:3 | functio ... OK\\n } | server-crash.js:157:5:157:16 | throwError() |
| server-crash.js:152:3:154:3 | functio ... OK\\n } | server-crash.js:160:5:160:16 | throwError() |
| server-crash.js:152:3:154:3 | functio ... OK\\n } | server-crash.js:164:3:164:14 | throwError() |
| server-crash.js:153:5:153:22 | throw new Error(); | server-crash.js:152:3:154:3 | functio ... OK\\n } |
| server-crash.js:153:11:153:21 | new Error() | server-crash.js:152:3:154:3 | functio ... OK\\n } |
| server-crash.js:157:5:157:16 | throwError() | server-crash.js:156:3:158:3 | functio ... ath\\n } |
nodes
| server-crash.js:5:1:9:1 | functio ... });\\n} |
| server-crash.js:6:28:8:3 | (err, x ... OK\\n } |
| server-crash.js:7:5:7:14 | throw err; |
| server-crash.js:10:1:12:1 | functio ... OT OK\\n} |
| server-crash.js:11:3:11:11 | throw 42; |
| server-crash.js:13:1:19:1 | functio ... e) {}\\n} |
| server-crash.js:15:30:17:5 | (err, x ... K\\n } |
| server-crash.js:16:7:16:16 | throw err; |
| server-crash.js:20:1:22:1 | functio ... aller\\n} |
| server-crash.js:23:1:25:1 | functio ... n6();\\n} |
| server-crash.js:24:3:24:16 | indirection6() |
| server-crash.js:26:1:30:1 | functio ... });\\n} |
| server-crash.js:27:28:29:3 | (err, x ... OK\\n } |
| server-crash.js:28:5:28:14 | throw err; |
| server-crash.js:31:25:73:1 | (req, r ... });\\n} |
| server-crash.js:32:28:34:3 | (err, x ... OK\\n } |
| server-crash.js:33:5:33:14 | throw err; |
| server-crash.js:49:3:49:16 | indirection1() |
| server-crash.js:50:28:52:3 | (err, x ... ();\\n } |
| server-crash.js:51:5:51:18 | indirection2() |
| server-crash.js:54:3:54:16 | indirection3() |
| server-crash.js:56:5:56:18 | indirection4() |
| server-crash.js:58:3:58:16 | indirection5() |
| server-crash.js:14:23:16:3 | (err, x ... OK\\n } |
| server-crash.js:15:5:15:14 | throw err; |
| server-crash.js:18:1:20:1 | functio ... OT OK\\n} |
| server-crash.js:19:3:19:11 | throw 42; |
| server-crash.js:23:25:25:5 | (err, x ... K\\n } |
| server-crash.js:24:7:24:16 | throw err; |
| server-crash.js:35:23:37:3 | (err, x ... OK\\n } |
| server-crash.js:36:5:36:14 | throw err; |
| server-crash.js:40:23:42:3 | (err, x ... OK\\n } |
| server-crash.js:41:5:41:14 | throw err; |
| server-crash.js:58:23:60:3 | (err, x ... ();\\n } |
| server-crash.js:59:5:59:18 | indirection2() |
| server-crash.js:87:23:89:3 | (err, x ... OK\\n } |
| server-crash.js:88:5:88:14 | throw err; |
| server-crash.js:93:22:95:3 | () => { ... OK\\n } |
| server-crash.js:94:5:94:14 | throw "e"; |
| server-crash.js:101:24:103:5 | () => { ... K\\n } |
| server-crash.js:102:7:102:16 | throw "e"; |
| server-crash.js:108:26:110:7 | () => { ... } |
| server-crash.js:109:9:109:18 | throw "e"; |
| server-crash.js:116:26:118:7 | () => { ... } |
| server-crash.js:117:9:117:18 | throw "e"; |
| server-crash.js:130:25:132:5 | (err, x ... K\\n } |
| server-crash.js:131:7:131:16 | throw err; |
| server-crash.js:152:3:154:3 | functio ... OK\\n } |
| server-crash.js:153:5:153:22 | throw new Error(); |
| server-crash.js:153:11:153:21 | new Error() |
| server-crash.js:156:3:158:3 | functio ... ath\\n } |
| server-crash.js:157:5:157:16 | throwError() |
| server-crash.js:160:5:160:16 | throwError() |
| server-crash.js:164:3:164:14 | throwError() |
#select
| server-crash.js:7:5:7:14 | throw err; | server-crash.js:7:5:7:14 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:6:28:8:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler |
| server-crash.js:11:3:11:11 | throw 42; | server-crash.js:11:3:11:11 | throw 42; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:50:28:52:3 | (err, x ... ();\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler |
| server-crash.js:16:7:16:16 | throw err; | server-crash.js:16:7:16:16 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:15:30:17:5 | (err, x ... K\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler |
| server-crash.js:28:5:28:14 | throw err; | server-crash.js:28:5:28:14 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:27:28:29:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler |
| server-crash.js:33:5:33:14 | throw err; | server-crash.js:33:5:33:14 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:32:28:34:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler |
| server-crash.js:15:5:15:14 | throw err; | server-crash.js:15:5:15:14 | throw err; | server-crash.js:14:23:16:3 | (err, x ... OK\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:14:23:16:3 | (err, x ... OK\\n } | asynchronous callback |
| server-crash.js:19:3:19:11 | throw 42; | server-crash.js:19:3:19:11 | throw 42; | server-crash.js:58:23:60:3 | (err, x ... ();\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:58:23:60:3 | (err, x ... ();\\n } | asynchronous callback |
| server-crash.js:24:7:24:16 | throw err; | server-crash.js:24:7:24:16 | throw err; | server-crash.js:23:25:25:5 | (err, x ... K\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:23:25:25:5 | (err, x ... K\\n } | asynchronous callback |
| server-crash.js:36:5:36:14 | throw err; | server-crash.js:36:5:36:14 | throw err; | server-crash.js:35:23:37:3 | (err, x ... OK\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:35:23:37:3 | (err, x ... OK\\n } | asynchronous callback |
| server-crash.js:41:5:41:14 | throw err; | server-crash.js:41:5:41:14 | throw err; | server-crash.js:40:23:42:3 | (err, x ... OK\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:40:23:42:3 | (err, x ... OK\\n } | asynchronous callback |
| server-crash.js:88:5:88:14 | throw err; | server-crash.js:88:5:88:14 | throw err; | server-crash.js:87:23:89:3 | (err, x ... OK\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:87:23:89:3 | (err, x ... OK\\n } | asynchronous callback |
| server-crash.js:94:5:94:14 | throw "e"; | server-crash.js:94:5:94:14 | throw "e"; | server-crash.js:93:22:95:3 | () => { ... OK\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:92:31:120:1 | (req, r ... });\\n} | this route handler | server-crash.js:93:22:95:3 | () => { ... OK\\n } | asynchronous callback |
| server-crash.js:102:7:102:16 | throw "e"; | server-crash.js:102:7:102:16 | throw "e"; | server-crash.js:101:24:103:5 | () => { ... K\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:92:31:120:1 | (req, r ... });\\n} | this route handler | server-crash.js:101:24:103:5 | () => { ... K\\n } | asynchronous callback |
| server-crash.js:109:9:109:18 | throw "e"; | server-crash.js:109:9:109:18 | throw "e"; | server-crash.js:108:26:110:7 | () => { ... } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:92:31:120:1 | (req, r ... });\\n} | this route handler | server-crash.js:108:26:110:7 | () => { ... } | asynchronous callback |
| server-crash.js:117:9:117:18 | throw "e"; | server-crash.js:117:9:117:18 | throw "e"; | server-crash.js:116:26:118:7 | () => { ... } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:92:31:120:1 | (req, r ... });\\n} | this route handler | server-crash.js:116:26:118:7 | () => { ... } | asynchronous callback |
| server-crash.js:131:7:131:16 | throw err; | server-crash.js:131:7:131:16 | throw err; | server-crash.js:130:25:132:5 | (err, x ... K\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:128:32:135:1 | async ( ... un();\\n} | this route handler | server-crash.js:130:25:132:5 | (err, x ... K\\n } | asynchronous callback |
| server-crash.js:153:5:153:22 | throw new Error(); | server-crash.js:153:5:153:22 | throw new Error(); | server-crash.js:156:3:158:3 | functio ... ath\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:151:40:166:1 | (req, r ... nc();\\n} | this route handler | server-crash.js:161:16:161:17 | cb | asynchronous callback |

View File

@@ -1,9 +1,17 @@
const express = require("express");
const app = express();
const fs = require("fs");
const EventEmitter = require("events");
const http = require("http");
const port = 12000;
let server = app.listen(port, () =>
// for manual testing of the fickle node.js runtime
console.log(`Example app listening on port ${port}!`)
);
function indirection1() {
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
throw err; // NOT OK
});
}
@@ -12,7 +20,7 @@ function indirection2() {
}
function indirection3() {
try {
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
throw err; // NOT OK
});
} catch (e) {}
@@ -24,30 +32,30 @@ function indirection5() {
indirection6();
}
function indirection6() {
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
throw err; // NOT OK
});
}
app.get("/async-throw", (req, res) => {
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
throw err; // NOT OK
});
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
try {
throw err; // OK: guarded throw
} catch (e) {}
});
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
res.setHeader("reflected", req.query.header); // NOT OK [INCONSISTENCY]
});
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
try {
res.setHeader("reflected", req.query.header); // OK: guarded call
} catch (e) {}
});
indirection1();
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
indirection2();
});
@@ -57,17 +65,17 @@ app.get("/async-throw", (req, res) => {
} catch (e) {}
indirection5();
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
req.query.foo; // OK
});
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
req.query.foo.toString(); // OK
});
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
req.query.foo.bar; // NOT OK [INCONSISTENCY]: need to add property reads as sinks
});
fs.readFile("/WHATEVER", (err, x) => {
fs.readFile("/foo", (err, x) => {
res.setHeader("reflected", unknown); // OK
});
@@ -80,3 +88,79 @@ function indirection7() {
throw err; // NOT OK
});
}
app.get("/async-throw-again", (req, res) => {
fs.readFile("foo", () => {
throw "e"; // NOT OK
});
fs.readFileSync("foo", () => {
throw "e"; // OK (does not take callbacks at all)
});
// can nest async calls (and only warns about the inner one)
fs.readFile("foo", () => {
fs.readFile("bar", () => {
throw "e"; // NOT OK
});
});
fs.readFile("foo", () => {
// can not catch async exceptions
try {
fs.readFile("bar", () => {
throw "e"; // NOT OK
});
} catch (e) {}
});
// can mix sync/async calls
fs.readFile("foo", () => {
(() =>
fs.readFile("bar", () => {
throw "e"; // NOT OK
}))();
});
});
app.get("/throw-in-promise-1", async (req, res) => {
async function fun() {
throw new Error(); // OK, requires `node --unhandled-rejections=strict ...` to terminate the process
}
await fun();
});
app.get("/throw-in-promise-2", async (req, res) => {
async function fun() {
fs.readFile("/foo", (err, x) => {
throw err; // NOT OK
});
}
await fun();
});
app.get("/throw-in-promise-3", async (req, res) => {
fs.readFile("/foo", async (err, x) => {
throw err; // OK, requires `node --unhandled-rejections=strict ...` to terminate the process
});
});
app.get("/throw-in-event-emitter", async (req, res) => {
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on("event", () => {
throw new Error(); // OK, requires `node --unhandled-rejections=strict ...` to terminate the process
});
myEmitter.emit("event");
});
app.get("/throw-with-ambiguous-paths", (req, res) => {
function throwError() {
throw new Error(); // NOT OK
}
function cb() {
throwError(); // on path
}
function withAsync() {
throwError(); // not on path
fs.stat(X, cb);
}
throwError(); // not on path
withAsync();
});