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 });