diff --git a/change-notes/1.25/analysis-javascript.md b/change-notes/1.25/analysis-javascript.md
index 24a1d1274d3..fe23ad561e7 100644
--- a/change-notes/1.25/analysis-javascript.md
+++ b/change-notes/1.25/analysis-javascript.md
@@ -37,6 +37,7 @@
| Unsafe expansion of self-closing HTML tag (`js/unsafe-html-expansion`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights potential XSS vulnerabilities caused by unsafe expansion of self-closing HTML tags. |
| Unsafe shell command constructed from library input (`js/shell-command-constructed-from-input`) | correctness, security, external/cwe/cwe-078, external/cwe/cwe-088 | Highlights potential command injections due to a shell command being constructed from library inputs. Results are shown on LGTM by default. |
| Improper code sanitization (`js/bad-code-sanitization`) | security, external/cwe/cwe-094, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights string concatenation where code is constructed without proper sanitization. Results are shown on LGTM by default. |
+| Resource exhaustion (`js/resource-exhaustion`) | security, external/cwe/cwe-770 | Highlights operations that may cause the resources of the application to be exhausted. Results are shown on LGTM by default. |
## Changes to existing queries
diff --git a/javascript/config/suites/javascript/security b/javascript/config/suites/javascript/security
index 5eb02bc148b..65bea14986e 100644
--- a/javascript/config/suites/javascript/security
+++ b/javascript/config/suites/javascript/security
@@ -44,6 +44,7 @@
+ semmlecode-javascript-queries/Security/CWE-730/RegExpInjection.ql: /Security/CWE/CWE-730
+ semmlecode-javascript-queries/Security/CWE-754/UnvalidatedDynamicMethodCall.ql: /Security/CWE/CWE-754
+ semmlecode-javascript-queries/Security/CWE-770/MissingRateLimiting.ql: /Security/CWE/CWE-770
++ semmlecode-javascript-queries/Security/CWE-770/ResourceExhaustion.ql: /Security/CWE/CWE-770
+ semmlecode-javascript-queries/Security/CWE-776/XmlBomb.ql: /Security/CWE/CWE-776
+ semmlecode-javascript-queries/Security/CWE-798/HardcodedCredentials.ql: /Security/CWE/CWE-798
+ semmlecode-javascript-queries/Security/CWE-807/ConditionalBypass.ql: /Security/CWE/CWE-807
diff --git a/javascript/ql/src/Security/CWE-770/MemoryExhaustion.qhelp b/javascript/ql/src/Security/CWE-770/MemoryExhaustion.qhelp
deleted file mode 100644
index c3258c4e5f1..00000000000
--- a/javascript/ql/src/Security/CWE-770/MemoryExhaustion.qhelp
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/javascript/ql/src/Security/CWE-770/MemoryExhaustion.ql b/javascript/ql/src/Security/CWE-770/MemoryExhaustion.ql
deleted file mode 100644
index e593fd83ee4..00000000000
--- a/javascript/ql/src/Security/CWE-770/MemoryExhaustion.ql
+++ /dev/null
@@ -1,225 +0,0 @@
-/**
- * @name Memory exhaustion
- * @description Allocating objects with user-controlled sizes
- * can cause memory exhaustion.
- * @kind path-problem
- * @problem.severity warning
- * @id js/memory-exhaustion
- * @precision high
- * @tags security
- * external/cwe/cwe-770
- */
-
-import javascript
-import DataFlow::PathGraph
-private import semmle.javascript.dataflow.InferredTypes
-import semmle.javascript.security.dataflow.LoopBoundInjectionCustomizations
-
-/**
- * A data flow source for memory exhaustion vulnerabilities.
- */
-abstract class Source extends DataFlow::Node {
- /** Gets a flow label denoting the type of value for which this is a source. */
- DataFlow::FlowLabel getAFlowLabel() { result.isTaint() }
-}
-
-/**
- * A data flow sink for memory exhaustion vulnerabilities.
- */
-abstract class Sink extends DataFlow::Node {
- /** Gets a flow label denoting the type of value for which this is a sink. */
- DataFlow::FlowLabel getAFlowLabel() { result instanceof Label::Number }
-}
-
-/**
- * A data flow sanitizer for memory exhaustion vulnerabilities.
- */
-abstract class Sanitizer extends DataFlow::Node { }
-
-/**
- * Provides data flow labels for memory exhaustion vulnerabilities.
- */
-module Label {
- /**
- * A number data flow label.
- */
- class Number extends DataFlow::FlowLabel {
- Number() { this = "number" }
- }
-}
-
-/**
- * A data flow configuration for memory exhaustion vulnerabilities.
- */
-class Configuration extends TaintTracking::Configuration {
- Configuration() { this = "MemoryExhaustion" }
-
- override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
- source.(Source).getAFlowLabel() = label
- }
-
- override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
- sink.(Sink).getAFlowLabel() = label
- }
-
- override predicate isAdditionalFlowStep(
- DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel,
- DataFlow::FlowLabel dstlabel
- ) {
- dstlabel instanceof Label::Number and
- isNumericFlowStep(src, dst)
- or
- // reuse taint steps
- super.isAdditionalFlowStep(src, dst) and
- not dst.asExpr() instanceof AddExpr and
- if dst.(DataFlow::MethodCallNode).calls(src, "toString")
- then dstlabel.isTaint()
- else srclabel = dstlabel
- }
-
- override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
- guard instanceof LoopBoundInjection::LengthCheckSanitizerGuard or
- guard instanceof UpperBoundsCheckSanitizerGuard or
- guard instanceof TypeTestGuard
- }
-}
-
-predicate isNumericFlowStep(DataFlow::Node src, DataFlow::Node dst) {
- // steps that introduce or preserve a number
- dst.(DataFlow::PropRead).accesses(src, ["length", "size"])
- or
- exists(DataFlow::CallNode c |
- c = dst and
- src = c.getAnArgument()
- |
- c = DataFlow::globalVarRef("Math").getAMemberCall(_) or
- c = DataFlow::globalVarRef(["Number", "parseInt", "parseFloat"]).getACall()
- )
- or
- exists(Expr dstExpr, Expr srcExpr |
- dstExpr = dst.asExpr() and
- srcExpr = src.asExpr()
- |
- dstExpr.(BinaryExpr).getAnOperand() = srcExpr and
- not dstExpr instanceof AddExpr
- or
- dstExpr.(PlusExpr).getOperand() = srcExpr
- )
-}
-
-/**
- * A sanitizer that blocks taint flow if the size of a number is limited.
- */
-class UpperBoundsCheckSanitizerGuard extends TaintTracking::LabeledSanitizerGuardNode,
- DataFlow::ValueNode {
- override RelationalComparison astNode;
-
- override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) {
- label instanceof Label::Number and
- (
- true = outcome and
- e = astNode.getLesserOperand()
- or
- false = outcome and
- e = astNode.getGreaterOperand()
- )
- }
-}
-
-/**
- * A test of form `typeof x === "something"`, preventing `x` from being a number in some cases.
- */
-private class TypeTestGuard extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode {
- override EqualityTest astNode;
- TypeofExpr typeof;
- boolean polarity;
-
- TypeTestGuard() {
- astNode.getAnOperand() = typeof and
- (
- // typeof x === "number" sanitizes `x` when it evaluates to false
- astNode.getAnOperand().getStringValue() = "number" and
- polarity = astNode.getPolarity().booleanNot()
- or
- // typeof x === "string" sanitizes `x` when it evaluates to true
- astNode.getAnOperand().getStringValue() != "number" and
- polarity = astNode.getPolarity()
- )
- }
-
- override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) {
- polarity = outcome and
- e = typeof.getOperand() and
- label instanceof Label::Number
- }
-}
-
-/** A source of remote user input, considered as a data flow source for memory exhaustion vulnerabilities. */
-class RemoteFlowSourceAsSource extends Source {
- RemoteFlowSourceAsSource() { this instanceof RemoteFlowSource }
-}
-
-/**
- * A node that determines the size of a buffer, considered as a data flow sink for memory exhaustion vulnerabilities.
- */
-class BufferSizeSink extends Sink {
- BufferSizeSink() {
- exists(DataFlow::SourceNode clazz, DataFlow::InvokeNode invk, int index |
- clazz = DataFlow::globalVarRef("Buffer") and this = invk.getArgument(index)
- |
- exists(string name |
- invk = clazz.getAMemberCall(name) and
- (
- name = "from" and index = 2
- or
- name = ["alloc", "allocUnsafe", "allocUnsafeSlow"] and index = 0
- )
- )
- or
- invk = clazz.getAnInvocation() and
- (
- invk.getNumArgument() = 1 and
- index = 0
- or
- invk.getNumArgument() = 3 and index = 2
- )
- )
- or
- this = DataFlow::globalVarRef("SlowBuffer").getAnInstantiation().getArgument(0)
- }
-}
-
-/**
- * A node that determines the size of an array, considered as a data flow sink for memory exhaustion vulnerabilities.
- */
-class DenseArraySizeSink extends Sink {
- DenseArraySizeSink() {
- // Arrays are sparse by default, so we must also look at how the array is used
- exists(DataFlow::ArrayConstructorInvokeNode instance |
- this = instance.getArgument(0) and
- instance.getNumArgument() = 1
- |
- exists(instance.getAMethodCall(["map", "fill", "join", "toString"])) or
- instance.flowsToExpr(any(AddExpr p).getAnOperand())
- )
- }
-}
-
-/**
- * A node that determines the repetitions of a string, considered as a data flow sink for memory exhaustion vulnerabilities.
- */
-class StringRepetitionSink extends Sink {
- StringRepetitionSink() {
- exists(DataFlow::MethodCallNode repeat |
- repeat.getMethodName() = "repeat" and
- this = repeat.getArgument(0)
- )
- }
-
- override DataFlow::FlowLabel getAFlowLabel() { any() }
-}
-
-from Configuration dataflow, DataFlow::PathNode source, DataFlow::PathNode sink
-where dataflow.hasFlowPath(source, sink)
-select sink, source, sink, "This allocates an object with a user-controlled size from $@.", source,
- "here"
diff --git a/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp b/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp
new file mode 100644
index 00000000000..e476c02f193
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp
@@ -0,0 +1,82 @@
+
+
+
+
+
+ Applications are constrained by how many resources they can make use
+ of, failing to respect these constraints may cause the application to
+ be unresponsive or crash. It is therefore be problematic if attackers
+ can control the sizes or lifetimes of allocated objects.
+
+
+
+
+
+ Ensure that attackers can not control object sizes and their
+ lifetimes. If object sizes and lifetimes must be controlled by
+ external parties, ensure to restrict the object sizes and lifetimes to
+ be within accptable ranges.
+
+
+
+
+
+ The following example allocates a buffer with a user-controlled
+ size.
+
+
+
+ This is problematic since an attacker can choose a size
+ that makes the application run out of memory. Even worse, in older
+ versions of Node.js, this could leak confidential memory.
+
+ To prevent such attacks, limit the buffer size:
+
+
+
+
+
+
+
+ As another example, consider an application that allocates an
+ array with a user-controlled size, and then fills it with values:
+
+
+
+ The allocation of the array itself is not problematic since arrays are
+ allocated sparsely, but the subsequent filling of the array will take
+ a long time, causing the application to be unresponsive, or even run
+ out of memory.
+
+ Again, a limit on the size will prevent the attack:
+
+
+
+
+
+
+
+ Finally, the following example lets a user choose delay after
+ which a function is executed:
+
+
+
+ This is problematic because a large delay essentially makes the
+ application wait indefinitely before executing the function. Repeated
+ registrations of such delays will therefore use up all of the memory
+ in the application.
+
+ Again, a limit on the delay will prevent the attack:
+
+
+
+
+
+
+
+
+
+
+
diff --git a/javascript/ql/src/Security/CWE-770/ResourceExhaustion.ql b/javascript/ql/src/Security/CWE-770/ResourceExhaustion.ql
new file mode 100644
index 00000000000..adb8663085e
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-770/ResourceExhaustion.ql
@@ -0,0 +1,20 @@
+/**
+ * @name Resource exhaustion
+ * @description Allocating objects or timers with user-controlled
+ * sizes or durations can cause resource exhaustion.
+ * @kind path-problem
+ * @problem.severity warning
+ * @id js/resource-exhaustion
+ * @precision high
+ * @tags security
+ * external/cwe/cwe-770
+ */
+
+import javascript
+import DataFlow::PathGraph
+import semmle.javascript.security.dataflow.ResourceExhaustion::ResourceExhaustion
+
+from Configuration dataflow, DataFlow::PathNode source, DataFlow::PathNode sink
+where dataflow.hasFlowPath(source, sink)
+select sink, source, sink, sink.getNode().(Sink).getProblemDescription() + " from $@.", source,
+ "here"
diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js
new file mode 100644
index 00000000000..e7c6be16953
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js
@@ -0,0 +1,10 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var size = parseInt(url.parse(req.url, true).query.size);
+
+ let dogs = new Array(size).fill(x => "dog"); // BAD
+
+ // ... use the dogs
+});
diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js
new file mode 100644
index 00000000000..f7c88129264
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js
@@ -0,0 +1,16 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var size = parseInt(url.parse(req.url, true).query.size);
+
+ if (size > 1024) {
+ res.statusCode = 400;
+ res.end("Bad request.");
+ return;
+ }
+
+ let dogs = new Array(size).fill(x => "dog"); // GOOD
+
+ // ... use the dogs
+});
diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js
new file mode 100644
index 00000000000..d821901e818
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js
@@ -0,0 +1,10 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var size = parseInt(url.parse(req.url, true).query.size);
+
+ let buffer = Buffer.alloc(size); // BAD
+
+ // ... use the buffer
+});
diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js
new file mode 100644
index 00000000000..8d9f9b0839f
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js
@@ -0,0 +1,16 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var size = parseInt(url.parse(req.url, true).query.size);
+
+ if (size > 1024) {
+ res.statusCode = 400;
+ res.end("Bad request.");
+ return;
+ }
+
+ let buffer = Buffer.alloc(size); // GOOD
+
+ // ... use the buffer
+});
diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout.js
new file mode 100644
index 00000000000..1718509534b
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout.js
@@ -0,0 +1,9 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var delay = parseInt(url.parse(req.url, true).query.delay);
+
+ setTimeout(f, delay); // BAD
+
+});
diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js
new file mode 100644
index 00000000000..2f5a614e3d7
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js
@@ -0,0 +1,15 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var delay = parseInt(url.parse(req.url, true).query.delay);
+
+ if (delay > 1000) {
+ res.statusCode = 400;
+ res.end("Bad request.");
+ return;
+ }
+
+ setTimeout(f, delay); // GOOD
+
+});
diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll
new file mode 100644
index 00000000000..dc46eb7daf0
--- /dev/null
+++ b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll
@@ -0,0 +1,77 @@
+/**
+ * Provides a taint tracking configuration for reasoning about
+ * resource exhaustion vulnerabilities (CWE-770).
+ *
+ * Note, for performance reasons: only import this file if
+ * `ResourceExhaustion::Configuration` is needed, otherwise
+ * `ResourceExhaustionCustomizations` should be imported instead.
+ */
+
+import javascript
+import semmle.javascript.security.dataflow.LoopBoundInjectionCustomizations
+
+module ResourceExhaustion {
+ import ResourceExhaustionCustomizations::ResourceExhaustion
+
+ /**
+ * A data flow configuration for resource exhaustion vulnerabilities.
+ */
+ class Configuration extends TaintTracking::Configuration {
+ Configuration() { this = "ResourceExhaustion" }
+
+ override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
+ source.(Source).getAFlowLabel() = label
+ }
+
+ override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
+ sink.(Sink).getAFlowLabel() = label
+ }
+
+ override predicate isAdditionalFlowStep(
+ DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel,
+ DataFlow::FlowLabel dstlabel
+ ) {
+ dstlabel instanceof Label::Number and
+ isNumericFlowStep(src, dst)
+ or
+ // reuse most existing taint steps
+ super.isAdditionalFlowStep(src, dst) and
+ not dst.asExpr() instanceof AddExpr and
+ if dst.(DataFlow::MethodCallNode).calls(src, "toString")
+ then dstlabel.isTaint()
+ else srclabel = dstlabel
+ }
+
+ override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
+ guard instanceof LoopBoundInjection::LengthCheckSanitizerGuard or
+ guard instanceof UpperBoundsCheckSanitizerGuard or
+ guard instanceof TypeTestGuard
+ }
+ }
+
+ /**
+ * Holds if data may flow from `src` to `dst` as a number.
+ */
+ predicate isNumericFlowStep(DataFlow::Node src, DataFlow::Node dst) {
+ // steps that introduce or preserve a number
+ dst.(DataFlow::PropRead).accesses(src, ["length", "size"])
+ or
+ exists(DataFlow::CallNode c |
+ c = dst and
+ src = c.getAnArgument()
+ |
+ c = DataFlow::globalVarRef("Math").getAMemberCall(_) or
+ c = DataFlow::globalVarRef(["Number", "parseInt", "parseFloat"]).getACall()
+ )
+ or
+ exists(Expr dstExpr, Expr srcExpr |
+ dstExpr = dst.asExpr() and
+ srcExpr = src.asExpr()
+ |
+ dstExpr.(BinaryExpr).getAnOperand() = srcExpr and
+ not dstExpr instanceof AddExpr
+ or
+ dstExpr.(PlusExpr).getOperand() = srcExpr
+ )
+ }
+}
diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll
new file mode 100644
index 00000000000..d5d92abae4e
--- /dev/null
+++ b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll
@@ -0,0 +1,186 @@
+/**
+ * Provides default sources, sinks and sanitizers for reasoning about
+ * resource exhaustion vulnerabilities, as well as extension points for
+ * adding your own.
+ */
+
+import javascript
+
+module ResourceExhaustion {
+ /**
+ * A data flow source for resource exhaustion vulnerabilities.
+ */
+ abstract class Source extends DataFlow::Node {
+ /** Gets a flow label denoting the type of value for which this is a source. */
+ DataFlow::FlowLabel getAFlowLabel() { result.isTaint() }
+ }
+
+ /**
+ * A data flow sink for resource exhaustion vulnerabilities.
+ */
+ abstract class Sink extends DataFlow::Node {
+ /** Gets a flow label denoting the type of value for which this is a sink. */
+ DataFlow::FlowLabel getAFlowLabel() { result instanceof Label::Number }
+
+ /**
+ * Gets a description of why this is a problematic sink.
+ */
+ abstract string getProblemDescription();
+ }
+
+ /**
+ * A data flow sanitizer for resource exhaustion vulnerabilities.
+ */
+ abstract class Sanitizer extends DataFlow::Node { }
+
+ /**
+ * Provides data flow labels for resource exhaustion vulnerabilities.
+ */
+ module Label {
+ /**
+ * A number data flow label.
+ */
+ class Number extends DataFlow::FlowLabel {
+ Number() { this = "number" }
+ }
+ }
+
+ /**
+ * A sanitizer that blocks taint flow if the size of a number is limited.
+ */
+ class UpperBoundsCheckSanitizerGuard extends TaintTracking::LabeledSanitizerGuardNode,
+ DataFlow::ValueNode {
+ override RelationalComparison astNode;
+
+ override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) {
+ label instanceof Label::Number and
+ (
+ true = outcome and
+ e = astNode.getLesserOperand()
+ or
+ false = outcome and
+ e = astNode.getGreaterOperand()
+ )
+ }
+ }
+
+ /**
+ * A test of form `typeof x === "something"`, preventing `x` from being a number in some cases.
+ */
+ class TypeTestGuard extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode {
+ override EqualityTest astNode;
+ TypeofExpr typeof;
+ boolean polarity;
+
+ TypeTestGuard() {
+ astNode.getAnOperand() = typeof and
+ (
+ // typeof x === "number" sanitizes `x` when it evaluates to false
+ astNode.getAnOperand().getStringValue() = "number" and
+ polarity = astNode.getPolarity().booleanNot()
+ or
+ // typeof x === "string" sanitizes `x` when it evaluates to true
+ astNode.getAnOperand().getStringValue() != "number" and
+ polarity = astNode.getPolarity()
+ )
+ }
+
+ override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) {
+ polarity = outcome and
+ e = typeof.getOperand() and
+ label instanceof Label::Number
+ }
+ }
+
+ /** A source of remote user input, considered as a data flow source for resource exhaustion vulnerabilities. */
+ class RemoteFlowSourceAsSource extends Source {
+ RemoteFlowSourceAsSource() { this instanceof RemoteFlowSource }
+ }
+
+ /**
+ * A node that determines the size of a buffer, considered as a data flow sink for resource exhaustion vulnerabilities.
+ */
+ class BufferSizeSink extends Sink {
+ BufferSizeSink() {
+ exists(DataFlow::SourceNode clazz, DataFlow::InvokeNode invk, int index |
+ clazz = DataFlow::globalVarRef("Buffer") and this = invk.getArgument(index)
+ |
+ exists(string name |
+ invk = clazz.getAMemberCall(name) and
+ (
+ name = "from" and index = 2
+ or
+ name = ["alloc", "allocUnsafe", "allocUnsafeSlow"] and index = 0
+ )
+ )
+ or
+ invk = clazz.getAnInvocation() and
+ (
+ invk.getNumArgument() = 1 and
+ index = 0
+ or
+ invk.getNumArgument() = 3 and index = 2
+ )
+ )
+ or
+ this = DataFlow::globalVarRef("SlowBuffer").getAnInstantiation().getArgument(0)
+ }
+
+ override string getProblemDescription() {
+ result = "This creates a buffer with a user-controlled size"
+ }
+ }
+
+ /**
+ * A node that determines the size of an array, considered as a data flow sink for resource exhaustion vulnerabilities.
+ */
+ class DenseArraySizeSink extends Sink {
+ DenseArraySizeSink() {
+ // Arrays are sparse by default, so we must also look at how the array is used
+ exists(DataFlow::ArrayConstructorInvokeNode instance |
+ this = instance.getArgument(0) and
+ instance.getNumArgument() = 1
+ |
+ exists(instance.getAMethodCall(["map", "fill", "join", "toString"])) or
+ instance.flowsToExpr(any(AddExpr p).getAnOperand())
+ )
+ }
+
+ override string getProblemDescription() {
+ result = "This creates an array with a user-controlled length"
+ }
+ }
+
+ /**
+ * A node that determines the repetitions of a string, considered as a data flow sink for resource exhaustion vulnerabilities.
+ */
+ class StringRepetitionSink extends Sink {
+ StringRepetitionSink() {
+ exists(DataFlow::MethodCallNode repeat |
+ repeat.getMethodName() = "repeat" and
+ this = repeat.getArgument(0)
+ )
+ }
+
+ override DataFlow::FlowLabel getAFlowLabel() { any() }
+
+ override string getProblemDescription() {
+ result = "This creates a string with a user-controlled length"
+ }
+ }
+
+ /**
+ * A node that determines the duration of a timer, considered as a data flow sink for resource exhaustion vulnerabilities.
+ */
+ class TimerDurationSink extends Sink {
+ TimerDurationSink() {
+ this = DataFlow::globalVarRef(["setTimeout", "setInterval"]).getACall().getArgument(1)
+ }
+
+ override DataFlow::FlowLabel getAFlowLabel() { any() }
+
+ override string getProblemDescription() {
+ result = "This creates a timer with a user-controlled duration"
+ }
+ }
+}
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/MemoryExhaustion.expected b/javascript/ql/test/query-tests/Security/CWE-770/MemoryExhaustion.expected
deleted file mode 100644
index 73bcafa1a81..00000000000
--- a/javascript/ql/test/query-tests/Security/CWE-770/MemoryExhaustion.expected
+++ /dev/null
@@ -1,154 +0,0 @@
-nodes
-| memory-exhaustion.js:6:7:6:42 | s |
-| memory-exhaustion.js:6:11:6:34 | url.par ... , true) |
-| memory-exhaustion.js:6:11:6:40 | url.par ... ).query |
-| memory-exhaustion.js:6:11:6:42 | url.par ... query.s |
-| memory-exhaustion.js:6:21:6:27 | req.url |
-| memory-exhaustion.js:6:21:6:27 | req.url |
-| memory-exhaustion.js:7:7:7:21 | n |
-| memory-exhaustion.js:7:11:7:21 | parseInt(s) |
-| memory-exhaustion.js:7:20:7:20 | s |
-| memory-exhaustion.js:13:21:13:21 | n |
-| memory-exhaustion.js:13:21:13:21 | n |
-| memory-exhaustion.js:14:21:14:21 | n |
-| memory-exhaustion.js:14:21:14:21 | n |
-| memory-exhaustion.js:15:16:15:16 | n |
-| memory-exhaustion.js:15:16:15:16 | n |
-| memory-exhaustion.js:16:22:16:22 | n |
-| memory-exhaustion.js:16:22:16:22 | n |
-| memory-exhaustion.js:17:26:17:26 | n |
-| memory-exhaustion.js:17:26:17:26 | n |
-| memory-exhaustion.js:19:14:19:14 | n |
-| memory-exhaustion.js:19:14:19:14 | n |
-| memory-exhaustion.js:21:20:21:20 | n |
-| memory-exhaustion.js:21:20:21:20 | n |
-| memory-exhaustion.js:23:18:23:18 | n |
-| memory-exhaustion.js:23:18:23:18 | n |
-| memory-exhaustion.js:28:9:28:9 | n |
-| memory-exhaustion.js:28:9:28:9 | n |
-| memory-exhaustion.js:29:13:29:13 | n |
-| memory-exhaustion.js:29:13:29:13 | n |
-| memory-exhaustion.js:30:9:30:9 | n |
-| memory-exhaustion.js:30:9:30:9 | n |
-| memory-exhaustion.js:31:9:31:9 | n |
-| memory-exhaustion.js:31:9:31:9 | n |
-| memory-exhaustion.js:32:9:32:9 | n |
-| memory-exhaustion.js:32:9:32:9 | n |
-| memory-exhaustion.js:33:9:33:9 | n |
-| memory-exhaustion.js:33:9:33:9 | n |
-| memory-exhaustion.js:35:12:35:12 | n |
-| memory-exhaustion.js:35:12:35:12 | n |
-| memory-exhaustion.js:36:12:36:12 | s |
-| memory-exhaustion.js:36:12:36:12 | s |
-| memory-exhaustion.js:38:14:38:14 | n |
-| memory-exhaustion.js:38:14:38:18 | n * x |
-| memory-exhaustion.js:38:14:38:18 | n * x |
-| memory-exhaustion.js:46:14:46:25 | Math.ceil(s) |
-| memory-exhaustion.js:46:14:46:25 | Math.ceil(s) |
-| memory-exhaustion.js:46:24:46:24 | s |
-| memory-exhaustion.js:47:14:47:22 | Number(s) |
-| memory-exhaustion.js:47:14:47:22 | Number(s) |
-| memory-exhaustion.js:47:21:47:21 | s |
-| memory-exhaustion.js:51:14:51:14 | s |
-| memory-exhaustion.js:51:14:51:21 | s.length |
-| memory-exhaustion.js:51:14:51:21 | s.length |
-| memory-exhaustion.js:56:16:56:16 | n |
-| memory-exhaustion.js:56:16:56:16 | n |
-| memory-exhaustion.js:59:7:59:20 | ns |
-| memory-exhaustion.js:59:12:59:20 | x ? n : s |
-| memory-exhaustion.js:59:16:59:16 | n |
-| memory-exhaustion.js:60:14:60:15 | ns |
-| memory-exhaustion.js:60:14:60:15 | ns |
-| memory-exhaustion.js:67:16:67:16 | n |
-| memory-exhaustion.js:67:16:67:16 | n |
-| memory-exhaustion.js:71:16:71:16 | n |
-| memory-exhaustion.js:71:16:71:16 | n |
-edges
-| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:7:20:7:20 | s |
-| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:36:12:36:12 | s |
-| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:36:12:36:12 | s |
-| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:46:24:46:24 | s |
-| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:47:21:47:21 | s |
-| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:51:14:51:14 | s |
-| memory-exhaustion.js:6:11:6:34 | url.par ... , true) | memory-exhaustion.js:6:11:6:40 | url.par ... ).query |
-| memory-exhaustion.js:6:11:6:40 | url.par ... ).query | memory-exhaustion.js:6:11:6:42 | url.par ... query.s |
-| memory-exhaustion.js:6:11:6:42 | url.par ... query.s | memory-exhaustion.js:6:7:6:42 | s |
-| memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:6:11:6:34 | url.par ... , true) |
-| memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:6:11:6:34 | url.par ... , true) |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:13:21:13:21 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:13:21:13:21 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:14:21:14:21 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:14:21:14:21 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:15:16:15:16 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:15:16:15:16 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:16:22:16:22 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:16:22:16:22 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:17:26:17:26 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:17:26:17:26 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:19:14:19:14 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:19:14:19:14 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:21:20:21:20 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:21:20:21:20 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:23:18:23:18 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:23:18:23:18 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:28:9:28:9 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:28:9:28:9 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:29:13:29:13 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:29:13:29:13 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:30:9:30:9 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:30:9:30:9 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:31:9:31:9 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:31:9:31:9 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:32:9:32:9 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:32:9:32:9 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:33:9:33:9 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:33:9:33:9 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:35:12:35:12 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:35:12:35:12 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:38:14:38:14 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:56:16:56:16 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:56:16:56:16 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:59:16:59:16 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:67:16:67:16 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:67:16:67:16 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:71:16:71:16 | n |
-| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:71:16:71:16 | n |
-| memory-exhaustion.js:7:11:7:21 | parseInt(s) | memory-exhaustion.js:7:7:7:21 | n |
-| memory-exhaustion.js:7:20:7:20 | s | memory-exhaustion.js:7:11:7:21 | parseInt(s) |
-| memory-exhaustion.js:38:14:38:14 | n | memory-exhaustion.js:38:14:38:18 | n * x |
-| memory-exhaustion.js:38:14:38:14 | n | memory-exhaustion.js:38:14:38:18 | n * x |
-| memory-exhaustion.js:46:24:46:24 | s | memory-exhaustion.js:46:14:46:25 | Math.ceil(s) |
-| memory-exhaustion.js:46:24:46:24 | s | memory-exhaustion.js:46:14:46:25 | Math.ceil(s) |
-| memory-exhaustion.js:47:21:47:21 | s | memory-exhaustion.js:47:14:47:22 | Number(s) |
-| memory-exhaustion.js:47:21:47:21 | s | memory-exhaustion.js:47:14:47:22 | Number(s) |
-| memory-exhaustion.js:51:14:51:14 | s | memory-exhaustion.js:51:14:51:21 | s.length |
-| memory-exhaustion.js:51:14:51:14 | s | memory-exhaustion.js:51:14:51:21 | s.length |
-| memory-exhaustion.js:59:7:59:20 | ns | memory-exhaustion.js:60:14:60:15 | ns |
-| memory-exhaustion.js:59:7:59:20 | ns | memory-exhaustion.js:60:14:60:15 | ns |
-| memory-exhaustion.js:59:12:59:20 | x ? n : s | memory-exhaustion.js:59:7:59:20 | ns |
-| memory-exhaustion.js:59:16:59:16 | n | memory-exhaustion.js:59:12:59:20 | x ? n : s |
-#select
-| memory-exhaustion.js:13:21:13:21 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:13:21:13:21 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:14:21:14:21 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:14:21:14:21 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:15:16:15:16 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:15:16:15:16 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:16:22:16:22 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:16:22:16:22 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:17:26:17:26 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:17:26:17:26 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:19:14:19:14 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:19:14:19:14 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:21:20:21:20 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:21:20:21:20 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:23:18:23:18 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:23:18:23:18 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:28:9:28:9 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:28:9:28:9 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:29:13:29:13 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:29:13:29:13 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:30:9:30:9 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:30:9:30:9 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:31:9:31:9 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:31:9:31:9 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:32:9:32:9 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:32:9:32:9 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:33:9:33:9 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:33:9:33:9 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:35:12:35:12 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:35:12:35:12 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:36:12:36:12 | s | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:36:12:36:12 | s | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:38:14:38:18 | n * x | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:38:14:38:18 | n * x | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:46:14:46:25 | Math.ceil(s) | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:46:14:46:25 | Math.ceil(s) | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:47:14:47:22 | Number(s) | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:47:14:47:22 | Number(s) | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:51:14:51:21 | s.length | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:51:14:51:21 | s.length | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:56:16:56:16 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:56:16:56:16 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:60:14:60:15 | ns | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:60:14:60:15 | ns | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:67:16:67:16 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:67:16:67:16 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
-| memory-exhaustion.js:71:16:71:16 | n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:71:16:71:16 | n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/MemoryExhaustion.qlref b/javascript/ql/test/query-tests/Security/CWE-770/MemoryExhaustion.qlref
deleted file mode 100644
index feed3f04014..00000000000
--- a/javascript/ql/test/query-tests/Security/CWE-770/MemoryExhaustion.qlref
+++ /dev/null
@@ -1 +0,0 @@
-Security/CWE-770/MemoryExhaustion.ql
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected
new file mode 100644
index 00000000000..0260567be53
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected
@@ -0,0 +1,234 @@
+nodes
+| documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size |
+| documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) |
+| documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) |
+| documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query |
+| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size |
+| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size |
+| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url |
+| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url |
+| documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size |
+| documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size |
+| documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size |
+| documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) |
+| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) |
+| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query |
+| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size |
+| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size |
+| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url |
+| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url |
+| documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size |
+| documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size |
+| documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay |
+| documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) |
+| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) |
+| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query |
+| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay |
+| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url |
+| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url |
+| documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay |
+| documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay |
+| resource-exhaustion.js:5:7:5:42 | s |
+| resource-exhaustion.js:5:11:5:34 | url.par ... , true) |
+| resource-exhaustion.js:5:11:5:40 | url.par ... ).query |
+| resource-exhaustion.js:5:11:5:42 | url.par ... query.s |
+| resource-exhaustion.js:5:21:5:27 | req.url |
+| resource-exhaustion.js:5:21:5:27 | req.url |
+| resource-exhaustion.js:6:7:6:21 | n |
+| resource-exhaustion.js:6:11:6:21 | parseInt(s) |
+| resource-exhaustion.js:6:20:6:20 | s |
+| resource-exhaustion.js:12:21:12:21 | n |
+| resource-exhaustion.js:12:21:12:21 | n |
+| resource-exhaustion.js:13:21:13:21 | n |
+| resource-exhaustion.js:13:21:13:21 | n |
+| resource-exhaustion.js:14:16:14:16 | n |
+| resource-exhaustion.js:14:16:14:16 | n |
+| resource-exhaustion.js:15:22:15:22 | n |
+| resource-exhaustion.js:15:22:15:22 | n |
+| resource-exhaustion.js:16:26:16:26 | n |
+| resource-exhaustion.js:16:26:16:26 | n |
+| resource-exhaustion.js:18:14:18:14 | n |
+| resource-exhaustion.js:18:14:18:14 | n |
+| resource-exhaustion.js:20:20:20:20 | n |
+| resource-exhaustion.js:20:20:20:20 | n |
+| resource-exhaustion.js:22:18:22:18 | n |
+| resource-exhaustion.js:22:18:22:18 | n |
+| resource-exhaustion.js:27:9:27:9 | n |
+| resource-exhaustion.js:27:9:27:9 | n |
+| resource-exhaustion.js:28:13:28:13 | n |
+| resource-exhaustion.js:28:13:28:13 | n |
+| resource-exhaustion.js:29:9:29:9 | n |
+| resource-exhaustion.js:29:9:29:9 | n |
+| resource-exhaustion.js:30:9:30:9 | n |
+| resource-exhaustion.js:30:9:30:9 | n |
+| resource-exhaustion.js:31:9:31:9 | n |
+| resource-exhaustion.js:31:9:31:9 | n |
+| resource-exhaustion.js:32:9:32:9 | n |
+| resource-exhaustion.js:32:9:32:9 | n |
+| resource-exhaustion.js:34:12:34:12 | n |
+| resource-exhaustion.js:34:12:34:12 | n |
+| resource-exhaustion.js:35:12:35:12 | s |
+| resource-exhaustion.js:35:12:35:12 | s |
+| resource-exhaustion.js:37:14:37:14 | n |
+| resource-exhaustion.js:37:14:37:18 | n * x |
+| resource-exhaustion.js:37:14:37:18 | n * x |
+| resource-exhaustion.js:45:14:45:25 | Math.ceil(s) |
+| resource-exhaustion.js:45:14:45:25 | Math.ceil(s) |
+| resource-exhaustion.js:45:24:45:24 | s |
+| resource-exhaustion.js:46:14:46:22 | Number(s) |
+| resource-exhaustion.js:46:14:46:22 | Number(s) |
+| resource-exhaustion.js:46:21:46:21 | s |
+| resource-exhaustion.js:50:14:50:14 | s |
+| resource-exhaustion.js:50:14:50:21 | s.length |
+| resource-exhaustion.js:50:14:50:21 | s.length |
+| resource-exhaustion.js:55:16:55:16 | n |
+| resource-exhaustion.js:55:16:55:16 | n |
+| resource-exhaustion.js:58:7:58:20 | ns |
+| resource-exhaustion.js:58:12:58:20 | x ? n : s |
+| resource-exhaustion.js:58:16:58:16 | n |
+| resource-exhaustion.js:59:14:59:15 | ns |
+| resource-exhaustion.js:59:14:59:15 | ns |
+| resource-exhaustion.js:66:16:66:16 | n |
+| resource-exhaustion.js:66:16:66:16 | n |
+| resource-exhaustion.js:70:16:70:16 | n |
+| resource-exhaustion.js:70:16:70:16 | n |
+| resource-exhaustion.js:81:17:81:17 | n |
+| resource-exhaustion.js:81:17:81:17 | n |
+| resource-exhaustion.js:82:17:82:17 | s |
+| resource-exhaustion.js:82:17:82:17 | s |
+| resource-exhaustion.js:83:18:83:18 | n |
+| resource-exhaustion.js:83:18:83:18 | n |
+| resource-exhaustion.js:84:18:84:18 | s |
+| resource-exhaustion.js:84:18:84:18 | s |
+edges
+| documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size |
+| documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size |
+| documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) | documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size |
+| documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) | documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query |
+| documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size |
+| documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size |
+| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) |
+| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) |
+| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) |
+| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) |
+| documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size |
+| documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size |
+| documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) | documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size |
+| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query |
+| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size |
+| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size |
+| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) |
+| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) |
+| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) |
+| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) |
+| documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay |
+| documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay |
+| documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay |
+| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query |
+| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay |
+| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) |
+| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) |
+| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) |
+| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:6:20:6:20 | s |
+| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:35:12:35:12 | s |
+| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:35:12:35:12 | s |
+| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:45:24:45:24 | s |
+| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:46:21:46:21 | s |
+| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:50:14:50:14 | s |
+| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:82:17:82:17 | s |
+| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:82:17:82:17 | s |
+| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:84:18:84:18 | s |
+| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:84:18:84:18 | s |
+| resource-exhaustion.js:5:11:5:34 | url.par ... , true) | resource-exhaustion.js:5:11:5:40 | url.par ... ).query |
+| resource-exhaustion.js:5:11:5:40 | url.par ... ).query | resource-exhaustion.js:5:11:5:42 | url.par ... query.s |
+| resource-exhaustion.js:5:11:5:42 | url.par ... query.s | resource-exhaustion.js:5:7:5:42 | s |
+| resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:5:11:5:34 | url.par ... , true) |
+| resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:5:11:5:34 | url.par ... , true) |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:12:21:12:21 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:12:21:12:21 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:13:21:13:21 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:13:21:13:21 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:14:16:14:16 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:14:16:14:16 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:15:22:15:22 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:15:22:15:22 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:16:26:16:26 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:16:26:16:26 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:18:14:18:14 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:18:14:18:14 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:20:20:20:20 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:20:20:20:20 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:22:18:22:18 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:22:18:22:18 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:27:9:27:9 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:27:9:27:9 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:28:13:28:13 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:28:13:28:13 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:29:9:29:9 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:29:9:29:9 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:30:9:30:9 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:30:9:30:9 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:31:9:31:9 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:31:9:31:9 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:32:9:32:9 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:32:9:32:9 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:34:12:34:12 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:34:12:34:12 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:37:14:37:14 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:55:16:55:16 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:55:16:55:16 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:58:16:58:16 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:66:16:66:16 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:66:16:66:16 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:70:16:70:16 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:70:16:70:16 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:81:17:81:17 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:81:17:81:17 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:83:18:83:18 | n |
+| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:83:18:83:18 | n |
+| resource-exhaustion.js:6:11:6:21 | parseInt(s) | resource-exhaustion.js:6:7:6:21 | n |
+| resource-exhaustion.js:6:20:6:20 | s | resource-exhaustion.js:6:11:6:21 | parseInt(s) |
+| resource-exhaustion.js:37:14:37:14 | n | resource-exhaustion.js:37:14:37:18 | n * x |
+| resource-exhaustion.js:37:14:37:14 | n | resource-exhaustion.js:37:14:37:18 | n * x |
+| resource-exhaustion.js:45:24:45:24 | s | resource-exhaustion.js:45:14:45:25 | Math.ceil(s) |
+| resource-exhaustion.js:45:24:45:24 | s | resource-exhaustion.js:45:14:45:25 | Math.ceil(s) |
+| resource-exhaustion.js:46:21:46:21 | s | resource-exhaustion.js:46:14:46:22 | Number(s) |
+| resource-exhaustion.js:46:21:46:21 | s | resource-exhaustion.js:46:14:46:22 | Number(s) |
+| resource-exhaustion.js:50:14:50:14 | s | resource-exhaustion.js:50:14:50:21 | s.length |
+| resource-exhaustion.js:50:14:50:14 | s | resource-exhaustion.js:50:14:50:21 | s.length |
+| resource-exhaustion.js:58:7:58:20 | ns | resource-exhaustion.js:59:14:59:15 | ns |
+| resource-exhaustion.js:58:7:58:20 | ns | resource-exhaustion.js:59:14:59:15 | ns |
+| resource-exhaustion.js:58:12:58:20 | x ? n : s | resource-exhaustion.js:58:7:58:20 | ns |
+| resource-exhaustion.js:58:16:58:16 | n | resource-exhaustion.js:58:12:58:20 | x ? n : s |
+#select
+| documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | This creates an array with a user-controlled length from $@. | documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | here |
+| documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | This creates a buffer with a user-controlled size from $@. | documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | here |
+| documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | This creates a timer with a user-controlled duration from $@. | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | here |
+| resource-exhaustion.js:12:21:12:21 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:12:21:12:21 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:13:21:13:21 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:13:21:13:21 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:14:16:14:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:14:16:14:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:15:22:15:22 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:15:22:15:22 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:16:26:16:26 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:16:26:16:26 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:18:14:18:14 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:18:14:18:14 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:20:20:20:20 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:20:20:20:20 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:22:18:22:18 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:22:18:22:18 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:27:9:27:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:27:9:27:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:28:13:28:13 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:28:13:28:13 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:29:9:29:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:29:9:29:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:30:9:30:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:30:9:30:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:31:9:31:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:31:9:31:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:32:9:32:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:32:9:32:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:34:12:34:12 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:34:12:34:12 | n | This creates a string with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:35:12:35:12 | s | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:35:12:35:12 | s | This creates a string with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:37:14:37:18 | n * x | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:37:14:37:18 | n * x | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:46:14:46:22 | Number(s) | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:46:14:46:22 | Number(s) | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:50:14:50:21 | s.length | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:50:14:50:21 | s.length | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:55:16:55:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:55:16:55:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:59:14:59:15 | ns | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:59:14:59:15 | ns | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:66:16:66:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:66:16:66:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:70:16:70:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:70:16:70:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:81:17:81:17 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:81:17:81:17 | n | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:82:17:82:17 | s | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:82:17:82:17 | s | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:83:18:83:18 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:83:18:83:18 | n | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
+| resource-exhaustion.js:84:18:84:18 | s | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:84:18:84:18 | s | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here |
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref
new file mode 100644
index 00000000000..38e612d406f
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref
@@ -0,0 +1 @@
+Security/CWE-770/ResourceExhaustion.ql
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js
new file mode 100644
index 00000000000..2fad9da5d93
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js
@@ -0,0 +1,10 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var size = parseInt(url.parse(req.url, true).query.size);
+
+ let dogs = new Array(size).fill(x => "dog"); // BAD
+
+ // ... use the dog
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js
new file mode 100644
index 00000000000..f7c88129264
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js
@@ -0,0 +1,16 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var size = parseInt(url.parse(req.url, true).query.size);
+
+ if (size > 1024) {
+ res.statusCode = 400;
+ res.end("Bad request.");
+ return;
+ }
+
+ let dogs = new Array(size).fill(x => "dog"); // GOOD
+
+ // ... use the dogs
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js
new file mode 100644
index 00000000000..d821901e818
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js
@@ -0,0 +1,10 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var size = parseInt(url.parse(req.url, true).query.size);
+
+ let buffer = Buffer.alloc(size); // BAD
+
+ // ... use the buffer
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js
new file mode 100644
index 00000000000..8d9f9b0839f
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js
@@ -0,0 +1,16 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var size = parseInt(url.parse(req.url, true).query.size);
+
+ if (size > 1024) {
+ res.statusCode = 400;
+ res.end("Bad request.");
+ return;
+ }
+
+ let buffer = Buffer.alloc(size); // GOOD
+
+ // ... use the buffer
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout.js
new file mode 100644
index 00000000000..1718509534b
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout.js
@@ -0,0 +1,9 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var delay = parseInt(url.parse(req.url, true).query.delay);
+
+ setTimeout(f, delay); // BAD
+
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout_fixed.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout_fixed.js
new file mode 100644
index 00000000000..2f5a614e3d7
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout_fixed.js
@@ -0,0 +1,15 @@
+var http = require("http"),
+ url = require("url");
+
+var server = http.createServer(function(req, res) {
+ var delay = parseInt(url.parse(req.url, true).query.delay);
+
+ if (delay > 1000) {
+ res.statusCode = 400;
+ res.end("Bad request.");
+ return;
+ }
+
+ setTimeout(f, delay); // GOOD
+
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-770/memory-exhaustion.js b/javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js
similarity index 92%
rename from javascript/ql/test/query-tests/Security/CWE-770/memory-exhaustion.js
rename to javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js
index 806ccd1ddc4..1500fe15b87 100644
--- a/javascript/ql/test/query-tests/Security/CWE-770/memory-exhaustion.js
+++ b/javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js
@@ -1,6 +1,5 @@
var http = require("http"),
- url = require("url"),
- fs = require("fs");
+ url = require("url");
var server = http.createServer(function(req, res) {
let s = url.parse(req.url, true).query.s;
@@ -79,4 +78,8 @@ var server = http.createServer(function(req, res) {
new Buffer(s); // OK
}
+ setTimeout(f, n); // NOT OK
+ setTimeout(f, s); // NOT OK
+ setInterval(f, n); // NOT OK
+ setInterval(f, s); // NOT OK
});