Skip to content

Commit f209ff4

Browse files
committed
Use synthetic fields to improve taint precision
1 parent b7f7c5b commit f209ff4

File tree

3 files changed

+84
-62
lines changed

3 files changed

+84
-62
lines changed

java/ql/lib/semmle/code/java/frameworks/android/Notifications.qll

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,39 @@
11
/** Provides classes and predicates related to Android notifications. */
22

33
import java
4+
private import semmle.code.java.dataflow.DataFlow
45
private import semmle.code.java.dataflow.ExternalFlow
6+
private import semmle.code.java.dataflow.FlowSteps
7+
8+
private class NotificationActionsInheritTaint extends DataFlow::SyntheticFieldContent,
9+
TaintInheritingContent {
10+
NotificationActionsInheritTaint() { this.getField().matches("android.app.Notification.action") }
11+
}
512

613
private class NotificationBuildersSummaryModels extends SummaryModelCsv {
714
override predicate row(string row) {
815
row =
916
[
10-
"android.app;Notification$Action;true;Action;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint",
11-
"android.app;Notification$Action$Builder;true;Builder;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint",
12-
"android.app;Notification$Action$Builder;true;Builder;(Icon,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint",
13-
"android.app;Notification$Action$Builder;true;Builder;(Action);;Argument[0];Argument[-1];taint",
14-
"android.app;Notification$Action$Builder;true;addExtras;;;MapKey of Argument[0];MapKey of SyntheticField[android.app.NotificationActionBuilder.extras] of Argument[-1];value",
15-
"android.app;Notification$Action$Builder;true;addExtras;;;MapValue of Argument[0];MapValue of SyntheticField[android.app.NotificationActionBuilder.extras] of Argument[-1];value",
16-
"android.app;Notification$Action$Builder;true;build;;;Argument[-1];ReturnValue;taint",
17-
"android.app;Notification$Action$Builder;true;getExtras;;;SyntheticField[android.app.NotificationActionBuilder.extras] of Argument[-1];ReturnValue;value",
18-
"android.app;Notification$Builder;true;addAction;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint",
19-
"android.app;Notification$Builder;true;addAction;(Action);;Argument[0];Argument[-1];taint",
20-
"android.app;Notification$Builder;true;addExtras;;;MapKey of Argument[0];MapKey of SyntheticField[android.app.NotificationBuilder.extras] of Argument[-1];value",
21-
"android.app;Notification$Builder;true;addExtras;;;MapValue of Argument[0];MapValue of SyntheticField[android.app.NotificationBuilder.extras] of Argument[-1];value",
22-
"android.app;Notification$Builder;true;build;;;Argument[-1];ReturnValue;taint",
23-
"android.app;Notification$Builder;true;setContentIntent;;;Argument[0];Argument[-1];taint",
24-
"android.app;Notification$Builder;true;getExtras;;;SyntheticField[android.app.NotificationBuilder.extras] of Argument[-1];ReturnValue;value",
25-
"android.app;Notification$Builder;true;recoverBuilder;;;Argument[1];ReturnValue;taint",
26-
"android.app;Notification$Builder;true;setActions;;;ArrayElement of Argument[0];Argument[-1];taint",
27-
"android.app;Notification$Builder;true;setExtras;;;Argument[0];SyntheticField[android.app.NotificationBuilder.extras] of Argument[-1];value",
28-
"android.app;Notification$Builder;true;setDeleteIntent;;;Argument[0];Argument[-1];taint",
29-
"android.app;Notification$Builder;true;setPublicVersion;;;Argument[0];Argument[-1];taint",
17+
"android.app;Notification$Action;true;Action;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
18+
"android.app;Notification$Action$Builder;true;Builder;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
19+
"android.app;Notification$Action$Builder;true;Builder;(Icon,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
20+
"android.app;Notification$Action$Builder;true;Builder;(Action);;SyntheticField[android.app.Notification.action] of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
21+
"android.app;Notification$Action$Builder;true;addExtras;;;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value",
22+
"android.app;Notification$Action$Builder;true;addExtras;;;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value",
23+
"android.app;Notification$Action$Builder;true;build;;;SyntheticField[android.app.Notification.action] of Argument[-1];SyntheticField[android.app.Notification.action] of ReturnValue;taint",
24+
"android.app;Notification$Action$Builder;true;getExtras;;;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value",
25+
"android.app;Notification$Builder;true;addAction;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
26+
"android.app;Notification$Builder;true;addAction;(Action);;SyntheticField[android.app.Notification.action] of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
27+
"android.app;Notification$Builder;true;addExtras;;;MapKey of Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of Argument[-1];value",
28+
"android.app;Notification$Builder;true;addExtras;;;MapValue of Argument[0];MapValue of SyntheticField[android.content.Intent.extras] of Argument[-1];value",
29+
"android.app;Notification$Builder;true;build;;;SyntheticField[android.app.Notification.action] of Argument[-1];SyntheticField[android.app.Notification.action] of ReturnValue;taint",
30+
"android.app;Notification$Builder;true;setContentIntent;;;Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
31+
"android.app;Notification$Builder;true;getExtras;;;SyntheticField[android.content.Intent.extras] of Argument[-1];ReturnValue;value",
32+
"android.app;Notification$Builder;true;recoverBuilder;;;SyntheticField[android.app.Notification.action] of Argument[1];SyntheticField[android.app.Notification.action] of ReturnValue;taint",
33+
"android.app;Notification$Builder;true;setActions;;;SyntheticField[android.app.Notification.action] of ArrayElement of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
34+
"android.app;Notification$Builder;true;setExtras;;;Argument[0];SyntheticField[android.content.Intent.extras] of Argument[-1];value",
35+
"android.app;Notification$Builder;true;setDeleteIntent;;;Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
36+
"android.app;Notification$Builder;true;setPublicVersion;;;SyntheticField[android.app.Notification.action] of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint",
3037
// Fluent models
3138
"android.app;Notification$Action$Builder;true;" +
3239
[

java/ql/test/library-tests/frameworks/android/notification/Test.java

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,6 @@
1313
// Test case generated by GenerateFlowTestCase.ql
1414
public class Test {
1515

16-
Notification.Action.Builder newActionBuilderWithExtras(Bundle element) {
17-
return null;
18-
}
19-
20-
Notification.Builder newBuilderWithExtras(Bundle element) {
21-
return null;
22-
}
23-
2416
Object getMapKeyDefault(Bundle container) {
2517
return null;
2618
}
@@ -50,21 +42,24 @@ void sink(Object o) {}
5042
public void test() throws Exception {
5143

5244
{
53-
// "android.app;Notification$Action$Builder;true;Builder;(Action);;Argument[0];Argument[-1];taint"
45+
// "android.app;Notification$Action$Builder;true;Builder;(Action);;SyntheticField[android.app.Notification.action]
46+
// of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint"
5447
Notification.Action.Builder out = null;
5548
Notification.Action in = (Notification.Action) source();
5649
out = new Notification.Action.Builder(in);
5750
sink(out); // $ hasTaintFlow
5851
}
5952
{
60-
// "android.app;Notification$Action$Builder;true;Builder;(Icon,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint"
53+
// "android.app;Notification$Action$Builder;true;Builder;(Icon,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action]
54+
// of Argument[-1];taint"
6155
Notification.Action.Builder out = null;
6256
PendingIntent in = (PendingIntent) source();
6357
out = new Notification.Action.Builder((Icon) null, (CharSequence) null, in);
6458
sink(out); // $ hasTaintFlow
6559
}
6660
{
67-
// "android.app;Notification$Action$Builder;true;Builder;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint"
61+
// "android.app;Notification$Action$Builder;true;Builder;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action]
62+
// of Argument[-1];taint"
6863
Notification.Action.Builder out = null;
6964
PendingIntent in = (PendingIntent) source();
7065
out = new Notification.Action.Builder(0, (CharSequence) null, in);
@@ -79,17 +74,17 @@ public void test() throws Exception {
7974
}
8075
{
8176
// "android.app;Notification$Action$Builder;true;addExtras;;;MapKey of
82-
// Argument[0];MapKey of SyntheticField[android.app.Notification$Action$Builder.extras]
83-
// of Argument[-1];value"
77+
// Argument[0];MapKey of SyntheticField[android.content.Intent.extras] of
78+
// Argument[-1];value"
8479
Notification.Action.Builder out = null;
85-
Bundle in = newWithMapKeyDefault(source());
80+
Bundle in = (Bundle) newWithMapKeyDefault(source());
8681
out.addExtras(in);
8782
sink(getMapKeyDefault(out.getExtras())); // $ hasValueFlow
8883
}
8984
{
9085
// "android.app;Notification$Action$Builder;true;addExtras;;;MapValue of
91-
// Argument[0];MapValue of
92-
// SyntheticField[android.app.Notification$Action$Builder.extras] of Argument[-1];value"
86+
// Argument[0];MapValue of SyntheticField[android.content.Intent.extras]
87+
// of Argument[-1];value"
9388
Notification.Action.Builder out = null;
9489
Bundle in = (Bundle) newWithMapValueDefault(source());
9590
out.addExtras(in);
@@ -103,7 +98,8 @@ public void test() throws Exception {
10398
sink(out); // $ hasValueFlow
10499
}
105100
{
106-
// "android.app;Notification$Action$Builder;true;build;;;Argument[-1];ReturnValue;taint"
101+
// "android.app;Notification$Action$Builder;true;build;;;SyntheticField[android.app.Notification.action]
102+
// of Argument[-1];SyntheticField[android.app.Notification.action] of ReturnValue;taint"
107103
Notification.Action out = null;
108104
Notification.Action.Builder in = (Notification.Action.Builder) source();
109105
out = in.build();
@@ -117,12 +113,12 @@ public void test() throws Exception {
117113
sink(out); // $ hasValueFlow
118114
}
119115
{
120-
// "android.app;Notification$Action$Builder;true;getExtras;;;SyntheticField[android.app.Notification$Action$Builder.extras]
116+
// "android.app;Notification$Action$Builder;true;getExtras;;;SyntheticField[android.content.Intent.extras]
121117
// of Argument[-1];ReturnValue;value"
122118
Bundle out = null;
123-
Notification.Action.Builder in = newActionBuilderWithExtras((Bundle) source());
119+
Notification.Action.Builder in = (Notification.Action.Builder) source();
124120
out = in.getExtras();
125-
sink(out); // $ hasValueFlow
121+
sink(out); // $ hasTaintFlow
126122
}
127123
{
128124
// "android.app;Notification$Action$Builder;true;setAllowGeneratedReplies;;;Argument[-1];ReturnValue;value"
@@ -153,21 +149,24 @@ public void test() throws Exception {
153149
sink(out); // $ hasValueFlow
154150
}
155151
{
156-
// "android.app;Notification$Action;true;Action;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint"
152+
// "android.app;Notification$Action;true;Action;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action]
153+
// of Argument[-1];taint"
157154
Notification.Action out = null;
158155
PendingIntent in = (PendingIntent) source();
159-
out = new Action(0, null, in);
156+
out = new Notification.Action(0, null, in);
160157
sink(out); // $ hasTaintFlow
161158
}
162159
{
163-
// "android.app;Notification$Builder;true;addAction;(Action);;Argument[0];Argument[-1];taint"
160+
// "android.app;Notification$Builder;true;addAction;(Action);;SyntheticField[android.app.Notification.action]
161+
// of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint"
164162
Notification.Builder out = null;
165163
Notification.Action in = (Notification.Action) source();
166164
out.addAction(in);
167165
sink(out); // $ hasTaintFlow
168166
}
169167
{
170-
// "android.app;Notification$Builder;true;addAction;(int,CharSequence,PendingIntent);;Argument[2];Argument[-1];taint"
168+
// "android.app;Notification$Builder;true;addAction;(int,CharSequence,PendingIntent);;Argument[2];SyntheticField[android.app.Notification.action]
169+
// of Argument[-1];taint"
171170
Notification.Builder out = null;
172171
PendingIntent in = (PendingIntent) source();
173172
out.addAction(0, null, in);
@@ -196,17 +195,17 @@ public void test() throws Exception {
196195
}
197196
{
198197
// "android.app;Notification$Builder;true;addExtras;;;MapKey of Argument[0];MapKey of
199-
// SyntheticField[android.app.Notification$Builder.extras] of Argument[-1];value"
198+
// SyntheticField[android.content.Intent.extras] of Argument[-1];value"
200199
Notification.Builder out = null;
201-
Bundle in = newWithMapKeyDefault(source());
200+
Bundle in = (Bundle) newWithMapKeyDefault(source());
202201
out.addExtras(in);
203202
sink(getMapKeyDefault(out.getExtras())); // $ hasValueFlow
204203
}
205204
{
206205
// "android.app;Notification$Builder;true;addExtras;;;MapValue of Argument[0];MapValue
207-
// of SyntheticField[android.app.Notification$Builder.extras] of Argument[-1];value"
206+
// of SyntheticField[android.content.Intent.extras] of Argument[-1];value"
208207
Notification.Builder out = null;
209-
Bundle in = newWithMapValueDefault(source());
208+
Bundle in = (Bundle) newWithMapValueDefault(source());
210209
out.addExtras(in);
211210
sink(getMapValueDefault(out.getExtras())); // $ hasValueFlow
212211
}
@@ -225,7 +224,8 @@ public void test() throws Exception {
225224
sink(out); // $ hasValueFlow
226225
}
227226
{
228-
// "android.app;Notification$Builder;true;build;;;Argument[-1];ReturnValue;taint"
227+
// "android.app;Notification$Builder;true;build;;;SyntheticField[android.app.Notification.action]
228+
// of Argument[-1];SyntheticField[android.app.Notification.action] of ReturnValue;taint"
229229
Notification out = null;
230230
Notification.Builder in = (Notification.Builder) source();
231231
out = in.build();
@@ -239,15 +239,16 @@ public void test() throws Exception {
239239
sink(out); // $ hasValueFlow
240240
}
241241
{
242-
// "android.app;Notification$Builder;true;getExtras;;;SyntheticField[android.app.Notification$Builder.extras]
242+
// "android.app;Notification$Builder;true;getExtras;;;SyntheticField[android.content.Intent.extras]
243243
// of Argument[-1];ReturnValue;value"
244244
Bundle out = null;
245-
Notification.Builder in = newBuilderWithExtras((Bundle) source());
245+
Notification.Builder in = (Notification.Builder) source();
246246
out = in.getExtras();
247-
sink(out); // $ hasValueFlow
247+
sink(out); // $ hasTaintFlow
248248
}
249249
{
250-
// "android.app;Notification$Builder;true;recoverBuilder;;;Argument[1];ReturnValue;taint"
250+
// "android.app;Notification$Builder;true;recoverBuilder;;;SyntheticField[android.app.Notification.action]
251+
// of Argument[1];SyntheticField[android.app.Notification.action] of ReturnValue;taint"
251252
Notification.Builder out = null;
252253
Notification in = (Notification) source();
253254
out = Notification.Builder.recoverBuilder(null, in);
@@ -261,8 +262,9 @@ public void test() throws Exception {
261262
sink(out); // $ hasValueFlow
262263
}
263264
{
264-
// "android.app;Notification$Builder;true;setActions;;;ArrayElement of
265-
// Argument[0];Argument[-1];taint"
265+
// "android.app;Notification$Builder;true;setActions;;;SyntheticField[android.app.Notification.action]
266+
// of ArrayElement of Argument[0];SyntheticField[android.app.Notification.action] of
267+
// Argument[-1];taint"
266268
Notification.Builder out = null;
267269
Notification.Action[] in = (Notification.Action[]) new Notification.Action[] {
268270
(Notification.Action) source()};
@@ -347,7 +349,8 @@ public void test() throws Exception {
347349
sink(out); // $ hasValueFlow
348350
}
349351
{
350-
// "android.app;Notification$Builder;true;setContentIntent;;;Argument[0];Argument[-1];taint"
352+
// "android.app;Notification$Builder;true;setContentIntent;;;Argument[0];SyntheticField[android.app.Notification.action]
353+
// of Argument[-1];taint"
351354
Notification.Builder out = null;
352355
PendingIntent in = (PendingIntent) source();
353356
out.setContentIntent(in);
@@ -396,7 +399,8 @@ public void test() throws Exception {
396399
sink(out); // $ hasValueFlow
397400
}
398401
{
399-
// "android.app;Notification$Builder;true;setDeleteIntent;;;Argument[0];Argument[-1];taint"
402+
// "android.app;Notification$Builder;true;setDeleteIntent;;;Argument[0];SyntheticField[android.app.Notification.action]
403+
// of Argument[-1];taint"
400404
Notification.Builder out = null;
401405
PendingIntent in = (PendingIntent) source();
402406
out.setDeleteIntent(in);
@@ -410,7 +414,7 @@ public void test() throws Exception {
410414
sink(out); // $ hasValueFlow
411415
}
412416
{
413-
// android.app;Notification$Builder;true;setExtras;;;Argument[0];SyntheticField[android.app.Notification$Builder.extras]
417+
// "android.app;Notification$Builder;true;setExtras;;;Argument[0];SyntheticField[android.content.Intent.extras]
414418
// of Argument[-1];value"
415419
Notification.Builder out = null;
416420
Bundle in = (Bundle) source();
@@ -537,7 +541,8 @@ public void test() throws Exception {
537541
sink(out); // $ hasValueFlow
538542
}
539543
{
540-
// "android.app;Notification$Builder;true;setPublicVersion;;;Argument[0];Argument[-1];taint"
544+
// "android.app;Notification$Builder;true;setPublicVersion;;;SyntheticField[android.app.Notification.action]
545+
// of Argument[0];SyntheticField[android.app.Notification.action] of Argument[-1];taint"
541546
Notification.Builder out = null;
542547
Notification in = (Notification) source();
543548
out.setPublicVersion(in);
Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
import java
2+
import semmle.code.java.frameworks.android.Intent
23
import TestUtilities.InlineFlowTest
34

45
class SummaryModelTest extends SummaryModelCsv {
56
override predicate row(string row) {
67
row =
78
[
89
//"package;type;overrides;name;signature;ext;inputspec;outputspec;kind",
9-
"generatedtest;Test;false;getMapKeyDefault;(Bundle);;MapKey of Argument[0];ReturnValue;value",
10-
"generatedtest;Test;false;newActionBuilderWithExtras;(Bundle);;Argument[0];SyntheticField[android.app.NotificationActionBuilder.extras] of ReturnValue;value",
11-
"generatedtest;Test;false;newBuilderWithExtras;(Bundle);;Argument[0];SyntheticField[android.app.NotificationBuilder.extras] of ReturnValue;value"
10+
"generatedtest;Test;false;getMapKeyDefault;(Bundle);;MapKey of Argument[0];ReturnValue;value"
1211
]
1312
}
1413
}
14+
15+
class NotificationsTaintFlowConf extends DefaultTaintFlowConf {
16+
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
17+
super.allowImplicitRead(node, c)
18+
or
19+
isSink(node) and
20+
c.(DataFlow::SyntheticFieldContent).getField() = "android.app.Notification.action"
21+
or
22+
allowIntentExtrasImplicitRead(node, c)
23+
}
24+
}

0 commit comments

Comments
 (0)