diff --git a/java/ql/test/library-tests/frameworks/android/intent/TestStartActivityToGetIntent.java b/java/ql/test/library-tests/frameworks/android/intent/TestStartActivityToGetIntent.java index 3d497aac93d..115b5673eab 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/TestStartActivityToGetIntent.java +++ b/java/ql/test/library-tests/frameworks/android/intent/TestStartActivityToGetIntent.java @@ -2,24 +2,68 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +// ! Original - saving for reference +// public class TestStartActivityToGetIntent { + +// static Object source() { +// return null; +// } + +// static void sink(Object sink) { +// } + +// public void test(Context ctx) { +// Intent intent = new Intent(null, SomeActivity.class); +// intent.putExtra("data", (String) source()); +// ctx.startActivity(intent); +// } + +// static class SomeActivity extends Activity { + +// public void test() { +// sink(getIntent().getStringExtra("data")); // $ hasValueFlow +// } +// } +// } + public class TestStartActivityToGetIntent { - static Object source() { + static Object source(String kind) { return null; } - static void sink(Object sink) {} + static void sink(Object sink) { + } - public void test(Context ctx) { - Intent intent = new Intent(null, SomeActivity.class); - intent.putExtra("data", (String) source()); - ctx.startActivity(intent); + public void test(Context ctx, Activity act) { + { + Intent intentCtx = new Intent(null, SomeActivity.class); + Intent intentAct = new Intent(null, SomeActivity.class); + intentCtx.putExtra("data", (String) source("context")); + intentAct.putExtra("data", (String) source("activity")); + ctx.startActivity(intentCtx); + act.startActivity(intentAct); + } + + { + Intent intentCtx = new Intent(null, SafeActivity.class); + Intent intentAct = new Intent(null, SafeActivity.class); + ctx.startActivity(intentCtx); + act.startActivity(intentAct); + } } static class SomeActivity extends Activity { public void test() { - sink(getIntent().getStringExtra("data")); // $ hasValueFlow + sink(getIntent().getStringExtra("data")); // $ hasValueFlow=context hasValueFlow=activity + } + } + + static class SafeActivity extends Activity { + + public void test() { + sink(getIntent().getStringExtra("data")); // Safe } } } diff --git a/java/ql/test/library-tests/frameworks/android/intent/TestStartBroadcastReceiverToIntent.java b/java/ql/test/library-tests/frameworks/android/intent/TestStartBroadcastReceiverToIntent.java new file mode 100644 index 00000000000..4cbc4f6e563 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/intent/TestStartBroadcastReceiverToIntent.java @@ -0,0 +1,42 @@ +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class TestStartBroadcastReceiverToIntent { + + static Object source() { + return null; + } + + static void sink(Object sink) { + } + + public void test(Context ctx) { + { + Intent intent = new Intent(null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source()); + ctx.sendBroadcast(intent); + } + + { + Intent intent = new Intent(null, SafeBroadcastReceiver.class); + ctx.sendBroadcast(intent); + } + } + + static class SomeBroadcastReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + sink(intent.getStringExtra("data")); // $ hasValueFlow + } + } + + static class SafeBroadcastReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + sink(intent.getStringExtra("data")); // Safe + } + } +} diff --git a/java/ql/test/library-tests/frameworks/android/intent/TestStartComponentToIntent.java b/java/ql/test/library-tests/frameworks/android/intent/TestStartComponentToIntent.java index bcc192958b4..ea5eee19d5b 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/TestStartComponentToIntent.java +++ b/java/ql/test/library-tests/frameworks/android/intent/TestStartComponentToIntent.java @@ -1,6 +1,6 @@ import android.app.Activity; -import android.app.Service; -import android.content.BroadcastReceiver; +//import android.app.Service; +//import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; diff --git a/java/ql/test/library-tests/frameworks/android/intent/TestStartServiceToIntent.java b/java/ql/test/library-tests/frameworks/android/intent/TestStartServiceToIntent.java new file mode 100644 index 00000000000..edfa3d18864 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/intent/TestStartServiceToIntent.java @@ -0,0 +1,99 @@ +import android.app.Service; +import android.os.IBinder; +import android.content.Context; +import android.content.Intent; + +public class TestStartServiceToIntent { + + static Object source() { + return null; + } + + static void sink(Object sink) { + } + + public void test(Context ctx) { + { + Intent intent = new Intent(null, SomeService.class); + intent.putExtra("data", (String) source()); + ctx.startService(intent); + } + + { + Intent intent = new Intent(null, SafeService.class); + ctx.startService(intent); + } + } + + static class SomeService extends Service { + + @Override + public void onStart(Intent intent, int startId) { + sink(intent.getStringExtra("data")); // $ hasValueFlow + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + sink(intent.getStringExtra("data")); // $ hasValueFlow + return -1; + } + + @Override + public IBinder onBind(Intent intent) { + sink(intent.getStringExtra("data")); // $ hasValueFlow + return null; + } + + @Override + public boolean onUnbind(Intent intent) { + sink(intent.getStringExtra("data")); // $ hasValueFlow + return false; + } + + @Override + public void onRebind(Intent intent) { + sink(intent.getStringExtra("data")); // $ hasValueFlow + } + + @Override + public void onTaskRemoved(Intent intent) { + sink(intent.getStringExtra("data")); // $ hasValueFlow + } + } + + static class SafeService extends Service { + + @Override + public void onStart(Intent intent, int startId) { + sink(intent.getStringExtra("data")); // Safe + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + sink(intent.getStringExtra("data")); // Safe + return -1; + } + + @Override + public IBinder onBind(Intent intent) { + sink(intent.getStringExtra("data")); // Safe + return null; + } + + @Override + public boolean onUnbind(Intent intent) { + sink(intent.getStringExtra("data")); // Safe + return false; + } + + @Override + public void onRebind(Intent intent) { + sink(intent.getStringExtra("data")); // Safe + } + + @Override + public void onTaskRemoved(Intent intent) { + sink(intent.getStringExtra("data")); // Safe + } + } +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/app/Service.java b/java/ql/test/stubs/google-android-9.0.0/android/app/Service.java index 8250b8917c2..d47dadcce4f 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/app/Service.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/app/Service.java @@ -20,12 +20,13 @@ import android.content.ContextWrapper; import android.os.IBinder; /** - * A Service is an application component representing either an application's desire + * A Service is an application component representing either an application's + * desire * to perform a longer-running operation while not interacting with the user - * or to supply functionality for other applications to use. Each service + * or to supply functionality for other applications to use. Each service * class must have a corresponding * {@link android.R.styleable#AndroidManifestService <service>} - * declaration in its package's AndroidManifest.xml. Services + * declaration in its package's AndroidManifest.xml. Services * can be started with * {@link android.content.Context#startService Context.startService()} and * {@link android.content.Context#bindService Context.bindService()}. @@ -34,9 +35,10 @@ import android.os.IBinder; * thread of their hosting process. This means that, if your service is going * to do any CPU intensive (such as MP3 playback) or blocking (such as * networking) operations, it should spawn its own thread in which to do that - * work. More information on this can be found in - * Processes and - * Threads. The {@link IntentService} class is available + * work. More information on this can be found in + * Processes and + * Threads. The {@link IntentService} class is available * as a standard implementation of Service that has its own thread where it * schedules its work to be done.

* @@ -47,13 +49,18 @@ import android.os.IBinder; *
  • Permissions *
  • Process Lifecycle *
  • Local Service Sample - *
  • Remote Messenger Service Sample + *
  • Remote Messenger Service + * Sample * * *
    *

    Developer Guides

    - *

    For a detailed discussion about how to create services, read the - * Services developer guide.

    + *

    + * For a detailed discussion about how to create services, read the + * Services developer + * guide. + *

    *
    * * @@ -63,10 +70,10 @@ import android.os.IBinder; * it is not:

    * * * @@ -75,12 +82,12 @@ import android.os.IBinder; *