forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStrings.qll
More file actions
117 lines (101 loc) · 3.79 KB
/
Strings.qll
File metadata and controls
117 lines (101 loc) · 3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/**
* Contains flow summaries and steps modelling flow through string methods.
*/
private import javascript
private import semmle.javascript.dataflow.FlowSummary
/**
* Summary for calls to `.replace` or `.replaceAll` (without a regexp pattern containing a wildcard).
*/
private class StringReplaceNoWildcard extends SummarizedCallable {
StringReplaceNoWildcard() {
this = "String#replace / String#replaceAll (without wildcard pattern)"
}
override StringReplaceCall getACall() { not result.hasRegExpContainingWildcard() }
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
preservesValue = false and
(
input = "Argument[this]" and
output = "ReturnValue"
or
input = "Argument[1].ReturnValue" and
output = "ReturnValue"
)
}
}
/**
* Summary for calls to `.replace` or `.replaceAll` (with a regexp pattern containing a wildcard).
*
* In this case, the receiver is considered to flow into the callback.
*/
private class StringReplaceWithWildcard extends SummarizedCallable {
StringReplaceWithWildcard() {
this = "String#replace / String#replaceAll (with wildcard pattern)"
}
override StringReplaceCall getACall() { result.hasRegExpContainingWildcard() }
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
preservesValue = false and
(
input = "Argument[this]" and
output = ["ReturnValue", "Argument[1].Parameter[0]"]
or
input = "Argument[1].ReturnValue" and
output = "ReturnValue"
)
}
}
class StringSplit extends SummarizedCallable {
StringSplit() { this = "String#split" }
override DataFlow::MethodCallNode getACallSimple() {
result.getMethodName() = "split" and
result.getNumArgument() = [1, 2] and
not result.getArgument(0).getStringValue() = ["#", "?"]
}
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
preservesValue = false and
input = "Argument[this]" and
output = "ReturnValue.ArrayElement"
}
}
/**
* A call of form `x.split("#")` or `x.split("?")`.
*
* These are of special significance when tracking a tainted URL suffix, such as `window.location.href`,
* because the first element of the resulting array should not be considered tainted.
*
* This summary defaults to the same behaviour as the general `.split()` case, but it contains optional steps
* and barriers named `tainted-url-suffix` that should be activated when tracking a tainted URL suffix.
*/
class StringSplitHashOrQuestionMark extends SummarizedCallable {
StringSplitHashOrQuestionMark() { this = "String#split with '#' or '?'" }
override DataFlow::MethodCallNode getACallSimple() {
result.getMethodName() = "split" and
result.getNumArgument() = [1, 2] and
result.getArgument(0).getStringValue() = ["#", "?"]
}
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
preservesValue = false and
(
input = "Argument[this].OptionalBarrier[split-url-suffix]" and
output = "ReturnValue.ArrayElement"
or
input = "Argument[this].OptionalStep[split-url-suffix-pre]" and
output = "ReturnValue.ArrayElement[0]"
or
input = "Argument[this].OptionalStep[split-url-suffix-post]" and
output = "ReturnValue.ArrayElement[1]" // TODO: support ArrayElement[1..]
)
}
}
class StringFromCharCode extends SummarizedCallable {
StringFromCharCode() { this = "String#fromCharCode" }
override DataFlow::CallNode getACall() {
result = DataFlow::globalVarRef("String").getAPropertyRead("fromCharCode").getACall()
}
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
preservesValue = true and
(
input = "Argument[0..]" and
output = "ReturnValue"
)
}
}