diff --git a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll index d53d8db5519..1d189cca569 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll @@ -110,72 +110,51 @@ private class SQLiteSinkCsv extends SinkModelCsv { } } -private class QueryBuilderBuildMethod extends TaintPreservingCallable { - int argument; - - QueryBuilderBuildMethod() { - this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and - ( - // buildQuery(String[] projectionIn, String selection, String groupBy, String having, String sortOrder, String limit) - // buildQuery(String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) - // buildUnionQuery(String[] subQueries, String sortOrder, String limit) - this.hasName(["buildQuery", "buildUnionQuery"]) and - argument = [-1 .. getNumberOfParameters()] - or - // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String[] selectionArgs, String groupBy, String having) - // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String groupBy, String having) - this.hasName("buildUnionSubQuery") and - argument = [-1 .. getNumberOfParameters()] and - argument != 3 - or - // static buildQueryString(boolean distinct, String tables, String[] columns, String where, String groupBy, String having, String orderBy, String limit) - hasName("buildQueryString") and - argument = [1 .. getNumberOfParameters()] - ) - } - - override predicate returnsTaintFrom(int arg) { argument = arg } -} - -private class QueryBuilderAppendMethod extends TaintPreservingCallable { - QueryBuilderAppendMethod() { - this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and - // setProjectionMap(Map columnMap) - // setTables(String inTables) - // appendWhere(CharSequence inWhere) - // appendWhereStandalone(CharSequence inWhere) - // static appendColumns(StringBuilder s, String[] columns) - this.hasName([ - "setProjectionMap", "setTables", "appendWhere", "appendWhereStandalone", "appendColumns" - ]) - } - - override predicate transfersTaint(int src, int sink) { - if hasName("appendColumns") then (src = 1 and sink = 0) else (src = 0 and sink = -1) +private class SqlFlowStep extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", + // buildQuery(String[] projectionIn, String selection, String groupBy, String having, String sortOrder, String limit) + // buildQuery(String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) + // buildUnionQuery(String[] subQueries, String sortOrder, String limit) + "android.database.sqlite;SQLiteQueryBuilder;true;buildQuery;(String[],String,String,String,String,String);;Argument[-1];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildQuery;(String[],String,String,String,String,String);;ArrayElement of Argument[0];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildQuery;(String[],String,String,String,String,String);;Argument[1..5];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildQuery;(String[],String,String[],String,String,String,String);;Argument[-1];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildQuery;(String[],String,String[],String,String,String,String);;ArrayElement of Argument[0];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildQuery;(String[],String,String[],String,String,String,String);;Argument[1];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildQuery;(String[],String,String[],String,String,String,String);;Argument[3..6];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionQuery;(String[],String,String);;Argument[-1];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionQuery;(String[],String,String);;ArrayElement of Argument[0];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionQuery;(String[],String,String);;Argument[1..2];ReturnValue;taint", + // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String[] selectionArgs, String groupBy, String having) + // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String groupBy, String having) + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionSubQuery;(String,String[],Set,int,String,String,String[],String,String);;Argument[-1..0];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionSubQuery;(String,String[],Set,int,String,String,String[],String,String);;ArrayElement of Argument[1];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionSubQuery;(String,String[],Set,int,String,String,String[],String,String);;Element of Argument[2];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionSubQuery;(String,String[],Set,int,String,String,String[],String,String);;Argument[4..5];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionSubQuery;(String,String[],Set,int,String,String,String[],String,String);;Argument[7..8];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionSubQuery;(String,String[],Set,int,String,String,String,String);;Argument[-1..0];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionSubQuery;(String,String[],Set,int,String,String,String,String);;ArrayElement of Argument[1];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionSubQuery;(String,String[],Set,int,String,String,String,String);;Element of Argument[2];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildUnionSubQuery;(String,String[],Set,int,String,String,String,String);;Argument[4..7];ReturnValue;taint", + // static buildQueryString(boolean distinct, String tables, String[] columns, String where, String groupBy, String having, String orderBy, String limit) + "android.database.sqlite;SQLiteQueryBuilder;true;buildQueryString;(boolean,String,String[],String,String,String,String,String);;Argument[1];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildQueryString;(boolean,String,String[],String,String,String,String,String);;ArrayElement of Argument[2];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;buildQueryString;(boolean,String,String[],String,String,String,String,String);;Argument[3..7];ReturnValue;taint", + "android.database.sqlite;SQLiteQueryBuilder;true;setProjectionMap;(Map);;MapKey of Argument[0];Argument[-1];taint", + "android.database.sqlite;SQLiteQueryBuilder;true;setProjectionMap;(Map);;MapValue of Argument[0];Argument[-1];taint", + "android.database.sqlite;SQLiteQueryBuilder;true;setTables;(String);;Argument[0];Argument[-1];taint", + "android.database.sqlite;SQLiteQueryBuilder;true;appendWhere;(CharSequence);;Argument[0];Argument[-1];taint", + "android.database.sqlite;SQLiteQueryBuilder;true;appendWhereStandalone;(CharSequence);;Argument[0];Argument[-1];taint", + "android.database.sqlite;SQLiteQueryBuilder;true;appendColumns;(StringBuilder,String[]);;ArrayElement of Argument[1];Argument[0];taint", + "android.database;DatabaseUtils;false;appendSelectionArgs;(String[],String[]);;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;taint", + "android.database;DatabaseUtils;false;concatenateWhere;(String,String);;Argument[0..1];ReturnValue;taint", + "android.content;ContentProvider;true;query;(Uri,String[],String,String[],String);;Argument[0];ReturnValue;taint", + "android.content;ContentProvider;true;query;(Uri,String[],String,String[],String,CancellationSignal);;Argument[0];ReturnValue;taint", + "android.content;ContentResolver;true;query;(Uri,String[],String,String[],String);;Argument[0];ReturnValue;taint", + "android.content;ContentResolver;true;query;(Uri,String[],String,String[],String,CancellationSignal);;Argument[0];ReturnValue;taint" + ] } } - -private class UnsafeAppendUtilMethod extends TaintPreservingCallable { - UnsafeAppendUtilMethod() { - this.getDeclaringType() instanceof TypeDatabaseUtils and - // String[] appendSelectionArgs(String[] originalValues, String[] newValues) - // String concatenateWhere(String a, String b) - this.hasName(["appendSelectionArgs", "concatenateWhere"]) - } - - override predicate returnsTaintFrom(int arg) { arg = [0 .. getNumberOfParameters()] } -} - -private class TaintPreservingQueryMethod extends TaintPreservingCallable { - TaintPreservingQueryMethod() { - ( - this.getDeclaringType() instanceof AndroidContentProvider or - this.getDeclaringType() instanceof AndroidContentResolver - ) and - // Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) - // Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) - this.hasName("query") - } - - override predicate returnsTaintFrom(int arg) { arg = 0 } -} diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java b/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java index afaf28fe03d..edf290c4cef 100644 --- a/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java +++ b/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java @@ -1,5 +1,7 @@ import java.util.Map; import java.util.Set; +import java.util.HashSet; +import java.util.HashMap; import android.content.ContentProvider; import android.content.ContentResolver; @@ -26,10 +28,10 @@ public class FlowSteps { // Dummy class to test for sub classes } - public static String[] appendSelectionArgs() { - String[] originalValues = {taint()}; // $ MISSING: taintReachesReturn - String[] newValues = {taint()}; // $ MISSING: taintReachesReturn - return DatabaseUtils.appendSelectionArgs(originalValues, newValues); + public static String appendSelectionArgs() { + String[] originalValues = {taint()}; // $taintReachesReturn + String[] newValues = {taint()}; // $taintReachesReturn + return DatabaseUtils.appendSelectionArgs(originalValues, newValues)[0]; } public static String concatenateWhere() { @@ -42,7 +44,7 @@ public class FlowSteps { target = taint(); boolean distinct = taint(); String tables = taint(); // $taintReachesReturn - String[] columns = {taint()}; // $ MISSING: taintReachesReturn + String[] columns = {taint()}; // $taintReachesReturn String where = taint(); // $taintReachesReturn String groupBy = taint(); // $taintReachesReturn String having = taint(); // $taintReachesReturn @@ -53,7 +55,7 @@ public class FlowSteps { public static String buildQuery(MySQLiteQueryBuilder target) { target = taint(); // $taintReachesReturn - String[] projectionIn = {taint()};// $ MISSING: taintReachesReturn + String[] projectionIn = {taint()}; // $taintReachesReturn String selection = taint(); // $taintReachesReturn String groupBy = taint(); // $taintReachesReturn String having = taint(); // $taintReachesReturn @@ -64,9 +66,9 @@ public class FlowSteps { public static String buildQuery2(MySQLiteQueryBuilder target) { target = taint(); // $taintReachesReturn - String[] projectionIn = {taint()}; // $ MISSING: taintReachesReturn + String[] projectionIn = {taint()}; // $taintReachesReturn String selection = taint(); // $taintReachesReturn - String[] selectionArgs = {taint()}; // $ MISSING: taintReachesReturn + String[] selectionArgs = {taint()}; String groupBy = taint(); // $taintReachesReturn String having = taint(); // $taintReachesReturn String sortOrder = taint(); // $taintReachesReturn @@ -76,7 +78,7 @@ public class FlowSteps { public static String buildUnionQuery(MySQLiteQueryBuilder target) { target = taint(); // $taintReachesReturn - String[] subQueries = {taint()}; // $ MISSING: taintReachesReturn + String[] subQueries = {taint()}; // $taintReachesReturn String sortOrder = taint(); // $taintReachesReturn String limit = taint(); // $taintReachesReturn return target.buildUnionQuery(subQueries, sortOrder, limit); @@ -85,12 +87,13 @@ public class FlowSteps { public static String buildUnionSubQuery2(MySQLiteQueryBuilder target) { target = taint(); // $taintReachesReturn String typeDiscriminatorColumn = taint(); // $taintReachesReturn - String[] unionColumns = {taint()}; // $ MISSING: taintReachesReturn - Set columnsPresentInTable = taint(); // $taintReachesReturn + String[] unionColumns = {taint()}; // $taintReachesReturn + Set columnsPresentInTable = new HashSet(); + columnsPresentInTable.add(taint()); // $taintReachesReturn int computedColumnsOffset = taint(); String typeDiscriminatorValue = taint(); // $taintReachesReturn String selection = taint(); // $taintReachesReturn - String[] selectionArgs = {taint()}; // $ MISSING: taintReachesReturn + String[] selectionArgs = {taint()}; String groupBy = taint(); // $taintReachesReturn String having = taint(); // $taintReachesReturn return target.buildUnionSubQuery(typeDiscriminatorColumn, unionColumns, columnsPresentInTable, @@ -100,8 +103,9 @@ public class FlowSteps { public static String buildUnionSubQuery3(MySQLiteQueryBuilder target) { target = taint(); // $taintReachesReturn String typeDiscriminatorColumn = taint(); // $taintReachesReturn - String[] unionColumns = {taint()}; // $ MISSING: taintReachesReturn - Set columnsPresentInTable = taint(); // $taintReachesReturn + String[] unionColumns = {taint()}; // $taintReachesReturn + Set columnsPresentInTable = new HashSet(); + columnsPresentInTable.add(taint()); // $taintReachesReturn int computedColumnsOffset = taint(); String typeDiscriminatorValue = taint(); // $taintReachesReturn String selection = taint(); // $taintReachesReturn @@ -151,14 +155,17 @@ public class FlowSteps { public static StringBuilder appendColumns() { StringBuilder s = taint(); // $taintReachesReturn - String[] columns = {taint()}; // $ MISSING: taintReachesReturn + String[] columns = {taint()}; // $taintReachesReturn SQLiteQueryBuilder.appendColumns(s, columns); return s; } public static SQLiteQueryBuilder setProjectionMap(MySQLiteQueryBuilder target) { target = taint(); // $taintReachesReturn - Map columnMap = taint(); // $taintReachesReturn + Map columnMap = new HashMap(); + String k = taint(); // $taintReachesReturn + String v = taint(); // $taintReachesReturn + columnMap.put(k, v); target.setProjectionMap(columnMap); return target; }