Skip to content

Commit 042dcf9

Browse files
Jami CogswellJami Cogswell
authored andcommitted
Java: some updates to UrlPathBarrier code
1 parent 052452b commit 042dcf9

File tree

2 files changed

+38
-38
lines changed

2 files changed

+38
-38
lines changed

java/ql/lib/semmle/code/java/JDK.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ class StringLengthMethod extends Method {
3838
StringLengthMethod() { this.hasName("length") and this.getDeclaringType() instanceof TypeString }
3939
}
4040

41+
/** The `contains()` method of the class `java.lang.String`. */
42+
class StringContainsMethod extends Method {
43+
StringContainsMethod() {
44+
this.hasName("contains") and this.getDeclaringType() instanceof TypeString
45+
}
46+
}
47+
4148
/**
4249
* The methods on the class `java.lang.String` that are used to perform partial matches with a specified substring or char.
4350
*/

java/ql/lib/semmle/code/java/security/UrlForward.qll

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,13 @@ private class UrlPathBarrier extends UrlForwardBarrier instanceof PathInjectionS
5858
UrlPathBarrier() {
5959
this instanceof ExactPathMatchSanitizer
6060
or
61-
this instanceof NoEncodingBarrier
61+
this instanceof NoUrlEncodingBarrier
6262
or
63-
this instanceof FullyDecodesBarrier
63+
this instanceof FullyDecodesUrlBarrier
6464
}
6565
}
6666

67+
/** A call to a method that decodes a URL. */
6768
abstract class UrlDecodeCall extends MethodCall { }
6869

6970
private class DefaultUrlDecodeCall extends UrlDecodeCall {
@@ -73,77 +74,69 @@ private class DefaultUrlDecodeCall extends UrlDecodeCall {
7374
}
7475
}
7576

76-
// TODO: this can probably be named/designed better...
77-
abstract class RepeatedStmt extends Stmt { }
77+
/** A repeated call to a method that decodes a URL. */
78+
abstract class RepeatedUrlDecodeCall extends MethodCall { }
7879

79-
private class DefaultRepeatedStmt extends RepeatedStmt instanceof LoopStmt { }
80-
81-
abstract class CheckEncodingCall extends MethodCall { }
82-
83-
private class DefaultCheckEncodingCall extends CheckEncodingCall {
84-
DefaultCheckEncodingCall() {
85-
// TODO: indexOf?, etc.
86-
this.getMethod().hasQualifiedName("java.lang", "String", "contains") and // TODO: reuse existing class? Or make this a class?
87-
this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "%"
80+
private class DefaultRepeatedUrlDecodeCall extends RepeatedUrlDecodeCall {
81+
DefaultRepeatedUrlDecodeCall() {
82+
this instanceof UrlDecodeCall and
83+
this.getAnEnclosingStmt() instanceof LoopStmt
8884
}
8985
}
9086

91-
// TODO: better naming?
92-
// TODO: check if any URL decoding implementations _fully_ decode... or if all need to be called in a loop?
93-
// TODO: make this extendable instead of `RepeatedStmt`?
94-
private class RepeatedUrlDecodeCall extends MethodCall {
95-
RepeatedUrlDecodeCall() {
96-
this instanceof UrlDecodeCall and
97-
this.getAnEnclosingStmt() instanceof RepeatedStmt
87+
/** A method call that checks a string for URL encoding. */
88+
abstract class CheckUrlEncodingCall extends MethodCall { }
89+
90+
private class DefaultCheckUrlEncodingCall extends CheckUrlEncodingCall {
91+
DefaultCheckUrlEncodingCall() {
92+
this.getMethod() instanceof StringContainsMethod and
93+
this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "%"
9894
}
9995
}
10096

101-
private class CheckEncodingGuard extends Guard instanceof MethodCall, CheckEncodingCall {
97+
private class CheckUrlEncodingGuard extends Guard instanceof CheckUrlEncodingCall {
10298
Expr getCheckedExpr() { result = this.(MethodCall).getQualifier() }
10399
}
104100

105-
private predicate noEncodingGuard(Guard g, Expr e, boolean branch) {
106-
g instanceof CheckEncodingGuard and
107-
e = g.(CheckEncodingGuard).getCheckedExpr() and
101+
private predicate noUrlEncodingGuard(Guard g, Expr e, boolean branch) {
102+
g instanceof CheckUrlEncodingGuard and
103+
e = g.(CheckUrlEncodingGuard).getCheckedExpr() and
108104
branch = false
109105
or
110-
// branch = false and
111-
// g instanceof AssignExpr and // AssignExpr
112-
// exists(CheckEncodingCall call | g.(AssignExpr).getSource() = call | e = call.getQualifier())
113106
branch = false and
114-
g.(Expr).getType() instanceof BooleanType and // AssignExpr
107+
g.(Expr).getType() instanceof BooleanType and // TODO: remove debugging comment: // AssignExpr
115108
(
116-
exists(CheckEncodingCall call, AssignExpr ae |
109+
exists(CheckUrlEncodingCall call, AssignExpr ae |
117110
ae.getSource() = call and
118111
e = call.getQualifier() and
119112
g = ae.getDest()
120113
)
121114
or
122-
exists(CheckEncodingCall call, LocalVariableDeclExpr vde |
115+
exists(CheckUrlEncodingCall call, LocalVariableDeclExpr vde |
123116
vde.getInitOrPatternSource() = call and
124117
e = call.getQualifier() and
125118
g = vde.getAnAccess() //and
126119
//vde.getVariable() = g
120+
// TODO: remove debugging comments above
127121
)
128122
)
129123
}
130124

131-
// TODO: check edge case of !contains(%), make sure that behaves as expected at least.
132-
private class NoEncodingBarrier extends DataFlow::Node {
133-
NoEncodingBarrier() { this = DataFlow::BarrierGuard<noEncodingGuard/3>::getABarrierNode() }
125+
private class NoUrlEncodingBarrier extends DataFlow::Node {
126+
NoUrlEncodingBarrier() { this = DataFlow::BarrierGuard<noUrlEncodingGuard/3>::getABarrierNode() }
134127
}
135128

136-
private predicate fullyDecodesGuard(Expr e) {
137-
exists(CheckEncodingGuard g, RepeatedUrlDecodeCall decodeCall |
129+
private predicate fullyDecodesUrlGuard(Expr e) {
130+
exists(CheckUrlEncodingGuard g, RepeatedUrlDecodeCall decodeCall |
138131
e = g.getCheckedExpr() and
139132
g.controls(decodeCall.getBasicBlock(), true)
140133
)
141134
}
142135

143-
private class FullyDecodesBarrier extends DataFlow::Node {
144-
FullyDecodesBarrier() {
136+
private class FullyDecodesUrlBarrier extends DataFlow::Node {
137+
FullyDecodesUrlBarrier() {
145138
exists(Variable v, Expr e | this.asExpr() = v.getAnAccess() |
146-
fullyDecodesGuard(e) and
139+
fullyDecodesUrlGuard(e) and
147140
e = v.getAnAccess() and
148141
e.getBasicBlock().bbDominates(this.asExpr().getBasicBlock())
149142
)

0 commit comments

Comments
 (0)