Skip to content

Commit 4e9849e

Browse files
committed
Refactor IntentFlagsOrDataCheckedGuard to avoid footgun
1 parent 62c2191 commit 4e9849e

File tree

1 file changed

+35
-32
lines changed

1 file changed

+35
-32
lines changed

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

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
import java
7+
private import semmle.code.java.controlflow.Guards
78
private import semmle.code.java.dataflow.DataFlow
89
private import semmle.code.java.dataflow.TaintTracking
910
private import semmle.code.java.frameworks.android.Android
@@ -85,38 +86,40 @@ private class IntentFlagsOrDataChangedSanitizer extends IntentUriPermissionManip
8586
private class IntentFlagsOrDataCheckedGuard extends IntentUriPermissionManipulationGuard {
8687
Expr condition;
8788

88-
IntentFlagsOrDataCheckedGuard() {
89-
this.(MethodAccess).getMethod() instanceof EqualsMethod and
90-
condition = [this.(MethodAccess).getArgument(0), this.(MethodAccess).getQualifier()]
91-
or
92-
condition = this.(EqualityTest).getAnOperand().(AndBitwiseExpr)
93-
}
89+
IntentFlagsOrDataCheckedGuard() { intentFlagsOrDataChecked(this, _, _) }
9490

95-
override predicate checks(Expr e, boolean branch) {
96-
exists(MethodAccess ma, Method m |
97-
// This checks `intent` when the result of an `intent.getFlags` or `intent.getData` call flows to `condition`
98-
// (i.e., that result is equality-tested)
99-
ma.getMethod() = m and
100-
m.getDeclaringType() instanceof TypeIntent and
101-
m.hasName(["getFlags", "getData"]) and
102-
TaintTracking::localExprTaint(ma, condition) and
103-
ma.getQualifier() = e
104-
|
105-
bitwiseCheck(branch)
106-
or
107-
this.(MethodAccess).getMethod() instanceof EqualsMethod and branch = true
108-
)
109-
}
91+
override predicate checks(Expr e, boolean branch) { intentFlagsOrDataChecked(this, e, branch) }
92+
}
11093

111-
/**
112-
* Holds if `this` is a bitwise check. `branch` is `true` when the expected value is `0`
113-
* and `false` otherwise.
114-
*/
115-
private predicate bitwiseCheck(boolean branch) {
116-
exists(CompileTimeConstantExpr operand | operand = this.(EqualityTest).getAnOperand() |
117-
if operand.getIntValue() = 0
118-
then this.(EqualityTest).polarity() = branch
119-
else this.(EqualityTest).polarity().booleanNot() = branch
120-
)
121-
}
94+
/**
95+
* Holds if `g` checks `intent` when the result of an `intent.getFlags` or `intent.getData` call
96+
* is equality-tested.
97+
*/
98+
private predicate intentFlagsOrDataChecked(Guard g, Expr intent, boolean branch) {
99+
exists(MethodAccess ma, Method m, Expr checkedValue |
100+
ma.getQualifier() = intent and
101+
ma.getMethod() = m and
102+
m.getDeclaringType() instanceof TypeIntent and
103+
m.hasName(["getFlags", "getData"]) and
104+
TaintTracking::localExprTaint(ma, checkedValue)
105+
|
106+
bitwiseCheck(g, branch) and
107+
checkedValue = g.(EqualityTest).getAnOperand().(AndBitwiseExpr)
108+
or
109+
g.(MethodAccess).getMethod() instanceof EqualsMethod and
110+
branch = true and
111+
checkedValue = [g.(MethodAccess).getArgument(0), g.(MethodAccess).getQualifier()]
112+
)
113+
}
114+
115+
/**
116+
* Holds if `g` is a bitwise check. `branch` is `true` when the expected value is `0`
117+
* and `false` otherwise.
118+
*/
119+
private predicate bitwiseCheck(Guard g, boolean branch) {
120+
exists(CompileTimeConstantExpr operand | operand = g.(EqualityTest).getAnOperand() |
121+
if operand.getIntValue() = 0
122+
then g.(EqualityTest).polarity() = branch
123+
else g.(EqualityTest).polarity().booleanNot() = branch
124+
)
122125
}

0 commit comments

Comments
 (0)