mirror of
https://github.com/github/codeql.git
synced 2026-02-19 16:33:40 +01:00
add experimental global flow config, and clean-up some code
This commit is contained in:
committed by
Tony Torralba
parent
9947b32446
commit
6cf3898101
@@ -1327,6 +1327,10 @@ class ClassInstanceExpr extends Expr, ConstructorCall, @classinstancexpr {
|
||||
arg.getType() = type and
|
||||
result = arg
|
||||
)
|
||||
// ! e.g. use above in below code in `StartActivityIntentStep` in Intent.qll
|
||||
// argType.getName().matches("Class<%>") and
|
||||
// newIntent.getArgumentByType(argType).getType().(ParameterizedType).getATypeArgument() =
|
||||
// getIntent.getReceiverType() and
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,9 @@ private import semmle.code.java.frameworks.android.Intent
|
||||
//private import semmle.code.java.frameworks.android.AsyncTask
|
||||
private import semmle.code.java.frameworks.android.Android
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
//private import semmle.code.java.dataflow.DataFlow2
|
||||
private import semmle.code.java.dataflow.FlowSteps
|
||||
//private import semmle.code.java.dataflow.FlowSources
|
||||
//private import semmle.code.java.dataflow.ExternalFlow
|
||||
//private import semmle.code.java.dataflow.TaintTracking
|
||||
private import semmle.code.xml.AndroidManifest
|
||||
@@ -37,31 +39,71 @@ private class DeepLinkIntentStep extends AdditionalValueStep {
|
||||
) and
|
||||
exists(AndroidComponent andComp |
|
||||
andComp.getAndroidComponentXmlElement().(AndroidActivityXmlElement).hasDeepLink() and
|
||||
n1.asExpr().getFile() = andComp.getFile() // ! ugly, see if better way to do this
|
||||
n1.asExpr().getFile() = andComp.getFile() // ! see if better way to do this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ! experimentation with global flow issue - REMOVE
|
||||
/**
|
||||
* A value-preserving step from the Intent variable
|
||||
* the `Intent` Parameter in the `startActivity`.
|
||||
*/
|
||||
class IntentVariableToStartActivityStep extends AdditionalValueStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(MethodAccess startActivity, Variable intentTypeTest |
|
||||
// // ! experimentation with global flow issue - REMOVE
|
||||
// /**
|
||||
// * A value-preserving step from the Intent variable
|
||||
// * the `Intent` Parameter in the `startActivity`.
|
||||
// */
|
||||
// class IntentVariableToStartActivityStep extends AdditionalValueStep {
|
||||
// override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
// exists(
|
||||
// MethodAccess startActivity, Variable intentTypeTest, DataFlow2::Node source,
|
||||
// DataFlow2::Node sink //ClassInstanceExpr intentTypeTest |
|
||||
// |
|
||||
// (
|
||||
// startActivity.getMethod().overrides*(any(ContextStartActivityMethod m)) or
|
||||
// startActivity.getMethod().overrides*(any(ActivityStartActivityMethod m))
|
||||
// ) and
|
||||
// intentTypeTest.getType() instanceof TypeIntent and // Variable
|
||||
// //intentTypeTest.getConstructedType() instanceof TypeIntent and // ClassInstanceExpr
|
||||
// startActivity.getFile().getBaseName() = "MainActivity.java" and // ! REMOVE - for testing only
|
||||
// //exists(StartComponentConfiguration cfg | cfg.hasFlow(source, sink)) and // GLOBAL FLOW ATTEMPT
|
||||
// DataFlow::localExprFlow(intentTypeTest.getInitializer(), startActivity.getArgument(0)) and // Variable - gives 5 results - misses the 1st ProfileActivity result since no variable with that one
|
||||
// //DataFlow::localExprFlow(intentTypeTest, startActivity.getArgument(0)) and // ClassInstanceExpr
|
||||
// n1.asExpr() = intentTypeTest.getInitializer() and // Variable
|
||||
// //n1.asExpr() = intentTypeTest and // ClassInstanceExpr
|
||||
// n2.asExpr() = startActivity.getArgument(0) // ! switch to getStartActivityIntentArg(startActivity)
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// ! rename?
|
||||
// ! below works as intended when run by itself (see latest query in AndroidDeeplinks_RemoteSources.ql),
|
||||
// ! but not when combined with existing flow steps (non-monotonic recursion)
|
||||
// ! need to figure out how to combine, or wrap all in global flow?
|
||||
class StartComponentConfiguration extends DataFlow::Configuration {
|
||||
StartComponentConfiguration() { this = "StartComponentConfiguration" }
|
||||
|
||||
// Override `isSource` and `isSink`.
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists(ClassInstanceExpr classInstanceExpr |
|
||||
classInstanceExpr.getConstructedType() instanceof TypeIntent and
|
||||
source.asExpr() = classInstanceExpr
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess startActivity |
|
||||
// ! need to handle for all components, not just Activity
|
||||
(
|
||||
// ! is there a better way to do this?
|
||||
startActivity.getMethod().overrides*(any(ContextStartActivityMethod m)) or
|
||||
startActivity.getMethod().overrides*(any(ActivityStartActivityMethod m))
|
||||
) and
|
||||
intentTypeTest.getType() instanceof TypeIntent and
|
||||
//startActivity.getFile().getBaseName() = "MainActivity.java" and // ! REMOVE
|
||||
DataFlow::localExprFlow(intentTypeTest.getInitializer(), startActivity.getArgument(0)) and
|
||||
n1.asExpr() = intentTypeTest.getInitializer() and
|
||||
n2.asExpr() = startActivity.getArgument(0) // ! switch to getStartActivityIntentArg(startActivity)
|
||||
sink.asExpr() = startActivity.getArgument(0)
|
||||
)
|
||||
}
|
||||
// Optionally override `isBarrier`.
|
||||
// Optionally override `isAdditionalFlowStep`.
|
||||
// Then, to query whether there is flow between some `source` and `sink`,
|
||||
// write
|
||||
//
|
||||
// ```ql
|
||||
// exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
|
||||
// ```
|
||||
}
|
||||
|
||||
/* ********************* INTENT METHODS, E.G. parseUri, getData, getExtras, etc. ********************* */
|
||||
@@ -95,61 +137,8 @@ class AndroidGetDataMethod extends Method {
|
||||
*/
|
||||
class AndroidParseUriMethod extends Method {
|
||||
AndroidParseUriMethod() {
|
||||
(this.hasName("parseUri") or this.hasName("getIntent")) and // ! Note to self: getIntent for older versions before deprecation to parseUri
|
||||
// ! Note to self: getIntent for older versions before deprecation to parseUri
|
||||
(this.hasName("parseUri") or this.hasName("getIntent")) and
|
||||
this.getDeclaringType() instanceof TypeIntent
|
||||
}
|
||||
}
|
||||
// /**
|
||||
// * A taint step from the Intent argument of a `startActivity` call to
|
||||
// * a `Intent.parseUri` call in the Activity the Intent pointed to in its constructor.
|
||||
// */
|
||||
// private class StartActivityParseUriStep extends AdditionalTaintStep {
|
||||
// override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
// exists(MethodAccess startActivity, MethodAccess parseUri, ClassInstanceExpr newIntent |
|
||||
// startActivity.getMethod().overrides*(any(ContextStartActivityMethod m)) and
|
||||
// parseUri.getMethod().overrides*(any(AndroidParseUriMethod m)) and
|
||||
// newIntent.getConstructedType() instanceof TypeIntent and
|
||||
// DataFlow::localExprFlow(newIntent, startActivity.getArgument(0)) and
|
||||
// newIntent.getArgument(1).getType().(ParameterizedType).getATypeArgument() =
|
||||
// parseUri.getReceiverType() and
|
||||
// n1.asExpr() = startActivity.getArgument(0) and
|
||||
// n2.asExpr() = parseUri
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// /**
|
||||
// * A taint step from the Intent argument of a `startActivity` call to
|
||||
// * a `Intent.get%Extra%` call in the Activity the Intent pointed to in its constructor.
|
||||
// */
|
||||
// private class StartActivityGetDataStep extends AdditionalTaintStep {
|
||||
// override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
// exists(MethodAccess startActivity, MethodAccess getData, ClassInstanceExpr newIntent |
|
||||
// startActivity.getMethod().overrides*(any(ContextStartActivityMethod m)) and
|
||||
// getData.getMethod().overrides*(any(AndroidGetDataMethod m)) and
|
||||
// newIntent.getConstructedType() instanceof TypeIntent and
|
||||
// DataFlow::localExprFlow(newIntent, startActivity.getArgument(0)) and
|
||||
// newIntent.getArgument(1).getType().(ParameterizedType).getATypeArgument() =
|
||||
// getData.getReceiverType() and
|
||||
// n1.asExpr() = startActivity.getArgument(0) and
|
||||
// n2.asExpr() = getData
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// /**
|
||||
// * A taint step from the Intent argument of a `startActivity` call to
|
||||
// * a `Intent.getData` call in the Activity the Intent pointed to in its constructor.
|
||||
// */
|
||||
// private class StartActivityGetExtrasStep extends AdditionalTaintStep {
|
||||
// override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
// exists(MethodAccess startActivity, MethodAccess getExtras, ClassInstanceExpr newIntent |
|
||||
// startActivity.getMethod().overrides*(any(ContextStartActivityMethod m)) and
|
||||
// getExtras.getMethod().overrides*(any(AndroidGetExtrasMethod m)) and
|
||||
// newIntent.getConstructedType() instanceof TypeIntent and
|
||||
// DataFlow::localExprFlow(newIntent, startActivity.getArgument(0)) and
|
||||
// newIntent.getArgument(1).getType().(ParameterizedType).getATypeArgument() =
|
||||
// getExtras.getReceiverType() and
|
||||
// n1.asExpr() = startActivity.getArgument(0) and
|
||||
// n2.asExpr() = getExtras
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import java
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
//private import semmle.code.java.dataflow.DataFlow2
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.FlowSteps
|
||||
private import semmle.code.java.frameworks.android.DeepLink
|
||||
|
||||
// ! Remember to add 'private' annotation as needed to all new classes/predicates below.
|
||||
// ! Remember to add 'private' annotation as needed to new classes/predicates below.
|
||||
// ! and clean-up comments, etc. in below in general...
|
||||
/**
|
||||
* The class `android.content.Intent`.
|
||||
@@ -119,24 +121,31 @@ class ContextStartActivityMethod extends Method {
|
||||
}
|
||||
}
|
||||
|
||||
// ! finish QLDoc
|
||||
// ! maybe reword below QLDoc?
|
||||
/**
|
||||
* The method `Activity.startActivity` or ...
|
||||
* The method `Activity.startActivity`,`startActivities`,
|
||||
* `startActivityForResult`, `startActivityIfNeeded`,
|
||||
* `startNextMatchingActivity`, `startActivityFromChild`,
|
||||
* or `startActivityFromFragment`.
|
||||
*/
|
||||
class ActivityStartActivityMethod extends Method {
|
||||
ActivityStartActivityMethod() {
|
||||
// ! captures all `startAct` methods in the Activity class
|
||||
this.getName().matches("start%Activit%") and // ! better to list all instead of using matches for any reason?
|
||||
this.getName().matches("start%Activit%") and
|
||||
this.getDeclaringType() instanceof TypeActivity
|
||||
}
|
||||
}
|
||||
|
||||
// ! maybe reword below QLDoc?
|
||||
/**
|
||||
* The method `Context.sendBroadcast`.
|
||||
* The method `Context.sendBroadcast`, `sendBroadcastAsUser`,
|
||||
* `sendOrderedBroadcast`, `sendOrderedBroadcastAsUser`,
|
||||
* `sendStickyBroadcast`, `sendStickyBroadcastAsUser`,
|
||||
* `sendStickyOrderedBroadcast`, `sendStickyOrderedBroadcastAsUser`,
|
||||
* or `sendBroadcastWithMultiplePermissions`.
|
||||
*/
|
||||
class ContextSendBroadcastMethod extends Method {
|
||||
ContextSendBroadcastMethod() {
|
||||
this.getName().matches("send%Broadcast%") and // ! Note to self: matches the 9 sendBroadcast methods
|
||||
this.getName().matches("send%Broadcast%") and
|
||||
this.getDeclaringType() instanceof TypeContext
|
||||
}
|
||||
}
|
||||
@@ -322,7 +331,7 @@ class StartActivityIntentStep extends AdditionalValueStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(MethodAccess startActivity, MethodAccess getIntent, ClassInstanceExpr newIntent |
|
||||
(
|
||||
// ! is there a better way to do this?
|
||||
// ! look for better way to handle the below
|
||||
startActivity.getMethod().overrides*(any(ContextStartActivityMethod m)) or
|
||||
startActivity.getMethod().overrides*(any(ActivityStartActivityMethod m))
|
||||
) and
|
||||
@@ -331,10 +340,6 @@ class StartActivityIntentStep extends AdditionalValueStep {
|
||||
DataFlow::localExprFlow(newIntent, getStartActivityIntentArg(startActivity)) and
|
||||
getIntentConstructorClassArg(newIntent).getType().(ParameterizedType).getATypeArgument() =
|
||||
getIntent.getReceiverType() and
|
||||
// ! below uses predicate `getArgumentByType` that I added to the Expr.qll lib, prbly should not add new predicate there.
|
||||
// argType.getName().matches("Class<%>") and
|
||||
// newIntent.getArgumentByType(argType).getType().(ParameterizedType).getATypeArgument() =
|
||||
// getIntent.getReceiverType() and
|
||||
n1.asExpr() = getStartActivityIntentArg(startActivity) and
|
||||
n2.asExpr() = getIntent
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user