Merge pull request #932 from asger-semmle/cookbook-prepare

Approved by xiemaisi
This commit is contained in:
semmle-qlci
2019-02-13 18:20:09 +00:00
committed by GitHub
14 changed files with 180 additions and 12 deletions

View File

@@ -19,7 +19,7 @@ class Configuration extends TaintTracking::Configuration {
Configuration() { this = "IncompleteHostnameRegExpTracking" }
override predicate isSource(DataFlow::Node source) {
isIncompleteHostNameRegExpPattern(source.asExpr().getStringValue(), _)
isIncompleteHostNameRegExpPattern(source.getStringValue(), _)
}
override predicate isSink(DataFlow::Node sink) { isInterpretedAsRegExp(sink) }

View File

@@ -76,7 +76,7 @@ predicate isDerivedFromLength(DataFlow::Node length, DataFlow::Node operand) {
exists(IndexOfCall call | operand = call.getAnOperand() |
length = getStringSource(operand).getAPropertyRead("length")
or
exists(string val | val = operand.asExpr().getStringValue() |
exists(string val | val = operand.getStringValue() |
// Find a literal length with the same string constant
exists(LiteralLengthExpr lengthExpr |
lengthExpr.getContainer() = call.getContainer() and

View File

@@ -83,7 +83,7 @@ class Replacement extends DataFlow::Node {
exists(DataFlow::MethodCallNode mcn |
mcn = this and
input = getStringValue(pattern) and
output = mcn.getArgument(1).asExpr().getStringValue()
output = mcn.getArgument(1).getStringValue()
)
}

View File

@@ -111,7 +111,7 @@ module DOM {
/**
* Gets the value of this attribute, if it can be determined.
*/
string getStringValue() { result = getValueNode().asExpr().getStringValue() }
string getStringValue() { result = getValueNode().getStringValue() }
/**
* Gets the DOM element this attribute belongs to.

View File

@@ -104,6 +104,6 @@ module StringConcatenation {
*/
predicate isCoercion(DataFlow::Node node) {
getNumOperand(node) = 2 and
getOperand(node, _).asExpr().getStringValue() = ""
getOperand(node, _).getStringValue() = ""
}
}

View File

@@ -141,7 +141,7 @@ module StringOps {
(
substring.getALocalSource().getAPropertyRead("length").flowsTo(call.getArgument(1))
or
substring.asExpr().getStringValue().length() = call.getArgument(1).asExpr().getIntValue()
substring.getStringValue().length() = call.getArgument(1).asExpr().getIntValue()
)
}

View File

@@ -97,14 +97,23 @@ module DataFlow {
*/
predicate accessesGlobal(string g) { globalVarRef(g).flowsTo(this) }
/** Holds if this node may evaluate to the string `s`. */
/** Holds if this node may evaluate to the string `s`, possibly through local data flow. */
predicate mayHaveStringValue(string s) { getAPredecessor().mayHaveStringValue(s) }
/** Gets the string value of this node, if it is a string literal or constant string concatenation. */
string getStringValue() { result = asExpr().getStringValue() }
/** Holds if this node may evaluate to the Boolean value `b`. */
predicate mayHaveBooleanValue(boolean b) {
b = analyze().getAValue().(AbstractBoolean).getBooleanValue()
}
/** Gets the integer value of this node, if it is an integer constant. */
int getIntValue() { result = asExpr().getIntValue() }
/** Gets a function value that may reach this node. */
FunctionNode getAFunctionValue() { result.getAstNode() = analyze().getAValue().(AbstractCallable).getFunction() }
/**
* Holds if this expression may refer to the initial value of parameter `p`.
*/

View File

@@ -278,7 +278,7 @@ private module BrowserIdCrypto {
mod = DataFlow::moduleImport("browserid-crypto") and
keygen = mod.getAMemberCall("generateKeypair") and
algorithmNameNode = keygen.getOptionArgument(0, "algorithm") and
algorithm.matchesName(algorithmNameNode.asExpr().getStringValue()) and
algorithm.matchesName(algorithmNameNode.getStringValue()) and
callback = keygen.getCallback(1) and
this = mod.getAMemberCall("sign").asExpr()
)
@@ -321,7 +321,7 @@ private module NodeJSCrypto {
|
mod = DataFlow::moduleImport("crypto") and
this = mod.getAMemberCall("create" + createSuffix) and
algorithm.matchesName(getArgument(0).asExpr().getStringValue())
algorithm.matchesName(getArgument(0).getStringValue())
)
}

View File

@@ -13,7 +13,7 @@ import javascript
* Specifically, this holds if the string contains `?` or `#`.
*/
private predicate hasSanitizingSubstring(DataFlow::Node nd) {
nd.asExpr().getStringValue().regexpMatch(".*[?#].*")
nd.getStringValue().regexpMatch(".*[?#].*")
or
hasSanitizingSubstring(StringConcatenation::getAnOperand(nd))
or
@@ -48,7 +48,7 @@ predicate sanitizingPrefixEdge(DataFlow::Node source, DataFlow::Node sink) {
* the `//` separating the (optional) scheme from the hostname.
*/
private predicate hasHostnameSanitizingSubstring(DataFlow::Node nd) {
nd.asExpr().getStringValue().regexpMatch(".*([?#]|[^?#:/\\\\][/\\\\]).*")
nd.getStringValue().regexpMatch(".*([?#]|[^?#:/\\\\][/\\\\]).*")
or
hasHostnameSanitizingSubstring(StringConcatenation::getAnOperand(nd))
or

View File

@@ -67,7 +67,7 @@ module DomBasedXss {
// _may_ be interpreted as HTML
not exists(DataFlow::Node prefix, string strval |
isPrefixOfJQueryHtmlString(astNode, prefix) and
strval = prefix.asExpr().getStringValue() and
strval = prefix.getStringValue() and
not strval.regexpMatch("\\s*<.*")
) and
not isDocumentURL(astNode)

View File

@@ -0,0 +1,136 @@
| a.js:1:8:1:10 | foo | b.js:1:16:1:27 | function(){} |
| a.js:1:15:1:17 | bar | b.js:2:8:2:24 | function bar() {} |
| a.js:1:20:1:22 | qux | c.js:2:8:2:24 | function bar() {} |
| a.js:2:1:2:3 | foo | b.js:1:16:1:27 | function(){} |
| a.js:3:1:3:3 | bar | b.js:2:8:2:24 | function bar() {} |
| a.js:4:1:4:3 | qux | c.js:2:8:2:24 | function bar() {} |
| b.js:1:16:1:27 | function(){} | b.js:1:16:1:27 | function(){} |
| b.js:2:8:2:24 | function bar() {} | b.js:2:8:2:24 | function bar() {} |
| c.js:1:16:1:27 | function(){} | c.js:1:16:1:27 | function(){} |
| c.js:2:8:2:24 | function bar() {} | c.js:2:8:2:24 | function bar() {} |
| classes.js:1:1:19:2 | (functi ... o();\\n}) | classes.js:1:2:19:1 | functio ... lo();\\n} |
| classes.js:1:2:19:1 | functio ... lo();\\n} | classes.js:1:2:19:1 | functio ... lo();\\n} |
| classes.js:2:3:10:3 | A | classes.js:2:11:2:10 | () {} |
| classes.js:2:3:10:3 | class A ... }\\n } | classes.js:2:11:2:10 | () {} |
| classes.js:2:11:2:10 | () {} | classes.js:2:11:2:10 | () {} |
| classes.js:3:10:5:5 | () {\\n ... ;\\n } | classes.js:3:10:5:5 | () {\\n ... ;\\n } |
| classes.js:7:6:9:5 | () {\\n ... ;\\n } | classes.js:7:6:9:5 | () {\\n ... ;\\n } |
| classes.js:8:7:8:16 | this.hello | classes.js:3:10:5:5 | () {\\n ... ;\\n } |
| classes.js:12:3:16:3 | B | classes.js:12:21:12:20 | (...arg ... rgs); } |
| classes.js:12:3:16:3 | class B ... }\\n } | classes.js:12:21:12:20 | (...arg ... rgs); } |
| classes.js:12:19:12:19 | A | classes.js:2:11:2:10 | () {} |
| classes.js:12:21:12:20 | (...arg ... rgs); } | classes.js:12:21:12:20 | (...arg ... rgs); } |
| classes.js:12:21:12:20 | super | classes.js:2:11:2:10 | () {} |
| classes.js:13:10:15:5 | () {\\n ... ;\\n } | classes.js:13:10:15:5 | () {\\n ... ;\\n } |
| classes.js:18:3:18:15 | new B().hello | classes.js:13:10:15:5 | () {\\n ... ;\\n } |
| classes.js:18:7:18:7 | B | classes.js:12:21:12:20 | (...arg ... rgs); } |
| es2015.js:1:1:5:1 | class E ... ;\\n }\\n} | es2015.js:2:14:4:3 | () {\\n ... ");\\n } |
| es2015.js:2:14:4:3 | () {\\n ... ");\\n } | es2015.js:2:14:4:3 | () {\\n ... ");\\n } |
| es2015.js:6:5:6:16 | ExampleClass | es2015.js:2:14:4:3 | () {\\n ... ");\\n } |
| es2015.js:8:2:12:1 | functio ... \\n };\\n} | es2015.js:8:2:12:1 | functio ... \\n };\\n} |
| es2015.js:9:10:11:3 | () => { ... ();\\n } | es2015.js:9:10:11:3 | () => { ... ();\\n } |
| es2015.js:10:5:10:20 | arguments.callee | es2015.js:8:2:12:1 | functio ... \\n };\\n} |
| es2015.js:10:5:10:22 | arguments.callee() | es2015.js:9:10:11:3 | () => { ... ();\\n } |
| es2015.js:14:1:18:1 | class S ... ;\\n }\\n} | es2015.js:15:14:17:3 | () {\\n ... ();\\n } |
| es2015.js:14:19:14:47 | ("Wait ... eClass) | es2015.js:2:14:4:3 | () {\\n ... ");\\n } |
| es2015.js:14:20:14:46 | "Wait f ... leClass | es2015.js:2:14:4:3 | () {\\n ... ");\\n } |
| es2015.js:14:35:14:46 | ExampleClass | es2015.js:2:14:4:3 | () {\\n ... ");\\n } |
| es2015.js:15:14:17:3 | () {\\n ... ();\\n } | es2015.js:15:14:17:3 | () {\\n ... ();\\n } |
| es2015.js:16:5:16:9 | super | es2015.js:2:14:4:3 | () {\\n ... ");\\n } |
| es2015.js:20:1:22:1 | functio ... = 42;\\n} | es2015.js:20:1:22:1 | functio ... = 42;\\n} |
| es2015.js:24:1:29:1 | class O ... ;\\n }\\n} | es2015.js:25:14:28:3 | () {\\n ... x);\\n } |
| es2015.js:24:24:24:34 | PseudoClass | es2015.js:20:1:22:1 | functio ... = 42;\\n} |
| es2015.js:25:14:28:3 | () {\\n ... x);\\n } | es2015.js:25:14:28:3 | () {\\n ... x);\\n } |
| es2015.js:26:5:26:9 | super | es2015.js:20:1:22:1 | functio ... = 42;\\n} |
| es2015.js:31:1:33:1 | functio ... +y+z;\\n} | es2015.js:31:1:33:1 | functio ... +y+z;\\n} |
| es2015.js:34:1:34:3 | sum | es2015.js:31:1:33:1 | functio ... +y+z;\\n} |
| es2015.js:35:1:35:3 | sum | es2015.js:31:1:33:1 | functio ... +y+z;\\n} |
| es2015.js:36:1:36:3 | sum | es2015.js:31:1:33:1 | functio ... +y+z;\\n} |
| m2.js:2:6:2:18 | function() {} | m2.js:2:6:2:18 | function() {} |
| m.js:1:1:1:25 | exports ... on() {} | m.js:1:13:1:25 | function() {} |
| m.js:1:13:1:25 | function() {} | m.js:1:13:1:25 | function() {} |
| m.js:2:1:2:9 | exports.f | m.js:1:13:1:25 | function() {} |
| m.js:3:1:3:16 | module.exports.f | m.js:1:13:1:25 | function() {} |
| n.js:2:1:2:3 | m.f | m.js:1:13:1:25 | function() {} |
| n.js:5:1:5:4 | m2.f | m2.js:2:6:2:18 | function() {} |
| reflection.js:1:1:3:1 | functio ... x+y;\\n} | reflection.js:1:1:3:1 | functio ... x+y;\\n} |
| reflection.js:5:3:5:5 | add | reflection.js:1:1:3:1 | functio ... x+y;\\n} |
| reflection.js:5:3:5:39 | add.app ... n 56; } | reflection.js:5:15:5:39 | functio ... n 56; } |
| reflection.js:5:15:5:14 | this | reflection.js:1:1:3:1 | functio ... x+y;\\n} |
| reflection.js:5:15:5:39 | functio ... n 56; } | reflection.js:5:15:5:39 | functio ... n 56; } |
| reflection.js:7:1:7:3 | add | reflection.js:1:1:3:1 | functio ... x+y;\\n} |
| reflection.js:8:1:8:3 | add | reflection.js:1:1:3:1 | functio ... x+y;\\n} |
| reflection.js:8:1:8:9 | add.apply | reflection.js:5:15:5:39 | functio ... n 56; } |
| tst3.js:1:1:1:22 | functio ... fn() {} | tst3.js:1:1:1:22 | functio ... fn() {} |
| tst3.js:2:1:2:23 | functio ... n2() {} | tst3.js:2:1:2:23 | functio ... n2() {} |
| tst.js:1:1:1:15 | function f() {} | tst.js:1:1:1:15 | function f() {} |
| tst.js:2:9:2:21 | function() {} | tst.js:2:9:2:21 | function() {} |
| tst.js:3:1:3:17 | h = function() {} | tst.js:3:5:3:17 | function() {} |
| tst.js:3:5:3:17 | function() {} | tst.js:3:5:3:17 | function() {} |
| tst.js:4:1:4:5 | k = g | tst.js:2:9:2:21 | function() {} |
| tst.js:4:5:4:5 | g | tst.js:2:9:2:21 | function() {} |
| tst.js:6:1:6:1 | f | tst.js:1:1:1:15 | function f() {} |
| tst.js:7:1:7:1 | g | tst.js:2:9:2:21 | function() {} |
| tst.js:8:1:8:1 | h | tst.js:3:5:3:17 | function() {} |
| tst.js:9:1:9:1 | k | tst.js:2:9:2:21 | function() {} |
| tst.js:11:1:20:1 | functio ... \\tf();\\n} | tst.js:11:1:20:1 | functio ... \\tf();\\n} |
| tst.js:12:6:12:27 | n | tst.js:12:15:12:27 | function() {} |
| tst.js:12:10:12:27 | m \|\| function() {} | tst.js:12:15:12:27 | function() {} |
| tst.js:12:15:12:27 | function() {} | tst.js:12:15:12:27 | function() {} |
| tst.js:13:2:13:16 | function p() {} | tst.js:13:2:13:16 | function p() {} |
| tst.js:13:11:13:11 | p | tst.js:13:2:13:16 | function p() {} |
| tst.js:15:2:15:2 | l | tst.js:11:1:20:1 | functio ... \\tf();\\n} |
| tst.js:16:2:16:17 | arguments.callee | tst.js:11:1:20:1 | functio ... \\tf();\\n} |
| tst.js:17:2:17:2 | n | tst.js:12:15:12:27 | function() {} |
| tst.js:18:2:18:2 | p | tst.js:13:2:13:16 | function p() {} |
| tst.js:19:2:19:2 | f | tst.js:1:1:1:15 | function f() {} |
| tst.js:22:1:22:1 | l | tst.js:11:1:20:1 | functio ... \\tf();\\n} |
| tst.js:22:3:22:3 | k | tst.js:2:9:2:21 | function() {} |
| tst.js:24:5:24:5 | f | tst.js:1:1:1:15 | function f() {} |
| tst.js:25:5:25:5 | g | tst.js:2:9:2:21 | function() {} |
| tst.js:27:1:27:14 | (function(){}) | tst.js:27:2:27:13 | function(){} |
| tst.js:27:2:27:13 | function(){} | tst.js:27:2:27:13 | function(){} |
| tst.js:28:2:28:13 | function(){} | tst.js:28:2:28:13 | function(){} |
| tst.js:32:6:34:3 | functio ... ();\\n\\t\\t} | tst.js:32:6:34:3 | functio ... ();\\n\\t\\t} |
| tst.js:33:4:33:9 | this.g | tst.js:35:6:35:18 | function() {} |
| tst.js:35:6:35:18 | function() {} | tst.js:35:6:35:18 | function() {} |
| tst.js:38:6:38:18 | function() {} | tst.js:38:6:38:18 | function() {} |
| tst.js:39:6:39:6 | g | tst.js:2:9:2:21 | function() {} |
| tst.js:41:1:41:3 | o.f | tst.js:32:6:34:3 | functio ... ();\\n\\t\\t} |
| tst.js:42:1:42:32 | (functi ... }(o)).f | tst.js:32:6:34:3 | functio ... ();\\n\\t\\t} |
| tst.js:42:2:42:26 | functio ... rn x; } | tst.js:42:2:42:26 | functio ... rn x; } |
| tst.js:44:1:44:15 | function A() {} | tst.js:44:1:44:15 | function A() {} |
| tst.js:45:1:45:1 | A | tst.js:44:1:44:15 | function A() {} |
| tst.js:45:1:47:1 | A.proto ... .g();\\n} | tst.js:45:17:47:1 | functio ... .g();\\n} |
| tst.js:45:17:47:1 | functio ... .g();\\n} | tst.js:45:17:47:1 | functio ... .g();\\n} |
| tst.js:46:2:46:7 | this.g | tst.js:48:17:48:29 | function() {} |
| tst.js:46:2:46:7 | this.g | tst.js:61:17:61:29 | function() {} |
| tst.js:48:1:48:1 | A | tst.js:44:1:44:15 | function A() {} |
| tst.js:48:1:48:29 | A.proto ... on() {} | tst.js:48:17:48:29 | function() {} |
| tst.js:48:17:48:29 | function() {} | tst.js:48:17:48:29 | function() {} |
| tst.js:50:1:50:15 | function B() {} | tst.js:50:1:50:15 | function B() {} |
| tst.js:51:1:51:1 | B | tst.js:50:1:50:15 | function B() {} |
| tst.js:52:5:54:2 | functio ... g();\\n\\t} | tst.js:52:5:54:2 | functio ... g();\\n\\t} |
| tst.js:53:3:53:8 | this.g | tst.js:56:39:56:51 | function() {} |
| tst.js:53:3:53:8 | this.g | tst.js:57:39:57:51 | function() {} |
| tst.js:56:1:56:1 | B | tst.js:50:1:50:15 | function B() {} |
| tst.js:56:1:57:51 | B.proto ... on() {} | tst.js:56:39:56:51 | function() {} |
| tst.js:56:1:57:51 | B.proto ... on() {} | tst.js:57:39:57:51 | function() {} |
| tst.js:56:17:57:51 | Math.ra ... on() {} | tst.js:56:39:56:51 | function() {} |
| tst.js:56:17:57:51 | Math.ra ... on() {} | tst.js:57:39:57:51 | function() {} |
| tst.js:56:39:56:51 | function() {} | tst.js:56:39:56:51 | function() {} |
| tst.js:57:39:57:51 | function() {} | tst.js:57:39:57:51 | function() {} |
| tst.js:59:1:59:15 | function C() {} | tst.js:59:1:59:15 | function C() {} |
| tst.js:60:1:60:1 | C | tst.js:59:1:59:15 | function C() {} |
| tst.js:60:19:60:19 | A | tst.js:44:1:44:15 | function A() {} |
| tst.js:61:1:61:1 | C | tst.js:59:1:59:15 | function C() {} |
| tst.js:61:1:61:29 | C.proto ... on() {} | tst.js:61:17:61:29 | function() {} |
| tst.js:61:17:61:29 | function() {} | tst.js:61:17:61:29 | function() {} |
| tst.js:63:1:67:2 | (functi ... f();\\n}) | tst.js:63:2:67:1 | functio ... .f();\\n} |
| tst.js:63:2:67:1 | functio ... .f();\\n} | tst.js:63:2:67:1 | functio ... .f();\\n} |
| tst.js:64:17:64:17 | B | tst.js:50:1:50:15 | function B() {} |
| tst.js:65:5:65:23 | b.f = function() {} | tst.js:65:11:65:23 | function() {} |
| tst.js:65:11:65:23 | function() {} | tst.js:65:11:65:23 | function() {} |
| tst.js:66:5:66:7 | b.f | tst.js:65:11:65:23 | function() {} |
| tst.js:69:1:69:8 | globalfn | tst3.js:1:1:1:22 | functio ... fn() {} |
| tst.js:70:1:70:9 | globalfn2 | tst3.js:2:1:2:23 | functio ... n2() {} |

View File

@@ -0,0 +1,4 @@
import javascript
from DataFlow::Node node
select node, node.getAFunctionValue()

View File

@@ -0,0 +1,15 @@
| eval.js:2:11:2:12 | 42 | 42 |
| sources.js:4:12:4:13 | 19 | 19 |
| sources.js:5:4:5:5 | 23 | 23 |
| tst.js:3:9:3:10 | 42 | 42 |
| tst.js:51:11:51:12 | 42 | 42 |
| tst.js:65:9:65:10 | 42 | 42 |
| tst.js:69:11:69:12 | 23 | 23 |
| tst.js:93:6:93:7 | 19 | 19 |
| tst.js:94:6:94:7 | 23 | 23 |
| tst.js:95:6:95:6 | 0 | 0 |
| tst.js:103:6:103:7 | 19 | 19 |
| tst.js:103:10:103:11 | 23 | 23 |
| tst.js:103:14:103:14 | 0 | 0 |
| tst.ts:2:18:2:19 | 42 | 42 |
| tst.ts:8:9:8:10 | 23 | 23 |

View File

@@ -0,0 +1,4 @@
import javascript
from DataFlow::Node node
select node, node.getIntValue()