Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d9d8eb4

Browse files
committed
JS: avoid type inference in the taint steps (just a nice to have)
1 parent fa4e891 commit d9d8eb4

3 files changed

Lines changed: 37 additions & 90 deletions

File tree

javascript/ql/src/Security/CWE-770/MemoryExhaustion.ql

Lines changed: 32 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -66,52 +66,15 @@ class Configuration extends TaintTracking::Configuration {
6666
DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel,
6767
DataFlow::FlowLabel dstlabel
6868
) {
69-
exists(Expr dstExpr, Expr srcExpr | dstExpr = dst.asExpr() and srcExpr = src.asExpr() |
70-
// reuse taint steps
71-
super.isAdditionalFlowStep(src, dst) and
72-
(
73-
srclabel = dstlabel and
74-
not dstExpr instanceof AddExpr and
75-
not dst.(DataFlow::MethodCallNode).calls(src, "toString")
76-
or
77-
dstlabel.isTaint() and
78-
dst.(DataFlow::MethodCallNode).calls(src, "toString")
79-
or
80-
// this conversion step is probably covered below
81-
dstlabel instanceof Label::Number and dst.(AnalyzedNode).getTheType() = TTNumber()
82-
)
83-
or
84-
//
85-
// steps that introduce or preserve a number
86-
dstlabel instanceof Label::Number and
87-
(
88-
dst.(DataFlow::PropRead).accesses(src, ["length", "size"])
89-
or
90-
dstExpr.(BinaryExpr).getAnOperand() = srcExpr and
91-
not dstExpr instanceof AddExpr
92-
or
93-
dstExpr.(PlusExpr).getOperand() = srcExpr
94-
or
95-
exists(DataFlow::CallNode c |
96-
c = dst and
97-
src = c.getAnArgument()
98-
|
99-
c = DataFlow::globalVarRef("Math").getAMemberCall(_) or
100-
c = DataFlow::globalVarRef(["Number", "parseInt", "parseFloat"]).getACall()
101-
)
102-
)
103-
or
104-
// optimistic propagation through plus if either operand is a number
105-
exists(Expr operand | dstExpr.(AddExpr).hasOperands(operand, srcExpr) |
106-
operand.analyze().getTheType() = TTNumber()
107-
or
108-
operand.flow().getALocalSource().(DataFlow::PropRead).getPropertyName() = "length"
109-
or
110-
srclabel instanceof Label::Number and
111-
// unless the result provably is a string
112-
not operand.analyze().getTheType() = TTString()
113-
)
114-
)
69+
dstlabel instanceof Label::Number and
70+
isNumericFlowStep(src, dst)
71+
or
72+
// reuse taint steps
73+
super.isAdditionalFlowStep(src, dst) and
74+
not dst.asExpr() instanceof AddExpr and
75+
if dst.(DataFlow::MethodCallNode).calls(src, "toString")
76+
then dstlabel.isTaint()
77+
else srclabel = dstlabel
11578
}
11679

11780
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) {
@@ -121,6 +84,29 @@ class Configuration extends TaintTracking::Configuration {
12184
}
12285
}
12386

87+
predicate isNumericFlowStep(DataFlow::Node src, DataFlow::Node dst) {
88+
// steps that introduce or preserve a number
89+
dst.(DataFlow::PropRead).accesses(src, ["length", "size"])
90+
or
91+
exists(DataFlow::CallNode c |
92+
c = dst and
93+
src = c.getAnArgument()
94+
|
95+
c = DataFlow::globalVarRef("Math").getAMemberCall(_) or
96+
c = DataFlow::globalVarRef(["Number", "parseInt", "parseFloat"]).getACall()
97+
)
98+
or
99+
exists(Expr dstExpr, Expr srcExpr |
100+
dstExpr = dst.asExpr() and
101+
srcExpr = src.asExpr()
102+
|
103+
dstExpr.(BinaryExpr).getAnOperand() = srcExpr and
104+
not dstExpr instanceof AddExpr
105+
or
106+
dstExpr.(PlusExpr).getOperand() = srcExpr
107+
)
108+
}
109+
124110
/**
125111
* A sanitizer that blocks taint flow if the size of a number is limited.
126112
*/

javascript/ql/test/query-tests/Security/CWE-770/MemoryExhaustion.expected

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -43,28 +43,12 @@ nodes
4343
| memory-exhaustion.js:38:14:38:14 | n |
4444
| memory-exhaustion.js:38:14:38:18 | n * x |
4545
| memory-exhaustion.js:38:14:38:18 | n * x |
46-
| memory-exhaustion.js:39:14:39:14 | n |
47-
| memory-exhaustion.js:39:14:39:18 | n + n |
48-
| memory-exhaustion.js:39:14:39:18 | n + n |
49-
| memory-exhaustion.js:39:18:39:18 | n |
50-
| memory-exhaustion.js:40:14:40:14 | n |
51-
| memory-exhaustion.js:40:14:40:18 | n + x |
52-
| memory-exhaustion.js:40:14:40:18 | n + x |
53-
| memory-exhaustion.js:41:14:41:14 | n |
54-
| memory-exhaustion.js:41:14:41:18 | n + s |
55-
| memory-exhaustion.js:41:14:41:18 | n + s |
56-
| memory-exhaustion.js:42:14:42:14 | s |
57-
| memory-exhaustion.js:42:14:42:18 | s + 2 |
58-
| memory-exhaustion.js:42:14:42:18 | s + 2 |
5946
| memory-exhaustion.js:46:14:46:25 | Math.ceil(s) |
6047
| memory-exhaustion.js:46:14:46:25 | Math.ceil(s) |
6148
| memory-exhaustion.js:46:24:46:24 | s |
6249
| memory-exhaustion.js:47:14:47:22 | Number(s) |
6350
| memory-exhaustion.js:47:14:47:22 | Number(s) |
6451
| memory-exhaustion.js:47:21:47:21 | s |
65-
| memory-exhaustion.js:50:14:50:14 | s |
66-
| memory-exhaustion.js:50:14:50:25 | s + x.length |
67-
| memory-exhaustion.js:50:14:50:25 | s + x.length |
6852
| memory-exhaustion.js:51:14:51:14 | s |
6953
| memory-exhaustion.js:51:14:51:21 | s.length |
7054
| memory-exhaustion.js:51:14:51:21 | s.length |
@@ -83,10 +67,8 @@ edges
8367
| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:7:20:7:20 | s |
8468
| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:36:12:36:12 | s |
8569
| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:36:12:36:12 | s |
86-
| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:42:14:42:14 | s |
8770
| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:46:24:46:24 | s |
8871
| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:47:21:47:21 | s |
89-
| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:50:14:50:14 | s |
9072
| memory-exhaustion.js:6:7:6:42 | s | memory-exhaustion.js:51:14:51:14 | s |
9173
| memory-exhaustion.js:6:11:6:34 | url.par ... , true) | memory-exhaustion.js:6:11:6:40 | url.par ... ).query |
9274
| memory-exhaustion.js:6:11:6:40 | url.par ... ).query | memory-exhaustion.js:6:11:6:42 | url.par ... query.s |
@@ -124,10 +106,6 @@ edges
124106
| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:35:12:35:12 | n |
125107
| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:35:12:35:12 | n |
126108
| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:38:14:38:14 | n |
127-
| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:39:14:39:14 | n |
128-
| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:39:18:39:18 | n |
129-
| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:40:14:40:14 | n |
130-
| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:41:14:41:14 | n |
131109
| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:56:16:56:16 | n |
132110
| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:56:16:56:16 | n |
133111
| memory-exhaustion.js:7:7:7:21 | n | memory-exhaustion.js:59:16:59:16 | n |
@@ -139,22 +117,10 @@ edges
139117
| memory-exhaustion.js:7:20:7:20 | s | memory-exhaustion.js:7:11:7:21 | parseInt(s) |
140118
| memory-exhaustion.js:38:14:38:14 | n | memory-exhaustion.js:38:14:38:18 | n * x |
141119
| memory-exhaustion.js:38:14:38:14 | n | memory-exhaustion.js:38:14:38:18 | n * x |
142-
| memory-exhaustion.js:39:14:39:14 | n | memory-exhaustion.js:39:14:39:18 | n + n |
143-
| memory-exhaustion.js:39:14:39:14 | n | memory-exhaustion.js:39:14:39:18 | n + n |
144-
| memory-exhaustion.js:39:18:39:18 | n | memory-exhaustion.js:39:14:39:18 | n + n |
145-
| memory-exhaustion.js:39:18:39:18 | n | memory-exhaustion.js:39:14:39:18 | n + n |
146-
| memory-exhaustion.js:40:14:40:14 | n | memory-exhaustion.js:40:14:40:18 | n + x |
147-
| memory-exhaustion.js:40:14:40:14 | n | memory-exhaustion.js:40:14:40:18 | n + x |
148-
| memory-exhaustion.js:41:14:41:14 | n | memory-exhaustion.js:41:14:41:18 | n + s |
149-
| memory-exhaustion.js:41:14:41:14 | n | memory-exhaustion.js:41:14:41:18 | n + s |
150-
| memory-exhaustion.js:42:14:42:14 | s | memory-exhaustion.js:42:14:42:18 | s + 2 |
151-
| memory-exhaustion.js:42:14:42:14 | s | memory-exhaustion.js:42:14:42:18 | s + 2 |
152120
| memory-exhaustion.js:46:24:46:24 | s | memory-exhaustion.js:46:14:46:25 | Math.ceil(s) |
153121
| memory-exhaustion.js:46:24:46:24 | s | memory-exhaustion.js:46:14:46:25 | Math.ceil(s) |
154122
| memory-exhaustion.js:47:21:47:21 | s | memory-exhaustion.js:47:14:47:22 | Number(s) |
155123
| memory-exhaustion.js:47:21:47:21 | s | memory-exhaustion.js:47:14:47:22 | Number(s) |
156-
| memory-exhaustion.js:50:14:50:14 | s | memory-exhaustion.js:50:14:50:25 | s + x.length |
157-
| memory-exhaustion.js:50:14:50:14 | s | memory-exhaustion.js:50:14:50:25 | s + x.length |
158124
| memory-exhaustion.js:51:14:51:14 | s | memory-exhaustion.js:51:14:51:21 | s.length |
159125
| memory-exhaustion.js:51:14:51:14 | s | memory-exhaustion.js:51:14:51:21 | s.length |
160126
| memory-exhaustion.js:59:7:59:20 | ns | memory-exhaustion.js:60:14:60:15 | ns |
@@ -179,13 +145,8 @@ edges
179145
| 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 |
180146
| 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 |
181147
| 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 |
182-
| memory-exhaustion.js:39:14:39:18 | n + n | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:39:14:39:18 | n + n | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
183-
| memory-exhaustion.js:40:14:40:18 | n + x | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:40:14:40:18 | n + x | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
184-
| memory-exhaustion.js:41:14:41:18 | n + s | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:41:14:41:18 | n + s | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
185-
| memory-exhaustion.js:42:14:42:18 | s + 2 | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:42:14:42:18 | s + 2 | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
186148
| 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 |
187149
| 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 |
188-
| memory-exhaustion.js:50:14:50:25 | s + x.length | memory-exhaustion.js:6:21:6:27 | req.url | memory-exhaustion.js:50:14:50:25 | s + x.length | This allocates an object with a user-controlled size from $@. | memory-exhaustion.js:6:21:6:27 | req.url | here |
189150
| 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 |
190151
| 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 |
191152
| 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 |

javascript/ql/test/query-tests/Security/CWE-770/memory-exhaustion.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,18 @@ var server = http.createServer(function(req, res) {
3636
x.repeat(s); // NOT OK
3737

3838
new Buffer(n * x); // NOT OK
39-
new Buffer(n + n); // NOT OK
40-
new Buffer(n + x); // NOT OK (maybe)
41-
new Buffer(n + s); // OK [INCONSISTENCY]: this is a string if `s` is a string
42-
new Buffer(s + 2); // OK [INCONSISTENCY]: this is a string if `s` is a string
39+
new Buffer(n + n); // NOT OK [INCONSISTENCY]
40+
new Buffer(n + x); // OK (maybe)
41+
new Buffer(n + s); // OK (this is a string if `s` is a string)
42+
new Buffer(s + 2); // OK (this is a string if `s` is a string)
4343
new Buffer(s + s); // OK
4444
new Buffer(n + "X"); // OK
4545

4646
new Buffer(Math.ceil(s)); // NOT OK
4747
new Buffer(Number(s)); // NOT OK
4848
new Buffer(new Number(s)); // OK
4949

50-
new Buffer(s + x.length); // OK [INCONSISTENCY]: this is a string if `s` is a string
50+
new Buffer(s + x.length); // OK (this is a string if `s` is a string)
5151
new Buffer(s.length); // NOT OK
5252

5353
if (n < 100) {

0 commit comments

Comments
 (0)