Merge branch 'main' into repeatedWord

This commit is contained in:
Erik Krogh Kristensen
2022-08-09 21:22:47 +02:00
761 changed files with 51997 additions and 64658 deletions

View File

@@ -36,7 +36,7 @@ java.lang,13,,58,,,,,,,,,,,8,,,,,4,,,1,,,,,,,,,,,,,,,46,12
java.net,10,3,7,,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,,3,7,
java.nio,15,,6,,13,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,6,
java.sql,11,,,,,,,,,4,,,,,,,,,,,,,,,,7,,,,,,,,,,,,
java.util,44,,438,,,,,,,,,,,34,,,,,,5,2,,1,2,,,,,,,,,,,,,24,414
java.util,44,,458,,,,,,,,,,,34,,,,,,5,2,,1,2,,,,,,,,,,,,,36,422
javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,,
javax.jms,,9,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,57,
javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23
1 package sink source summary sink:bean-validation sink:create-file sink:groovy sink:header-splitting sink:information-leak sink:intent-start sink:jdbc-url sink:jexl sink:jndi-injection sink:ldap sink:logging sink:mvel sink:ognl-injection sink:open-url sink:pending-intent-sent sink:regex-use[-1] sink:regex-use[0] sink:regex-use[] sink:regex-use[f-1] sink:regex-use[f1] sink:regex-use[f] sink:set-hostname-verifier sink:sql sink:url-open-stream sink:url-redirect sink:write-file sink:xpath sink:xslt sink:xss source:android-external-storage-dir source:android-widget source:contentprovider source:remote summary:taint summary:value
36 java.net 10 3 7 10 3 7
37 java.nio 15 6 13 2 6
38 java.sql 11 4 7
39 java.util 44 438 458 34 5 2 1 2 24 36 414 422
40 javax.faces.context 2 7 2 7
41 javax.jms 9 57 9 57
42 javax.json 123 100 23

View File

@@ -15,9 +15,9 @@ Java framework & library support
`Apache HttpComponents <https://hc.apache.org/>`_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25
`Google Guava <https://guava.dev/>`_,``com.google.common.*``,,728,39,,6,,,,,
`JSON-java <https://github.com/stleary/JSON-java>`_,``org.json``,,236,,,,,,,,
Java Standard Library,``java.*``,3,549,130,28,,,7,,,10
Java Standard Library,``java.*``,3,569,130,28,,,7,,,10
Java extensions,"``javax.*``, ``jakarta.*``",63,609,32,,,4,,1,1,2
`Spring <https://spring.io/>`_,``org.springframework.*``,29,476,101,,,,19,14,,29
Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``kotlin.jvm.internal``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",65,395,932,,,,14,18,,3
Totals,,217,6410,1474,117,6,10,107,33,1,84
Totals,,217,6430,1474,117,6,10,107,33,1,84

View File

@@ -888,6 +888,10 @@ open class KotlinFileExtractor(
if (shortName.nameInDB != shortName.kotlinName) {
tw.writeKtFunctionOriginalNames(methodId, shortName.kotlinName)
}
if (f.hasInterfaceParent() && f.body != null) {
addModifiers(id, "default") // The actual output class file may or may not have this modifier, depending on the -Xjvm-default setting.
}
}
tw.writeHasLocation(id, locId)
@@ -1386,7 +1390,8 @@ open class KotlinFileExtractor(
dispatchReceiver: IrExpression?,
extensionReceiver: IrExpression?,
typeArguments: List<IrType> = listOf(),
extractClassTypeArguments: Boolean = false) {
extractClassTypeArguments: Boolean = false,
superQualifierSymbol: IrClassSymbol? = null) {
val locId = tw.getLocation(callsite)
@@ -1404,7 +1409,8 @@ open class KotlinFileExtractor(
dispatchReceiver?.let { { callId -> extractExpressionExpr(dispatchReceiver, enclosingCallable, callId, -1, enclosingStmt) } },
extensionReceiver?.let { { argParent -> extractExpressionExpr(extensionReceiver, enclosingCallable, argParent, 0, enclosingStmt) } },
typeArguments,
extractClassTypeArguments
extractClassTypeArguments,
superQualifierSymbol
)
}
@@ -1424,7 +1430,8 @@ open class KotlinFileExtractor(
extractDispatchReceiver: ((Label<out DbExpr>) -> Unit)?,
extractExtensionReceiver: ((Label<out DbExpr>) -> Unit)?,
typeArguments: List<IrType> = listOf(),
extractClassTypeArguments: Boolean = false) {
extractClassTypeArguments: Boolean = false,
superQualifierSymbol: IrClassSymbol? = null) {
val callTarget = syntacticCallTarget.target.realOverrideTarget
val id = tw.getFreshIdLabel<DbMethodaccess>()
@@ -1483,6 +1490,8 @@ open class KotlinFileExtractor(
if (callTarget.shouldExtractAsStatic) {
extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt)
} else if (superQualifierSymbol != null) {
extractSuperAccess(superQualifierSymbol.typeWith(), enclosingCallable, id, -1, enclosingStmt, locId)
} else if (extractDispatchReceiver != null) {
extractDispatchReceiver(id)
}
@@ -1744,7 +1753,7 @@ open class KotlinFileExtractor(
else
listOf()
extractRawMethodAccess(syntacticCallTarget, c, callable, parent, idx, enclosingStmt, (0 until c.valueArgumentsCount).map { c.getValueArgument(it) }, c.dispatchReceiver, c.extensionReceiver, typeArgs, extractClassTypeArguments)
extractRawMethodAccess(syntacticCallTarget, c, callable, parent, idx, enclosingStmt, (0 until c.valueArgumentsCount).map { c.getValueArgument(it) }, c.dispatchReceiver, c.extensionReceiver, typeArgs, extractClassTypeArguments, c.superQualifierSymbol)
}
fun extractSpecialEnumFunction(fnName: String){
@@ -2124,7 +2133,13 @@ open class KotlinFileExtractor(
}
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") && c.origin == IrStatementOrigin.FOR_LOOP_ITERATOR -> {
findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", "kotlin.jvm.internal.ArrayIteratorKt", c)?.let { iteratorFn ->
extractRawMethodAccess(iteratorFn, c, callable, parent, idx, enclosingStmt, listOf(c.dispatchReceiver), null, null, listOf((c.dispatchReceiver!!.type as IrSimpleType).arguments.first().typeOrNull!!))
val typeArgs = (c.dispatchReceiver!!.type as IrSimpleType).arguments.map {
when(it) {
is IrTypeProjection -> it.type
else -> pluginContext.irBuiltIns.anyNType
}
}
extractRawMethodAccess(iteratorFn, c, callable, parent, idx, enclosingStmt, listOf(c.dispatchReceiver), null, null, typeArgs)
}
}
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "get") && c.origin == IrStatementOrigin.GET_ARRAY_ELEMENT -> {
@@ -3060,6 +3075,17 @@ open class KotlinFileExtractor(
}
}
private fun extractSuperAccess(irType: IrType, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int, enclosingStmt: Label<out DbStmt>, locId: Label<out DbLocation>) =
tw.getFreshIdLabel<DbSuperaccess>().also {
val type = useType(irType)
tw.writeExprs_superaccess(it, type.javaResult.id, parent, idx)
tw.writeExprsKotlinType(it, type.kotlinResult.id)
tw.writeHasLocation(it, locId)
tw.writeCallableEnclosingExpr(it, callable)
tw.writeStatementEnclosingExpr(it, enclosingStmt)
extractTypeAccessRecursive(irType, locId, it, 0)
}
private fun extractThisAccess(e: IrGetValue, exprParent: ExprParent, callable: Label<out DbCallable>) {
val containingDeclaration = declarationStack.peek()
val locId = tw.getLocation(e)
@@ -4014,7 +4040,7 @@ open class KotlinFileExtractor(
/**
* Extracts a single wildcard type access expression with no enclosing callable and statement.
*/
private fun extractWildcardTypeAccess(type: TypeResults, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
private fun extractWildcardTypeAccess(type: TypeResults, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
val id = tw.getFreshIdLabel<DbWildcardtypeaccess>()
tw.writeExprs_wildcardtypeaccess(id, type.javaResult.id, parent, idx)
tw.writeExprsKotlinType(id, type.kotlinResult.id)
@@ -4025,7 +4051,7 @@ open class KotlinFileExtractor(
/**
* Extracts a single type access expression with no enclosing callable and statement.
*/
private fun extractTypeAccess(type: TypeResults, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
private fun extractTypeAccess(type: TypeResults, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int): Label<out DbExpr> {
// TODO: elementForLocation allows us to give some sort of
// location, but a proper location for the type access will
// require upstream changes
@@ -4051,7 +4077,7 @@ open class KotlinFileExtractor(
* `extractTypeAccessRecursive` if the argument is invariant.
* No enclosing callable and statement is extracted, this is useful for type access extraction in field declarations.
*/
private fun extractWildcardTypeAccessRecursive(t: IrTypeArgument, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int) {
private fun extractWildcardTypeAccessRecursive(t: IrTypeArgument, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int) {
val typeLabels by lazy { TypeResults(getTypeArgumentLabel(t), TypeResult(fakeKotlinType(), "TODO", "TODO")) }
when (t) {
is IrStarProjection -> extractWildcardTypeAccess(typeLabels, location, parent, idx)
@@ -4071,7 +4097,7 @@ open class KotlinFileExtractor(
* Extracts a type access expression and its child type access expressions in case of a generic type. Nested generics are also handled.
* No enclosing callable and statement is extracted, this is useful for type access extraction in field declarations.
*/
private fun extractTypeAccessRecursive(t: IrType, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, typeContext: TypeContext = TypeContext.OTHER): Label<out DbExpr> {
private fun extractTypeAccessRecursive(t: IrType, location: Label<out DbLocation>, parent: Label<out DbExprparent>, idx: Int, typeContext: TypeContext = TypeContext.OTHER): Label<out DbExpr> {
val typeAccessId = extractTypeAccess(useType(t, typeContext), location, parent, idx)
if (t is IrSimpleType) {
t.arguments.forEachIndexed { argIdx, arg ->

View File

@@ -121,14 +121,19 @@ open class KotlinUsesExtractor(
}
}
private fun extractErrorType(): TypeResults {
private fun extractJavaErrorType(): TypeResult<DbErrortype> {
val typeId = tw.getLabelFor<DbErrortype>("@\"errorType\"") {
tw.writeError_type(it)
}
return TypeResult(typeId, null, "<CodeQL error type>")
}
private fun extractErrorType(): TypeResults {
val javaResult = extractJavaErrorType()
val kotlinTypeId = tw.getLabelFor<DbKt_nullable_type>("@\"errorKotlinType\"") {
tw.writeKt_nullable_types(it, typeId)
tw.writeKt_nullable_types(it, javaResult.id)
}
return TypeResults(TypeResult(typeId, null, "<CodeQL error type>"),
return TypeResults(javaResult,
TypeResult(kotlinTypeId, null, "<CodeQL error type>"))
}
@@ -719,7 +724,7 @@ open class KotlinUsesExtractor(
}
else -> {
logger.error("Unrecognised IrSimpleType: " + s.javaClass + ": " + s.render())
return TypeResults(TypeResult(fakeLabel(), "unknown", "unknown"), TypeResult(fakeLabel(), "unknown", "unknown"))
return extractErrorType()
}
}
}
@@ -1276,7 +1281,7 @@ open class KotlinUsesExtractor(
}
else -> {
logger.error("Unexpected type argument.")
return TypeResult(fakeLabel(), "unknown", "unknown")
return extractJavaErrorType()
}
}
}

View File

@@ -29,15 +29,3 @@ class IntLabel<T>(val i: Int): Label<T> {
class StringLabel<T>(val name: String): Label<T> {
override fun toString(): String = "#$name"
}
// TODO: Remove this and all of its uses
fun <T> fakeLabel(): Label<T> {
if (false) {
println("Fake label")
} else {
val sw = StringWriter()
Exception().printStackTrace(PrintWriter(sw))
println("Fake label from:\n$sw")
}
return IntLabel(0)
}

View File

@@ -51,6 +51,8 @@ private val specialFunctions = mapOf(
makeDescription(FqName("java.lang.Number"), "toFloat") to "floatValue",
makeDescription(StandardNames.FqNames.number.toSafe(), "toDouble") to "doubleValue",
makeDescription(FqName("java.lang.Number"), "toDouble") to "doubleValue",
makeDescription(StandardNames.FqNames.string.toSafe(), "get") to "charAt",
makeDescription(FqName("java.lang.String"), "get") to "charAt",
)
private val specialFunctionShortNames = specialFunctions.keys.map { it.functionName }.toSet()

View File

@@ -12,6 +12,8 @@ Type getAMentionedType(RefType type) {
result = getAMentionedType(type).(InstantiatedType).getATypeArgument()
or
result = getAMentionedType(type).(NestedType).getEnclosingType()
or
result = getAMentionedType(type).(Wildcard).getATypeBound().getType()
}
Type getATypeUsedInClass(RefType type) {

View File

@@ -1,3 +1,27 @@
## 0.3.2
### New Features
* The QL predicate `Expr::getUnderlyingExpr` has been added. It can be used to look through casts and not-null expressions and obtain the underlying expression to which they apply.
### Minor Analysis Improvements
* The JUnit5 version of `AssertNotNull` is now recognized, which removes related false positives in the nullness queries.
* Added data flow models for `java.util.Scanner`.
## 0.3.1
### New Features
* Added an `ErrorType` class. An instance of this class will be used if an extractor is unable to extract a type, or if an up/downgrade script is unable to provide a type.
### Minor Analysis Improvements
* Added data-flow models for `java.util.Properites`. Additional results may be found where relevant data is stored in and then retrieved from a `Properties` instance.
* Added `Modifier.isInline()`.
* Removed Kotlin-specific database and QL structures for loops and `break`/`continue` statements. The Kotlin extractor was changed to reuse the Java structures for these constructs.
* Added additional flow sources for uses of external storage on Android.
## 0.3.0
### Deprecated APIs

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
Added additional flow sources for uses of external storage on Android.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Removed Kotlin-specific database and QL structures for loops and `break`/`continue` statements. The Kotlin extractor was changed to reuse the Java structures for these constructs.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
Added `Modifier.isInline()`.

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Added an `ErrorType` class. An instance of this class will be used if an extractor is unable to extract a type, or if an up/downgrade script is unable to provide a type.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added data-flow models for `java.util.Properites`. Additional results may be found where relevant data is stored in and then retrieved from a `Properties` instance.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Improved analysis of the Android class `AsyncTask` so that data can properly flow through its methods according to the life-cycle steps described here: https://developer.android.com/reference/android/os/AsyncTask#the-4-steps.

View File

@@ -0,0 +1,12 @@
## 0.3.1
### New Features
* Added an `ErrorType` class. An instance of this class will be used if an extractor is unable to extract a type, or if an up/downgrade script is unable to provide a type.
### Minor Analysis Improvements
* Added data-flow models for `java.util.Properites`. Additional results may be found where relevant data is stored in and then retrieved from a `Properties` instance.
* Added `Modifier.isInline()`.
* Removed Kotlin-specific database and QL structures for loops and `break`/`continue` statements. The Kotlin extractor was changed to reuse the Java structures for these constructs.
* Added additional flow sources for uses of external storage on Android.

View File

@@ -0,0 +1,10 @@
## 0.3.2
### New Features
* The QL predicate `Expr::getUnderlyingExpr` has been added. It can be used to look through casts and not-null expressions and obtain the underlying expression to which they apply.
### Minor Analysis Improvements
* The JUnit5 version of `AssertNotNull` is now recognized, which removes related false positives in the nullness queries.
* Added data flow models for `java.util.Scanner`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.3.0
lastReleaseVersion: 0.3.2

View File

@@ -1,5 +1,5 @@
name: codeql/java-all
version: 0.3.1-dev
version: 0.3.3-dev
groups: java
dbscheme: config/semmlecode.dbscheme
extractor: java

View File

@@ -100,6 +100,18 @@ class Expr extends ExprParent, @expr {
/** Holds if this expression is parenthesized. */
predicate isParenthesized() { isParenthesized(this, _) }
/**
* Gets the underlying expression looking through casts and not-nulls, if any.
* Otherwise just gets this expression.
*/
Expr getUnderlyingExpr() {
if this instanceof CastingExpr or this instanceof NotNullExpr
then
result = this.(CastingExpr).getExpr().getUnderlyingExpr() or
result = this.(NotNullExpr).getExpr().getUnderlyingExpr()
else result = this
}
}
/**

View File

@@ -1194,8 +1194,8 @@ private Type erase(Type t) {
}
/**
* Is there a common (reflexive, transitive) subtype of the erasures of
* types `t1` and `t2`?
* Holds if there is a common (reflexive, transitive) subtype of the erasures of
* types `t1` and `t2`.
*
* If there is no such common subtype, then the two types are disjoint.
* However, the converse is not true; for example, the parameterized types
@@ -1212,6 +1212,25 @@ predicate haveIntersection(RefType t1, RefType t2) {
)
}
/**
* Holds if there is no common (reflexive, transitive) subtype of the erasures
* of types `t1` and `t2`.
*
* If there is no such common subtype, then the two types are disjoint.
* However, the converse is not true; for example, the parameterized types
* `List<Integer>` and `Collection<String>` are disjoint,
* but their erasures (`List` and `Collection`, respectively)
* do have common subtypes (such as `List` itself).
*
* For the definition of the notion of *erasure* see JLS v8, section 4.6 (Type Erasure).
*/
bindingset[t1, t2]
predicate notHaveIntersection(RefType t1, RefType t2) {
exists(RefType e1, RefType e2 | e1 = erase(t1) and e2 = erase(t2) |
not erasedHaveIntersection(e1, e2)
)
}
/**
* Holds if there is a common (reflexive, transitive) subtype of the erased
* types `t1` and `t2`.

View File

@@ -244,8 +244,26 @@ private class ContainerFlowSummaries extends SummaryModelCsv {
"java.util;Properties;true;getProperty;(String);;Argument[-1].MapValue;ReturnValue;value;manual",
"java.util;Properties;true;getProperty;(String,String);;Argument[-1].MapValue;ReturnValue;value;manual",
"java.util;Properties;true;getProperty;(String,String);;Argument[1];ReturnValue;value;manual",
"java.util;Scanner;true;next;(Pattern);;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;next;(String);;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual",
"java.util;Scanner;true;findInLine;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;findWithinHorizon;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;findWithinHorizon;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;next;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;nextBigDecimal;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;nextBigInteger;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;nextBoolean;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;nextByte;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;nextDouble;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;nextFloat;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;nextInt;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;nextLine;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;nextLong;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;nextShort;;;Argument[-1];ReturnValue;taint;manual",
"java.util;Scanner;true;reset;;;Argument[-1];ReturnValue;value;manual",
"java.util;Scanner;true;skip;;;Argument[-1];ReturnValue;value;manual",
"java.util;Scanner;true;useDelimiter;;;Argument[-1];ReturnValue;value;manual",
"java.util;Scanner;true;useLocale;;;Argument[-1];ReturnValue;value;manual",
"java.util;Scanner;true;useRadix;;;Argument[-1];ReturnValue;value;manual",
"java.util;SortedMap;true;headMap;(Object);;Argument[-1].MapKey;ReturnValue.MapKey;value;manual",
"java.util;SortedMap;true;headMap;(Object);;Argument[-1].MapValue;ReturnValue.MapValue;value;manual",
"java.util;SortedMap;true;subMap;(Object,Object);;Argument[-1].MapKey;ReturnValue.MapKey;value;manual",

File diff suppressed because it is too large Load Diff

View File

@@ -19,8 +19,9 @@ private predicate runner(Method m, int n, Method runmethod) {
exists(Parameter p, MethodAccess ma, int j |
p = m.getParameter(n) and
ma.getEnclosingCallable() = m and
runner(ma.getMethod().getSourceDeclaration(), j, _) and
ma.getArgument(j) = p.getAnAccess()
runner(pragma[only_bind_into](ma.getMethod().getSourceDeclaration()),
pragma[only_bind_into](j), _) and
ma.getArgument(pragma[only_bind_into](j)) = p.getAnAccess()
)
)
}

View File

@@ -2,7 +2,8 @@
* A library providing uniform access to various assertion frameworks.
*
* Currently supports `org.junit.Assert`, `junit.framework.*`,
* `com.google.common.base.Preconditions`, and `java.util.Objects`.
* `org.junit.jupiter.api.Assertions`, `com.google.common.base.Preconditions`,
* and `java.util.Objects`.
*/
import java
@@ -17,7 +18,11 @@ private newtype AssertKind =
private predicate assertionMethod(Method m, AssertKind kind) {
exists(RefType junit |
m.getDeclaringType() = junit and
(junit.hasQualifiedName("org.junit", "Assert") or junit.hasQualifiedName("junit.framework", _))
(
junit.hasQualifiedName("org.junit", "Assert") or
junit.hasQualifiedName("junit.framework", _) or
junit.hasQualifiedName("org.junit.jupiter.api", "Assertions")
)
|
m.hasName("assertNotNull") and kind = AssertKindNotNull()
or

View File

@@ -4,19 +4,62 @@ import java
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.FlowSteps
/**
* Models the value-preserving step from `asyncTask.execute(params)` to `AsyncTask::doInBackground(params)`.
/*
* The following flow steps aim to model the life-cycle of `AsyncTask`s described here:
* https://developer.android.com/reference/android/os/AsyncTask#the-4-steps
*/
private class AsyncTaskAdditionalValueStep extends AdditionalValueStep {
/**
* A taint step from the vararg arguments of `AsyncTask::execute` and `AsyncTask::executeOnExecutor`
* to the parameter of `AsyncTask::doInBackground`.
*/
private class AsyncTaskExecuteAdditionalValueStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
exists(ExecuteAsyncTaskMethodAccess ma, AsyncTaskRunInBackgroundMethod m |
DataFlow::getInstanceArgument(ma).getType() = m.getDeclaringType() and
DataFlow::getInstanceArgument(ma).getType() = m.getDeclaringType()
|
node1.asExpr() = ma.getParamsArgument() and
node2.asParameter() = m.getParameter(0)
)
}
}
/**
* A value-preserving step from the return value of `AsyncTask::doInBackground`
* to the parameter of `AsyncTask::onPostExecute`.
*/
private class AsyncTaskOnPostExecuteAdditionalValueStep extends AdditionalValueStep {
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
exists(
AsyncTaskRunInBackgroundMethod runInBackground, AsyncTaskOnPostExecuteMethod onPostExecute
|
onPostExecute.getDeclaringType() = runInBackground.getDeclaringType()
|
node1.asExpr() = any(ReturnStmt r | r.getEnclosingCallable() = runInBackground).getResult() and
node2.asParameter() = onPostExecute.getParameter(0)
)
}
}
/**
* A value-preserving step from field initializers in `AsyncTask`'s constructor or initializer method
* to the instance parameter of `AsyncTask::runInBackground` and `AsyncTask::onPostExecute`.
*/
private class AsyncTaskFieldInitQualifierToInstanceParameterStep extends AdditionalValueStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(AsyncTaskInit init, Callable receiver |
n1.(DataFlow::PostUpdateNode).getPreUpdateNode() =
DataFlow::getFieldQualifier(any(FieldWrite f | f.getEnclosingCallable() = init)) and
n2.(DataFlow::InstanceParameterNode).getCallable() = receiver and
receiver.getDeclaringType() = init.getDeclaringType() and
(
receiver instanceof AsyncTaskRunInBackgroundMethod or
receiver instanceof AsyncTaskOnPostExecuteMethod
)
)
}
}
/**
* The Android class `android.os.AsyncTask`.
*/
@@ -24,29 +67,38 @@ private class AsyncTask extends RefType {
AsyncTask() { this.hasQualifiedName("android.os", "AsyncTask") }
}
/** The constructor or initializer method of the `android.os.AsyncTask` class. */
private class AsyncTaskInit extends Callable {
AsyncTaskInit() {
this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and
(this instanceof Constructor or this instanceof InitializerMethod)
}
}
/** A call to the `execute` or `executeOnExecutor` methods of the `android.os.AsyncTask` class. */
private class ExecuteAsyncTaskMethodAccess extends MethodAccess {
Argument paramsArgument;
ExecuteAsyncTaskMethodAccess() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask
|
m.getName() = "execute" and not m.isStatic() and paramsArgument = this.getArgument(0)
or
m.getName() = "executeOnExecutor" and paramsArgument = this.getArgument(1)
)
this.getMethod().hasName(["execute", "executeOnExecutor"]) and
this.getMethod().getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof
AsyncTask
}
/** Returns the `params` argument of this call. */
Argument getParamsArgument() { result = paramsArgument }
Argument getParamsArgument() { result = this.getAnArgument() and result.isVararg() }
}
/** The `doInBackground` method of the `android.os.AsyncTask` class. */
private class AsyncTaskRunInBackgroundMethod extends Method {
AsyncTaskRunInBackgroundMethod() {
this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and
this.getName() = "doInBackground"
this.hasName("doInBackground")
}
}
/** The `onPostExecute` method of the `android.os.AsyncTask` class. */
private class AsyncTaskOnPostExecuteMethod extends Method {
AsyncTaskOnPostExecuteMethod() {
this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and
this.hasName("onPostExecute")
}
}

View File

@@ -0,0 +1,29 @@
/** Definitions for the web view certificate validation query */
import java
/** A method that overrides `WebViewClient.onReceivedSslError` */
class OnReceivedSslErrorMethod extends Method {
OnReceivedSslErrorMethod() {
this.overrides*(any(Method m |
m.hasQualifiedName("android.webkit", "WebViewClient", "onReceivedSslError")
))
}
/** Gets the `SslErrorHandler` argument to this method. */
Parameter handlerArg() { result = this.getParameter(1) }
}
/** A call to `SslErrorHandler.proceed` */
private class SslProceedCall extends MethodAccess {
SslProceedCall() {
this.getMethod().hasQualifiedName("android.webkit", "SslErrorHandler", "proceed")
}
}
/** Holds if `m` trusts all certificates by calling `SslErrorHandler.proceed` unconditionally. */
predicate trustsAllCerts(OnReceivedSslErrorMethod m) {
exists(SslProceedCall pr | pr.getQualifier().(VarAccess).getVariable() = m.handlerArg() |
pr.getBasicBlock().bbPostDominates(m.getBody().getBasicBlock())
)
}

View File

@@ -51,7 +51,7 @@ private predicate sharedPreferencesInput(DataFlow::Node editor, Expr input) {
exists(MethodAccess m |
m.getMethod() instanceof PutSharedPreferenceMethod and
input = m.getArgument(1) and
editor.asExpr() = m.getQualifier()
editor.asExpr() = m.getQualifier().getUnderlyingExpr()
)
}
@@ -61,7 +61,7 @@ private predicate sharedPreferencesInput(DataFlow::Node editor, Expr input) {
*/
private predicate sharedPreferencesStore(DataFlow::Node editor, MethodAccess m) {
m.getMethod() instanceof StoreSharedPreferenceMethod and
editor.asExpr() = m.getQualifier()
editor.asExpr() = m.getQualifier().getUnderlyingExpr()
}
/** Flow from `SharedPreferences.Editor` to either a setter or a store method. */

View File

@@ -75,6 +75,8 @@ private predicate webViewLoadUrl(Argument urlArg, WebViewRef webview) {
loadUrl.getArgument(0) = urlArg and
loadUrl.getMethod() instanceof WebViewLoadUrlMethod
|
webview.getAnAccess() = DataFlow::exprNode(loadUrl.getQualifier().getUnderlyingExpr())
or
webview.getAnAccess() = DataFlow::getInstanceArgument(loadUrl)
or
// `webview` is received as a parameter of an event method in a custom `WebViewClient`,
@@ -82,8 +84,9 @@ private predicate webViewLoadUrl(Argument urlArg, WebViewRef webview) {
exists(WebViewClientEventMethod eventMethod, MethodAccess setWebClient |
setWebClient.getMethod() instanceof WebViewSetWebViewClientMethod and
setWebClient.getArgument(0).getType() = eventMethod.getDeclaringType() and
loadUrl.getQualifier() = eventMethod.getWebViewParameter().getAnAccess()
loadUrl.getQualifier().getUnderlyingExpr() = eventMethod.getWebViewParameter().getAnAccess()
|
webview.getAnAccess() = DataFlow::exprNode(setWebClient.getQualifier().getUnderlyingExpr()) or
webview.getAnAccess() = DataFlow::getInstanceArgument(setWebClient)
)
)

View File

@@ -1,3 +1,17 @@
## 0.3.1
## 0.3.0
### Breaking Changes
* Contextual queries and the query libraries they depend on have been moved to the `codeql/java-all` package.
### New Queries
* A new query "Improper verification of intent by broadcast receiver" (`java/improper-intent-verification`) has been added.
This query finds instances of Android `BroadcastReceiver`s that don't verify the action string of received intents when registered
to receive system intents.
## 0.2.0
### Minor Analysis Improvements

View File

@@ -118,7 +118,7 @@ class MismatchedContainerAccess extends MethodAccess {
containerAccess(package, type, p, this.getCallee().getSignature(), i)
|
t = this.getCallee().getDeclaringType() and
t.getAnAncestor().getSourceDeclaration() = g and
t.getASourceSupertype*().getSourceDeclaration() = g and
g.hasQualifiedName(package, type) and
indirectlyInstantiates(t, g, p, result)
)
@@ -139,7 +139,7 @@ from MismatchedContainerAccess ma, RefType typearg, RefType argtype, int idx
where
typearg = ma.getReceiverElementType(idx).getSourceDeclaration() and
argtype = ma.getArgumentType(idx) and
not haveIntersection(typearg, argtype)
notHaveIntersection(typearg, argtype)
select ma.getArgument(idx),
"Actual argument type '" + argtype.getName() + "'" +
" is incompatible with expected argument type '" + typearg.getName() + "'."

View File

@@ -88,7 +88,7 @@ class MismatchedContainerModification extends MethodAccess {
containerModification(package, type, p, this.getCallee().getSignature(), i)
|
t = this.getCallee().getDeclaringType() and
t.getAnAncestor().getSourceDeclaration() = g and
t.getASourceSupertype*().getSourceDeclaration() = g and
g.hasQualifiedName(package, type) and
indirectlyInstantiates(t, g, p, result)
)
@@ -109,7 +109,7 @@ from MismatchedContainerModification ma, RefType elementtype, RefType argtype, i
where
elementtype = ma.getReceiverElementType(idx).getSourceDeclaration() and
argtype = ma.getArgumentType(idx) and
not haveIntersection(elementtype, argtype)
notHaveIntersection(elementtype, argtype)
select ma.getArgument(idx),
"Actual argument type '" + argtype.getName() + "'" +
" is incompatible with expected argument type '" + elementtype.getName() + "'."

View File

@@ -57,7 +57,7 @@ where
else recvtp = ma.getMethod().getDeclaringType()
) and
argtp = ma.getArgumentType() and
not haveIntersection(recvtp, argtp)
notHaveIntersection(recvtp, argtp)
select ma,
"Call to equals() comparing incomparable types " + recvtp.getName() + " and " + argtp.getName() +
"."

View File

@@ -15,6 +15,7 @@
import java
import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.security.PathCreation
import DataFlow::PathGraph
import TaintedPathCommon
@@ -34,7 +35,12 @@ class TaintedPathConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
exists(Expr e | e = sink.asExpr() | e = any(PathCreation p).getAnInput() and not guarded(e))
(
sink.asExpr() = any(PathCreation p).getAnInput()
or
sinkNode(sink, "create-file")
) and
not guarded(sink.asExpr())
}
override predicate isSanitizer(DataFlow::Node node) {
@@ -44,9 +50,21 @@ class TaintedPathConfig extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, PathCreation p, TaintedPathConfig conf
where
sink.getNode().asExpr() = p.getAnInput() and
conf.hasFlowPath(source, sink)
select p, source, sink, "$@ flows to here and is used in a path.", source.getNode(),
"User-provided value"
/**
* Gets the data-flow node at which to report a path ending at `sink`.
*
* Previously this query flagged alerts exclusively at `PathCreation` sites,
* so to avoid perturbing existing alerts, where a `PathCreation` exists we
* continue to report there; otherwise we report directly at `sink`.
*/
DataFlow::Node getReportingNode(DataFlow::Node sink) {
any(TaintedPathConfig c).hasFlowTo(sink) and
if exists(PathCreation pc | pc.getAnInput() = sink.asExpr())
then result.asExpr() = any(PathCreation pc | pc.getAnInput() = sink.asExpr())
else result = sink
}
from DataFlow::PathNode source, DataFlow::PathNode sink, TaintedPathConfig conf
where conf.hasFlowPath(source, sink)
select getReportingNode(sink.getNode()), source, sink, "$@ flows to here and is used in a path.",
source.getNode(), "User-provided value"

View File

@@ -0,0 +1,22 @@
class Bad extends WebViewClient {
// BAD: All certificates are trusted.
public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { // $hasResult
handler.proceed();
}
}
class Good extends WebViewClient {
PublicKey myPubKey = ...;
// GOOD: Only certificates signed by a certain public key are trusted.
public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { // $hasResult
try {
X509Certificate cert = error.getCertificate().getX509Certificate();
cert.verify(this.myPubKey);
handler.proceed();
}
catch (CertificateException|NoSuchAlgorithmException|InvalidKeyException|NoSuchProviderException|SignatureException e) {
handler.cancel();
}
}
}

View File

@@ -0,0 +1,46 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
If the <code>onReceivedSslError</code> method of an Android <code>WebViewClient</code> always calls <code>proceed</code> on the given <code>SslErrorHandler</code>, it trusts any certificate.
This allows an attacker to perform a machine-in-the-middle attack against the application, therefore breaking any security Transport Layer Security (TLS) gives.
</p>
<p>
An attack might look like this:
</p>
<ol>
<li>The vulnerable application connects to <code>https://example.com</code>.</li>
<li>The attacker intercepts this connection and presents a valid, self-signed certificate for <code>https://example.com</code>.</li>
<li>The vulnerable application calls the <code>onReceivedSslError</code> method to check whether it should trust the certificate.</li>
<li>The <code>onReceivedSslError</code> method of your <code>WebViewClient</code> calls <code>SslErrorHandler.proceed</code>.</li>
<li>The vulnerable application accepts the certificate and proceeds with the connection since your <code>WevViewClient</code> trusted it by proceeding.</li>
<li>The attacker can now read the data your application sends to <code>https://example.com</code> and/or alter its replies while the application thinks the connection is secure.</li>
</ol>
</overview>
<recommendation>
<p>
Do not use a call <code>SslerrorHandler.proceed</code> unconditionally.
If you have to use a self-signed certificate, only accept that certificate, not all certificates.
</p>
</recommendation>
<example>
<p>
In the first (bad) example, the <code>WebViewClient</code> trusts all certificates by always calling <code>SslErrorHandler.proceed</code>.
In the second (good) example, only certificates signed by a certain public key are accepted.
</p>
<sample src="ImproperWebViewCertificateValidation.java" />
</example>
<references>
<li>
<a href="https://developer.android.com/reference/android/webkit/WebViewClient?hl=en#onReceivedSslError(android.webkit.WebView,%20android.webkit.SslErrorHandler,%20android.net.http.SslError)">WebViewClient.onReceivedSslError documentation</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,18 @@
/**
* @name Android `WebView` that accepts all certificates
* @description Trusting all certificates allows an attacker to perform a machine-in-the-middle attack.
* @kind problem
* @problem.severity error
* @security-severity 7.5
* @precision high
* @id java/improper-webview-certificate-validation
* @tags security
* external/cwe/cwe-295
*/
import java
import semmle.code.java.security.AndroidWebViewCertificateValidationQuery
from OnReceivedSslErrorMethod m
where trustsAllCerts(m)
select m, "This handler accepts all SSL certificates."

View File

@@ -60,13 +60,43 @@ private predicate candidateMethod(RefType t, Method m, string name, int numParam
not whitelist(name)
}
pragma[inline]
private predicate potentiallyConfusingTypes(Type a, Type b) {
exists(RefType commonSubtype | hasSubtypeOrInstantiation*(a, commonSubtype) |
hasSubtypeOrInstantiation*(b, commonSubtype)
predicate paramTypePair(Type t1, Type t2) {
exists(Method n, Method m, int i |
overloadedMethodsMostSpecific(n, m) and
t1 = n.getParameterType(i) and
t2 = m.getParameterType(i)
)
}
// handle simple cases separately
predicate potentiallyConfusingTypesSimple(Type t1, Type t2) {
paramTypePair(t1, t2) and
(
t1 = t2
or
t1 instanceof TypeObject and t2 instanceof RefType
or
t2 instanceof TypeObject and t1 instanceof RefType
or
confusingPrimitiveBoxedTypes(t1, t2)
)
}
// check erased types first
predicate potentiallyConfusingTypesRefTypes(RefType t1, RefType t2) {
paramTypePair(t1, t2) and
not potentiallyConfusingTypesSimple(t1, t2) and
haveIntersection(t1, t2)
}
// then check hasSubtypeOrInstantiation
predicate potentiallyConfusingTypes(Type t1, Type t2) {
potentiallyConfusingTypesSimple(t1, t2)
or
confusingPrimitiveBoxedTypes(a, b)
potentiallyConfusingTypesRefTypes(t1, t2) and
exists(RefType commonSubtype | hasSubtypeOrInstantiation*(t1, commonSubtype) |
hasSubtypeOrInstantiation*(t2, commonSubtype)
)
}
private predicate hasSubtypeOrInstantiation(RefType t, RefType sub) {

View File

@@ -16,5 +16,5 @@ from RefType sub, RefType sup
where
sub.fromSource() and
sup = sub.getASupertype() and
sub.getName() = sup.getName()
pragma[only_bind_out](sub.getName()) = pragma[only_bind_out](sup.getName())
select sub, sub.getName() + " has the same name as its supertype $@.", sup, sup.getQualifiedName()

View File

@@ -1,6 +0,0 @@
---
category: newQuery
---
* A new query "Improper verification of intent by broadcast receiver" (`java/improper-intent-verification`) has been added.
This query finds instances of Android `BroadcastReceiver`s that don't verify the action string of received intents when registered
to receive system intents.

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* A new query "Android `WebView` that accepts all certificates" (`java/improper-webview-certificate-validation`) has been added. This query finds implementations of `WebViewClient`s that accept all certificates in the case of an SSL error.

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* Contextual queries and the query libraries they depend on have been moved to the `codeql/java-all` package.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The query `java/path-injection` now recognises vulnerable APIs defined using the `SinkModelCsv` class with the `create-file` type. Out of the box this includes Apache Commons-IO functions, as well as any user-defined sinks.

View File

@@ -0,0 +1,11 @@
## 0.3.0
### Breaking Changes
* Contextual queries and the query libraries they depend on have been moved to the `codeql/java-all` package.
### New Queries
* A new query "Improper verification of intent by broadcast receiver" (`java/improper-intent-verification`) has been added.
This query finds instances of Android `BroadcastReceiver`s that don't verify the action string of received intents when registered
to receive system intents.

View File

@@ -0,0 +1 @@
## 0.3.1

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.2.0
lastReleaseVersion: 0.3.1

View File

@@ -0,0 +1,46 @@
// BAD: Using an outdated SDK that does not support client side encryption version V2_0
new EncryptedBlobClientBuilder()
.blobClient(blobClient)
.key(resolver.buildAsyncKeyEncryptionKey(keyid).block(), keyWrapAlgorithm)
.buildEncryptedBlobClient()
.uploadWithResponse(new BlobParallelUploadOptions(data)
.setMetadata(metadata)
.setHeaders(headers)
.setTags(tags)
.setTier(tier)
.setRequestConditions(requestConditions)
.setComputeMd5(computeMd5)
.setParallelTransferOptions(parallelTransferOptions),
timeout, context);
// BAD: Using the deprecatedd client side encryption version V1_0
new EncryptedBlobClientBuilder(EncryptionVersion.V1)
.blobClient(blobClient)
.key(resolver.buildAsyncKeyEncryptionKey(keyid).block(), keyWrapAlgorithm)
.buildEncryptedBlobClient()
.uploadWithResponse(new BlobParallelUploadOptions(data)
.setMetadata(metadata)
.setHeaders(headers)
.setTags(tags)
.setTier(tier)
.setRequestConditions(requestConditions)
.setComputeMd5(computeMd5)
.setParallelTransferOptions(parallelTransferOptions),
timeout, context);
// GOOD: Using client side encryption version V2_0
new EncryptedBlobClientBuilder(EncryptionVersion.V2)
.blobClient(blobClient)
.key(resolver.buildAsyncKeyEncryptionKey(keyid).block(), keyWrapAlgorithm)
.buildEncryptedBlobClient()
.uploadWithResponse(new BlobParallelUploadOptions(data)
.setMetadata(metadata)
.setHeaders(headers)
.setTags(tags)
.setTier(tier)
.setRequestConditions(requestConditions)
.setComputeMd5(computeMd5)
.setParallelTransferOptions(parallelTransferOptions),
timeout, context);

View File

@@ -0,0 +1,29 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>Azure Storage .NET, Java, and Python SDKs support encryption on the client with a customer-managed key that is maintained in Azure Key Vault or another key store.</p>
<p>The Azure Storage SDK version 12.18.0 or later supports version <code>V2</code> for client-side encryption. All previous versions of Azure Storage SDK only support client-side encryption <code>V1</code> which is unsafe.</p>
</overview>
<recommendation>
<p>Consider switching to <code>V2</code> client-side encryption.</p>
</recommendation>
<example>
<sample src="UnsafeUsageOfClientSideEncryptionVersion.java" />
</example>
<references>
<li>
<a href="http://aka.ms/azstorageclientencryptionblog">Azure Storage Client Encryption Blog.</a>
</li>
<li>
<a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-30187">CVE-2022-30187</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,92 @@
/**
* @name Unsafe usage of v1 version of Azure Storage client-side encryption (CVE-2022-30187).
* @description Unsafe usage of v1 version of Azure Storage client-side encryption, please refer to http://aka.ms/azstorageclientencryptionblog
* @kind problem
* @tags security
* cryptography
* external/cwe/cwe-327
* @id java/azure-storage/unsafe-client-side-encryption-in-use
* @problem.severity error
* @precision high
*/
import java
import semmle.code.java.dataflow.DataFlow
/**
* Holds if `call` is an object creation for a class `EncryptedBlobClientBuilder`
* that takes no arguments, which means that it is using V1 encryption.
*/
predicate isCreatingOutdatedAzureClientSideEncryptionObject(Call call, Class c) {
exists(string package, string type, Constructor constructor |
c.hasQualifiedName(package, type) and
c.getAConstructor() = constructor and
call.getCallee() = constructor and
(
type = "EncryptedBlobClientBuilder" and
package = "com.azure.storage.blob.specialized.cryptography" and
constructor.hasNoParameters()
or
type = "BlobEncryptionPolicy" and package = "com.microsoft.azure.storage.blob"
)
)
}
/**
* Holds if `call` is an object creation for a class `EncryptedBlobClientBuilder`
* that takes `versionArg` as the argument specifying the encryption version.
*/
predicate isCreatingAzureClientSideEncryptionObjectNewVersion(Call call, Class c, Expr versionArg) {
exists(string package, string type, Constructor constructor |
c.hasQualifiedName(package, type) and
c.getAConstructor() = constructor and
call.getCallee() = constructor and
type = "EncryptedBlobClientBuilder" and
package = "com.azure.storage.blob.specialized.cryptography" and
versionArg = call.getArgument(0)
)
}
/**
* A dataflow config that tracks `EncryptedBlobClientBuilder.version` argument initialization.
*/
private class EncryptedBlobClientBuilderSafeEncryptionVersionConfig extends DataFlow::Configuration {
EncryptedBlobClientBuilderSafeEncryptionVersionConfig() {
this = "EncryptedBlobClientBuilderSafeEncryptionVersionConfig"
}
override predicate isSource(DataFlow::Node source) {
exists(FieldRead fr, Field f | fr = source.asExpr() |
f.getAnAccess() = fr and
f.hasQualifiedName("com.azure.storage.blob.specialized.cryptography", "EncryptionVersion",
"V2")
)
}
override predicate isSink(DataFlow::Node sink) {
isCreatingAzureClientSideEncryptionObjectNewVersion(_, _, sink.asExpr())
}
}
/**
* Holds if `call` is an object creation for a class `EncryptedBlobClientBuilder`
* that takes `versionArg` as the argument specifying the encryption version, and that version is safe.
*/
predicate isCreatingSafeAzureClientSideEncryptionObject(Call call, Class c, Expr versionArg) {
isCreatingAzureClientSideEncryptionObjectNewVersion(call, c, versionArg) and
exists(EncryptedBlobClientBuilderSafeEncryptionVersionConfig config, DataFlow::Node sink |
sink.asExpr() = versionArg
|
config.hasFlow(_, sink)
)
}
from Expr e, Class c
where
exists(Expr argVersion |
isCreatingAzureClientSideEncryptionObjectNewVersion(e, c, argVersion) and
not isCreatingSafeAzureClientSideEncryptionObject(e, c, argVersion)
)
or
isCreatingOutdatedAzureClientSideEncryptionObject(e, c)
select e, "Unsafe usage of v1 version of Azure Storage client-side encryption."

View File

@@ -1,5 +1,5 @@
name: codeql/java-queries
version: 0.2.1-dev
version: 0.3.2-dev
groups:
- java
- queries

View File

@@ -20,3 +20,15 @@ private class KtExpectationComment extends KtComment, ExpectationComment {
override string getContents() { result = this.getText().suffix(2).trim() }
}
private class XmlExpectationComment extends ExpectationComment instanceof XMLComment {
override string getContents() { result = this.(XMLComment).getText().trim() }
override Location getLocation() { result = this.(XMLComment).getLocation() }
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
this.(XMLComment).hasLocationInfo(path, sl, sc, el, ec)
}
override string toString() { result = this.(XMLComment).toString() }
}

View File

@@ -4,17 +4,13 @@ edges
| FileService.java:21:28:21:64 | getStringExtra(...) : Object | FileService.java:25:42:25:50 | localPath : Object |
| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:40:41:40:55 | params : Object[] |
| FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] |
| FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object | FileService.java:40:41:40:55 | params [[]] : Object |
| FileService.java:25:42:25:50 | localPath : Object | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : Object |
| FileService.java:25:42:25:50 | localPath : Object | FileService.java:32:13:32:28 | sourceUri : Object |
| FileService.java:32:13:32:28 | sourceUri : Object | FileService.java:35:17:35:25 | sourceUri : Object |
| FileService.java:34:20:36:13 | {...} [[]] : Object | FileService.java:34:20:36:13 | new Object[] [[]] : Object |
| FileService.java:35:17:35:25 | sourceUri : Object | FileService.java:34:20:36:13 | {...} [[]] : Object |
| FileService.java:40:41:40:55 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object |
| FileService.java:40:41:40:55 | params [[]] : Object | FileService.java:44:44:44:49 | params [[]] : Object |
| FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] |
| FileService.java:44:44:44:49 | params [[]] : Object | FileService.java:44:44:44:52 | ...[...] : Object |
| FileService.java:44:44:44:52 | ...[...] : Object | FileService.java:44:33:44:52 | (...)... : Object |
| LeakFileActivity2.java:15:13:15:18 | intent : Intent | LeakFileActivity2.java:16:26:16:31 | intent : Intent |
| LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:20:31:20:43 | intent : Intent |
| LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent |
@@ -34,10 +30,7 @@ nodes
| FileService.java:34:20:36:13 | {...} [[]] : Object | semmle.label | {...} [[]] : Object |
| FileService.java:35:17:35:25 | sourceUri : Object | semmle.label | sourceUri : Object |
| FileService.java:40:41:40:55 | params : Object[] | semmle.label | params : Object[] |
| FileService.java:40:41:40:55 | params [[]] : Object | semmle.label | params [[]] : Object |
| FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object |
| FileService.java:44:44:44:49 | params [[]] : Object | semmle.label | params [[]] : Object |
| FileService.java:44:44:44:52 | ...[...] : Object | semmle.label | ...[...] : Object |
| FileService.java:45:53:45:59 | ...[...] | semmle.label | ...[...] |
| LeakFileActivity2.java:15:13:15:18 | intent : Intent | semmle.label | intent : Intent |
| LeakFileActivity2.java:16:26:16:31 | intent : Intent | semmle.label | intent : Intent |

View File

@@ -0,0 +1,9 @@
| test.kt:5:14:5:14 | hasNext(...) |
| test.kt:5:14:5:14 | iterator(...) |
| test.kt:5:14:5:14 | next(...) |
| test.kt:6:14:6:14 | hasNext(...) |
| test.kt:6:14:6:14 | iterator(...) |
| test.kt:6:14:6:14 | next(...) |
| test.kt:7:14:7:14 | hasNext(...) |
| test.kt:7:14:7:14 | iterator(...) |
| test.kt:7:14:7:14 | next(...) |

View File

@@ -0,0 +1,11 @@
fun test(x: Array<String>, y: Array<*>, z: IntArray): Int {
var ret = 0
for (el in x) { ret += 1 }
for (el in y) { ret += 1 }
for (el in z) { ret += 1 }
return ret
}

View File

@@ -0,0 +1,4 @@
import java
from MethodAccess ma
select ma

View File

@@ -14,8 +14,8 @@ calls
| test.kt:22:15:22:33 | setter(...) | test.kt:12:1:25:1 | user | test.kt:0:0:0:0 | TestKt | file:///!unknown-binary-location/Generic.class:0:0:0:0 | setter | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic<? super String> |
| test.kt:23:15:23:22 | getter(...) | test.kt:12:1:25:1 | user | test.kt:0:0:0:0 | TestKt | file:///!unknown-binary-location/Generic.class:0:0:0:0 | getter | file:///!unknown-binary-location/Generic.class:0:0:0:0 | Generic<? super String> |
constructors
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2<? extends String>(java.lang.String) | ? extends String | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2<? super String>(java.lang.Object) | ? super String | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2<? extends String>(<nulltype>) | <nulltype> | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2<? super String>(java.lang.String) | String | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | Generic2<String> | Generic2<String>(java.lang.String) | String | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
| Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 | Generic2(java.lang.Object) | T | void | Test.java:1:7:1:14 | Generic2 | Test.java:3:10:3:17 | Generic2 |
| Test.java:14:14:14:17 | Test | Test.java:14:14:14:17 | Test | Test() | No parameters | void | Test.java:14:14:14:17 | Test | Test.java:14:14:14:17 | Test |
@@ -34,14 +34,14 @@ refTypes
| test.kt:1:1:10:1 | Generic |
| test.kt:1:15:1:15 | T |
#select
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | ? extends String | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | identity | identity(java.lang.String) | ? extends String | ? extends String | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | identity2 | identity2(java.lang.String) | ? extends String | ? extends String | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | setter | setter(java.lang.String) | ? extends String | void | Test.java:1:7:1:14 | Generic2 | Test.java:10:8:10:13 | setter |
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | ? super String | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | identity | identity(java.lang.Object) | ? super String | ? super String | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | identity2 | identity2(java.lang.Object) | ? super String | ? super String | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | setter | setter(java.lang.Object) | ? super String | void | Test.java:1:7:1:14 | Generic2 | Test.java:10:8:10:13 | setter |
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | String | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | identity | identity(<nulltype>) | <nulltype> | String | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | identity2 | identity2(<nulltype>) | <nulltype> | String | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |
| Generic2.class:0:0:0:0 | Generic2<? extends String> | Generic2.class:0:0:0:0 | setter | setter(<nulltype>) | <nulltype> | void | Test.java:1:7:1:14 | Generic2 | Test.java:10:8:10:13 | setter |
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | Object | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | identity | identity(java.lang.String) | String | Object | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | identity2 | identity2(java.lang.String) | String | Object | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |
| Generic2.class:0:0:0:0 | Generic2<? super String> | Generic2.class:0:0:0:0 | setter | setter(java.lang.String) | String | void | Test.java:1:7:1:14 | Generic2 | Test.java:10:8:10:13 | setter |
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | getter | getter() | No parameters | String | Test.java:1:7:1:14 | Generic2 | Test.java:9:5:9:10 | getter |
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | identity | identity(java.lang.String) | String | String | Test.java:1:7:1:14 | Generic2 | Test.java:8:5:8:12 | identity |
| Generic2.class:0:0:0:0 | Generic2<String> | Generic2.class:0:0:0:0 | identity2 | identity2(java.lang.String) | String | String | Test.java:1:7:1:14 | Generic2 | Test.java:7:5:7:13 | identity2 |

View File

@@ -8,7 +8,7 @@ reflection.kt:
# 46| 0: [TypeAccess] String
# 47| 5: [BlockStmt] { ... }
# 47| 0: [ReturnStmt] return ...
# 47| 0: [MethodAccess] get(...)
# 47| 0: [MethodAccess] charAt(...)
# 47| -1: [ExtensionReceiverAccess] this
# 47| 0: [SubExpr] ... - ...
# 47| 0: [MethodAccess] length(...)

View File

@@ -0,0 +1,5 @@
public class Test {
public char f(String s) { return s.charAt(0); }
}

View File

@@ -0,0 +1,2 @@
| Test.java:3:36:3:46 | charAt(...) |
| test.kt:2:20:2:23 | charAt(...) |

View File

@@ -0,0 +1,2 @@
fun f(x: String) = x[0]

View File

@@ -0,0 +1,4 @@
import java
from MethodAccess ma
select ma

View File

@@ -0,0 +1,2 @@
| test.kt:31:17:31:24 | source(...) | test.kt:31:15:31:25 | f(...) |
| test.kt:32:17:32:24 | source(...) | test.kt:32:15:32:25 | g(...) |

View File

@@ -0,0 +1,36 @@
open class A {
open fun f(x: String) = x
}
interface B {
fun g(x: String) = x
}
interface C {
fun g(x: String) = x
}
class User : A(), B, C {
override fun f(x: String) = super.f(x)
override fun g(x: String) = super<B>.g(x)
fun source() = "tainted"
fun sink(s: String) { }
fun test() {
sink(this.f(source()))
sink(this.g(source()))
}
}

View File

@@ -0,0 +1,18 @@
import java
import semmle.code.java.dataflow.DataFlow
class Config extends DataFlow::Configuration {
Config() { this = "abc" }
override predicate isSource(DataFlow::Node n) {
n.asExpr().(MethodAccess).getMethod().getName() = "source"
}
override predicate isSink(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().getName() = "sink"
}
}
from Config c, DataFlow::Node n1, DataFlow::Node n2
where c.hasFlow(n1, n2)
select n1, n2

View File

@@ -10,16 +10,19 @@ public class Test {
public void test() {
TestAsyncTask t = new TestAsyncTask();
t.execute(source("execute"));
t.executeOnExecutor(null, source("executeOnExecutor"));
t.execute(source("execute"), null);
t.executeOnExecutor(null, source("executeOnExecutor"), null);
SafeAsyncTask t2 = new SafeAsyncTask();
t2.execute("safe");
TestConstructorTask t3 = new TestConstructorTask(source("constructor"), "safe");
t3.execute(source("params"));
}
private class TestAsyncTask extends AsyncTask<Object, Object, Object> {
@Override
protected Object doInBackground(Object... params) {
sink(params); // $ hasValueFlow=execute hasValueFlow=executeOnExecutor
sink(params[0]); // $ hasTaintFlow=execute hasTaintFlow=executeOnExecutor
sink(params[1]); // $ SPURIOUS: hasTaintFlow=execute hasTaintFlow=executeOnExecutor
return null;
}
}
@@ -27,8 +30,40 @@ public class Test {
private class SafeAsyncTask extends AsyncTask<Object, Object, Object> {
@Override
protected Object doInBackground(Object... params) {
sink(params); // Safe
sink(params[0]); // Safe
return null;
}
}
static class TestConstructorTask extends AsyncTask<Object, Object, Object> {
private Object field;
private Object safeField;
private Object initField;
{
initField = Test.source("init");
}
public TestConstructorTask(Object field, Object safeField) {
this.field = field;
this.safeField = safeField;
}
@Override
protected Object doInBackground(Object... params) {
sink(params[0]); // $ hasTaintFlow=params
sink(field); // $ hasValueFlow=constructor
sink(safeField); // Safe
sink(initField); // $ hasValueFlow=init
return params[0];
}
@Override
protected void onPostExecute(Object param) {
sink(param); // $ hasTaintFlow=params
sink(field); // $ hasValueFlow=constructor
sink(safeField); // Safe
sink(initField); // $ hasValueFlow=init
}
}
}

View File

@@ -1,6 +1,2 @@
import java
import TestUtilities.InlineFlowTest
class AsyncTaskTest extends InlineFlowTest {
override TaintTracking::Configuration getTaintFlowConfig() { none() }
}

View File

@@ -0,0 +1,328 @@
package generatedtest;
import java.io.File;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.Scanner;
import java.util.regex.Pattern;
// Test case generated by GenerateFlowTestCase.ql
public class Test {
Object source() {
return null;
}
void sink(Object o) {}
public void test() throws Exception {
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
File in = (File) source();
out = new Scanner(in);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
File in = (File) source();
out = new Scanner(in, (Charset) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
File in = (File) source();
out = new Scanner(in, (String) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
InputStream in = (InputStream) source();
out = new Scanner(in);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
InputStream in = (InputStream) source();
out = new Scanner(in, (Charset) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
InputStream in = (InputStream) source();
out = new Scanner(in, (String) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
Path in = (Path) source();
out = new Scanner(in);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
Path in = (Path) source();
out = new Scanner(in, (Charset) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
Path in = (Path) source();
out = new Scanner(in, (String) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
Readable in = (Readable) source();
out = new Scanner(in);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
ReadableByteChannel in = (ReadableByteChannel) source();
out = new Scanner(in);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
ReadableByteChannel in = (ReadableByteChannel) source();
out = new Scanner(in, (Charset) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
ReadableByteChannel in = (ReadableByteChannel) source();
out = new Scanner(in, (String) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;Scanner;;;Argument[0];Argument[-1];taint;manual"
Scanner out = null;
String in = (String) source();
out = new Scanner(in);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;findInLine;;;Argument[-1];ReturnValue;taint;manual"
String out = null;
Scanner in = (Scanner) source();
out = in.findInLine((Pattern) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;findInLine;;;Argument[-1];ReturnValue;taint;manual"
String out = null;
Scanner in = (Scanner) source();
out = in.findInLine((String) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;findWithinHorizon;;;Argument[-1];ReturnValue;taint;manual"
String out = null;
Scanner in = (Scanner) source();
out = in.findWithinHorizon((Pattern) null, 0);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;findWithinHorizon;;;Argument[-1];ReturnValue;taint;manual"
String out = null;
Scanner in = (Scanner) source();
out = in.findWithinHorizon((String) null, 0);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;next;;;Argument[-1];ReturnValue;taint;manual"
String out = null;
Scanner in = (Scanner) source();
out = in.next((Pattern) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;next;;;Argument[-1];ReturnValue;taint;manual"
String out = null;
Scanner in = (Scanner) source();
out = in.next((String) null);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;next;;;Argument[-1];ReturnValue;taint;manual"
String out = null;
Scanner in = (Scanner) source();
out = in.next();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextBigDecimal;;;Argument[-1];ReturnValue;taint;manual"
BigDecimal out = null;
Scanner in = (Scanner) source();
out = in.nextBigDecimal();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextBigInteger;;;Argument[-1];ReturnValue;taint;manual"
BigInteger out = null;
Scanner in = (Scanner) source();
out = in.nextBigInteger();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextBigInteger;;;Argument[-1];ReturnValue;taint;manual"
BigInteger out = null;
Scanner in = (Scanner) source();
out = in.nextBigInteger(0);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextBoolean;;;Argument[-1];ReturnValue;taint;manual"
boolean out = false;
Scanner in = (Scanner) source();
out = in.nextBoolean();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextByte;;;Argument[-1];ReturnValue;taint;manual"
byte out = 0;
Scanner in = (Scanner) source();
out = in.nextByte();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextByte;;;Argument[-1];ReturnValue;taint;manual"
byte out = 0;
Scanner in = (Scanner) source();
out = in.nextByte(0);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextDouble;;;Argument[-1];ReturnValue;taint;manual"
double out = 0;
Scanner in = (Scanner) source();
out = in.nextDouble();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextFloat;;;Argument[-1];ReturnValue;taint;manual"
float out = 0;
Scanner in = (Scanner) source();
out = in.nextFloat();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextInt;;;Argument[-1];ReturnValue;taint;manual"
int out = 0;
Scanner in = (Scanner) source();
out = in.nextInt();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextInt;;;Argument[-1];ReturnValue;taint;manual"
int out = 0;
Scanner in = (Scanner) source();
out = in.nextInt(0);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextLine;;;Argument[-1];ReturnValue;taint;manual"
String out = null;
Scanner in = (Scanner) source();
out = in.nextLine();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextLong;;;Argument[-1];ReturnValue;taint;manual"
long out = 0;
Scanner in = (Scanner) source();
out = in.nextLong();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextLong;;;Argument[-1];ReturnValue;taint;manual"
long out = 0;
Scanner in = (Scanner) source();
out = in.nextLong(0);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextShort;;;Argument[-1];ReturnValue;taint;manual"
short out = 0;
Scanner in = (Scanner) source();
out = in.nextShort();
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;nextShort;;;Argument[-1];ReturnValue;taint;manual"
short out = 0;
Scanner in = (Scanner) source();
out = in.nextShort(0);
sink(out); // $ hasTaintFlow
}
{
// "java.util;Scanner;true;reset;;;Argument[-1];ReturnValue;value;manual"
Scanner out = null;
Scanner in = (Scanner) source();
out = in.reset();
sink(out); // $ hasValueFlow
}
{
// "java.util;Scanner;true;skip;;;Argument[-1];ReturnValue;value;manual"
Scanner out = null;
Scanner in = (Scanner) source();
out = in.skip((Pattern) null);
sink(out); // $ hasValueFlow
}
{
// "java.util;Scanner;true;skip;;;Argument[-1];ReturnValue;value;manual"
Scanner out = null;
Scanner in = (Scanner) source();
out = in.skip((String) null);
sink(out); // $ hasValueFlow
}
{
// "java.util;Scanner;true;useDelimiter;;;Argument[-1];ReturnValue;value;manual"
Scanner out = null;
Scanner in = (Scanner) source();
out = in.useDelimiter((Pattern) null);
sink(out); // $ hasValueFlow
}
{
// "java.util;Scanner;true;useDelimiter;;;Argument[-1];ReturnValue;value;manual"
Scanner out = null;
Scanner in = (Scanner) source();
out = in.useDelimiter((String) null);
sink(out); // $ hasValueFlow
}
{
// "java.util;Scanner;true;useLocale;;;Argument[-1];ReturnValue;value;manual"
Scanner out = null;
Scanner in = (Scanner) source();
out = in.useLocale(null);
sink(out); // $ hasValueFlow
}
{
// "java.util;Scanner;true;useRadix;;;Argument[-1];ReturnValue;value;manual"
Scanner out = null;
Scanner in = (Scanner) source();
out = in.useRadix(0);
sink(out); // $ hasValueFlow
}
}
}

View File

@@ -0,0 +1,2 @@
import java
import TestUtilities.InlineFlowTest

View File

@@ -0,0 +1,20 @@
import java.util.List;
public class Lib<T> {
public void takesVar(T t) { }
public void takesInvar(List<T> lt) { }
public void takesUnbound(List<?> lt) { }
public void takesExtends(List<? extends T> lt) { }
public void takesSuper(List<? super T> lt) { }
public T returnsVar() { return null; }
public List<T> returnsInvar() { return null; }
public List<?> returnsUnbound() { return null; }
public List<? extends T> returnsExtends() { return null; }
public List<? super T> returnsSuper() { return null; }
public void takesArray(T[] ts) { }
public T[] returnsArray() { return null; }
}

View File

@@ -0,0 +1,12 @@
public class User {
public static void test(Lib<CharSequence> invarLib, Lib<? extends CharSequence> extendsLib, Lib<? super CharSequence> superLib, Lib<?> unboundLib) {
invarLib.takesVar(null);
extendsLib.takesVar(null);
superLib.takesVar(null);
unboundLib.takesVar(null);
}
}

View File

@@ -0,0 +1,64 @@
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsArray | CharSequence[] |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsExtends | List<? extends CharSequence> |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsInvar | List<? extends CharSequence> |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsSuper | List<?> |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsUnbound | List<?> |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | returnsVar | CharSequence |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesArray | <nulltype>[] |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesExtends | List<? extends CharSequence> |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesInvar | List<? extends CharSequence> |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesSuper | List<?> |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesUnbound | List<?> |
| Lib.class:0:0:0:0 | Lib<? extends CharSequence> | Lib.class:0:0:0:0 | takesVar | <nulltype> |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsArray | Object[] |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsExtends | List<?> |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsInvar | List<? super CharSequence> |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsSuper | List<? super CharSequence> |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsUnbound | List<?> |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | returnsVar | Object |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesArray | CharSequence[] |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesExtends | List<?> |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesInvar | List<? super CharSequence> |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesSuper | List<? super CharSequence> |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesUnbound | List<?> |
| Lib.class:0:0:0:0 | Lib<? super CharSequence> | Lib.class:0:0:0:0 | takesVar | CharSequence |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsArray | Object[] |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsExtends | List<? extends Object> |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsInvar | List<?> |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsSuper | List<?> |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsUnbound | List<?> |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | returnsVar | Object |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesArray | <nulltype>[] |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesExtends | List<? extends Object> |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesInvar | List<?> |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesSuper | List<?> |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesUnbound | List<?> |
| Lib.class:0:0:0:0 | Lib<?> | Lib.class:0:0:0:0 | takesVar | <nulltype> |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsArray | CharSequence[] |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsExtends | List<? extends CharSequence> |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsInvar | List<CharSequence> |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsSuper | List<? super CharSequence> |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsUnbound | List<?> |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | returnsVar | CharSequence |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesArray | CharSequence[] |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesExtends | List<? extends CharSequence> |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesInvar | List<CharSequence> |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesSuper | List<? super CharSequence> |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesUnbound | List<?> |
| Lib.class:0:0:0:0 | Lib<CharSequence> | Lib.class:0:0:0:0 | takesVar | CharSequence |
| Lib.java:3:14:3:16 | Lib | Lib.java:5:15:5:22 | takesVar | T |
| Lib.java:3:14:3:16 | Lib | Lib.java:6:15:6:24 | takesInvar | List<T> |
| Lib.java:3:14:3:16 | Lib | Lib.java:7:15:7:26 | takesUnbound | List<?> |
| Lib.java:3:14:3:16 | Lib | Lib.java:8:15:8:26 | takesExtends | List<? extends T> |
| Lib.java:3:14:3:16 | Lib | Lib.java:9:15:9:24 | takesSuper | List<? super T> |
| Lib.java:3:14:3:16 | Lib | Lib.java:11:12:11:21 | returnsVar | T |
| Lib.java:3:14:3:16 | Lib | Lib.java:12:18:12:29 | returnsInvar | List<T> |
| Lib.java:3:14:3:16 | Lib | Lib.java:13:18:13:31 | returnsUnbound | List<?> |
| Lib.java:3:14:3:16 | Lib | Lib.java:14:28:14:41 | returnsExtends | List<? extends T> |
| Lib.java:3:14:3:16 | Lib | Lib.java:15:26:15:37 | returnsSuper | List<? super T> |
| Lib.java:3:14:3:16 | Lib | Lib.java:17:15:17:24 | takesArray | T[] |
| Lib.java:3:14:3:16 | Lib | Lib.java:18:14:18:25 | returnsArray | T[] |
| User.java:1:14:1:17 | User | User.java:3:22:3:25 | test | Lib<? extends CharSequence> |
| User.java:1:14:1:17 | User | User.java:3:22:3:25 | test | Lib<? super CharSequence> |
| User.java:1:14:1:17 | User | User.java:3:22:3:25 | test | Lib<?> |
| User.java:1:14:1:17 | User | User.java:3:22:3:25 | test | Lib<CharSequence> |

View File

@@ -0,0 +1,7 @@
import java
Type notVoid(Type t) { result = t and not result instanceof VoidType }
from Callable c
where c.getSourceDeclaration().fromSource()
select c.getDeclaringType(), c, notVoid([c.getAParamType(), c.getReturnType()]).toString()

View File

@@ -0,0 +1,3 @@
public class Test {
}

View File

@@ -0,0 +1,2 @@
| test.xml:4:5:4:32 | attribute=value | Unexpected result: hasXmlResult= |
| test.xml:5:29:5:52 | $ hasXmlResult | Missing result:hasXmlResult= |

View File

@@ -0,0 +1,17 @@
import semmle.code.xml.XML
import TestUtilities.InlineExpectationsTest
class XmlTest extends InlineExpectationsTest {
XmlTest() { this = "XmlTest" }
override string getARelevantTag() { result = "hasXmlResult" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasXmlResult" and
exists(XMLAttribute a |
a.getLocation() = location and
element = a.toString() and
value = ""
)
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<document>
<element attribute="value">Text</element> <!-- $ hasXmlResult -->
<element attribute="value">Text</element> <!-- Missing -->
<element>Text</element> <!-- $ hasXmlResult --> <!-- Spurious -->
</document>

View File

@@ -8,6 +8,7 @@ edges
| Test.java:79:74:79:97 | getInputStream(...) : ServletInputStream | Test.java:79:52:79:98 | new InputStreamReader(...) : InputStreamReader |
| Test.java:80:31:80:32 | br : BufferedReader | Test.java:80:31:80:43 | readLine(...) : String |
| Test.java:80:31:80:43 | readLine(...) : String | Test.java:82:67:82:81 | ... + ... |
| Test.java:88:17:88:37 | getHostName(...) : String | Test.java:90:26:90:29 | temp |
nodes
| Test.java:19:18:19:38 | getHostName(...) : String | semmle.label | getHostName(...) : String |
| Test.java:24:20:24:23 | temp | semmle.label | temp |
@@ -20,6 +21,8 @@ nodes
| Test.java:80:31:80:32 | br : BufferedReader | semmle.label | br : BufferedReader |
| Test.java:80:31:80:43 | readLine(...) : String | semmle.label | readLine(...) : String |
| Test.java:82:67:82:81 | ... + ... | semmle.label | ... + ... |
| Test.java:88:17:88:37 | getHostName(...) : String | semmle.label | getHostName(...) : String |
| Test.java:90:26:90:29 | temp | semmle.label | temp |
subpaths
#select
| Test.java:24:11:24:24 | new File(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:24:20:24:23 | temp | $@ flows to here and is used in a path. | Test.java:19:18:19:38 | getHostName(...) | User-provided value |
@@ -27,3 +30,4 @@ subpaths
| Test.java:30:11:30:48 | getPath(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:30:44:30:47 | temp | $@ flows to here and is used in a path. | Test.java:19:18:19:38 | getHostName(...) | User-provided value |
| Test.java:34:12:34:25 | new File(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:34:21:34:24 | temp | $@ flows to here and is used in a path. | Test.java:19:18:19:38 | getHostName(...) | User-provided value |
| Test.java:82:52:82:88 | new FileWriter(...) | Test.java:79:74:79:97 | getInputStream(...) : ServletInputStream | Test.java:82:67:82:81 | ... + ... | $@ flows to here and is used in a path. | Test.java:79:74:79:97 | getInputStream(...) | User-provided value |
| Test.java:90:26:90:29 | temp | Test.java:88:17:88:37 | getHostName(...) : String | Test.java:90:26:90:29 | temp | $@ flows to here and is used in a path. | Test.java:88:17:88:37 | getHostName(...) | User-provided value |

View File

@@ -2,7 +2,6 @@
// http://cwe.mitre.org/data/definitions/22.html
package test.cwe22.semmle.tests;
import javax.servlet.http.*;
import javax.servlet.ServletException;
@@ -12,6 +11,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.FileSystems;
import org.apache.commons.io.output.LockableFileWriter;
class Test {
void doGet1(InetAddress address)
@@ -19,13 +19,13 @@ class Test {
String temp = address.getHostName();
File file;
Path path;
// BAD: construct a file path with user input
file = new File(temp);
// BAD: construct a path with user input
path = Paths.get(temp);
// BAD: construct a path with user input
path = FileSystems.getDefault().getPath(temp);
@@ -34,7 +34,7 @@ class Test {
file = new File(temp);
}
}
void doGet2(InetAddress address)
throws IOException {
String temp = address.getHostName();
@@ -44,7 +44,7 @@ class Test {
if(isSafe(temp))
file = new File(temp);
}
void doGet3(InetAddress address)
throws IOException {
String temp = address.getHostName();
@@ -66,7 +66,7 @@ class Test {
return false;
return true;
}
boolean isSortOfSafe(String pathSpec) {
// no file separators
if (pathSpec.contains(File.separator))
@@ -82,4 +82,11 @@ class Test {
BufferedWriter bw = new BufferedWriter(new FileWriter("dir/"+filename, true));
}
}
void doGet4(InetAddress address)
throws IOException {
String temp = address.getHostName();
// BAD: open a file based on user input, using a MaD-documented API
new LockableFileWriter(temp);
}
}

View File

@@ -1 +1 @@
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/apache-commons-io-2.6

View File

@@ -0,0 +1,54 @@
import android.webkit.WebViewClient;
import android.webkit.WebView;
import android.webkit.SslErrorHandler;
import android.net.http.SslError;
import android.net.http.SslCertificate;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.app.Activity;
class Test {
class A extends WebViewClient {
public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { // $hasResult
handler.proceed();
}
}
interface Validator {
boolean isValid(SslCertificate cert);
}
class B extends WebViewClient {
Validator v;
public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) {
if (this.v.isValid(error.getCertificate())) {
handler.proceed();
}
else {
handler.cancel();
}
}
}
class C extends WebViewClient {
Activity activity;
public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) {
new AlertDialog.Builder(activity).
setTitle("SSL error").
setMessage("SSL error. Connect anyway?").
setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
handler.proceed();
}
}).setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
handler.cancel();
}
}).show();
}
}
}

View File

@@ -0,0 +1 @@
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0

View File

@@ -0,0 +1,19 @@
import java
import semmle.code.java.security.AndroidWebViewCertificateValidationQuery
import TestUtilities.InlineExpectationsTest
class WebViewTest extends InlineExpectationsTest {
WebViewTest() { this = "WebViewTest" }
override string getARelevantTag() { result = "hasResult" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(OnReceivedSslErrorMethod m |
trustsAllCerts(m) and
location = m.getLocation() and
element = m.toString() and
tag = "hasResult" and
value = ""
)
}
}

View File

@@ -0,0 +1,11 @@
import android.app.Activity
import android.content.Context
import android.content.SharedPreferences
class CleartextStorageSharedPrefsTestKt : Activity() {
fun testSetSharedPrefs1(context: Context, name: String, password: String) {
val sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE);
sharedPrefs.edit().putString("name", name).apply(); // Safe
sharedPrefs.edit().putString("password", password).apply(); // $ hasCleartextStorageSharedPrefs
}
}

View File

@@ -1 +1,2 @@
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/google-android-9.0.0
// codeql-extractor-kotlin-options: ${testdir}/../../../stubs/google-android-9.0.0

View File

@@ -44,6 +44,7 @@
<activity android:name=".UnsafeActivity3" android:exported="true" />
<activity android:name=".UnsafeActivity4" android:exported="true" />
<activity android:name=".UnsafeActivityKt" android:exported="true" />
<receiver android:name=".UnsafeAndroidBroadcastReceiver" android:exported="true" />
</application>

View File

@@ -0,0 +1,20 @@
package com.example.app
import android.app.Activity
import android.os.Bundle
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
class UnsafeActivityKt : Activity() {
override fun onCreate(savedInstanceState : Bundle) {
val wv = findViewById<WebView>(-1)
// Implicit not-nulls happening here
wv.settings.setJavaScriptEnabled(true)
wv.settings.setAllowFileAccessFromFileURLs(true)
val thisUrl : String = intent.extras.getString("url")
wv.loadUrl(thisUrl) // $ hasUnsafeAndroidAccess
}
}

View File

@@ -1 +1,2 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/android
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/google-android-9.0.0
//codeql-extractor-kotlin-options: ${testdir}/../../../stubs/google-android-9.0.0

View File

@@ -0,0 +1,7 @@
package org.apache.commons.io.output;
public class LockableFileWriter {
public LockableFileWriter(String filename) { }
}

View File

@@ -0,0 +1,132 @@
// Generated automatically from android.app.ActionBar for testing purposes
package android.app;
import android.app.FragmentTransaction;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SpinnerAdapter;
abstract public class ActionBar
{
abstract static public class Tab
{
public Tab(){}
public abstract ActionBar.Tab setContentDescription(CharSequence p0);
public abstract ActionBar.Tab setContentDescription(int p0);
public abstract ActionBar.Tab setCustomView(View p0);
public abstract ActionBar.Tab setCustomView(int p0);
public abstract ActionBar.Tab setIcon(Drawable p0);
public abstract ActionBar.Tab setIcon(int p0);
public abstract ActionBar.Tab setTabListener(ActionBar.TabListener p0);
public abstract ActionBar.Tab setTag(Object p0);
public abstract ActionBar.Tab setText(CharSequence p0);
public abstract ActionBar.Tab setText(int p0);
public abstract CharSequence getContentDescription();
public abstract CharSequence getText();
public abstract Drawable getIcon();
public abstract Object getTag();
public abstract View getCustomView();
public abstract int getPosition();
public abstract void select();
public static int INVALID_POSITION = 0;
}
public ActionBar(){}
public Context getThemedContext(){ return null; }
public abstract ActionBar.Tab getSelectedTab();
public abstract ActionBar.Tab getTabAt(int p0);
public abstract ActionBar.Tab newTab();
public abstract CharSequence getSubtitle();
public abstract CharSequence getTitle();
public abstract View getCustomView();
public abstract boolean isShowing();
public abstract int getDisplayOptions();
public abstract int getHeight();
public abstract int getNavigationItemCount();
public abstract int getNavigationMode();
public abstract int getSelectedNavigationIndex();
public abstract int getTabCount();
public abstract void addOnMenuVisibilityListener(ActionBar.OnMenuVisibilityListener p0);
public abstract void addTab(ActionBar.Tab p0);
public abstract void addTab(ActionBar.Tab p0, boolean p1);
public abstract void addTab(ActionBar.Tab p0, int p1);
public abstract void addTab(ActionBar.Tab p0, int p1, boolean p2);
public abstract void hide();
public abstract void removeAllTabs();
public abstract void removeOnMenuVisibilityListener(ActionBar.OnMenuVisibilityListener p0);
public abstract void removeTab(ActionBar.Tab p0);
public abstract void removeTabAt(int p0);
public abstract void selectTab(ActionBar.Tab p0);
public abstract void setBackgroundDrawable(Drawable p0);
public abstract void setCustomView(View p0);
public abstract void setCustomView(View p0, ActionBar.LayoutParams p1);
public abstract void setCustomView(int p0);
public abstract void setDisplayHomeAsUpEnabled(boolean p0);
public abstract void setDisplayOptions(int p0);
public abstract void setDisplayOptions(int p0, int p1);
public abstract void setDisplayShowCustomEnabled(boolean p0);
public abstract void setDisplayShowHomeEnabled(boolean p0);
public abstract void setDisplayShowTitleEnabled(boolean p0);
public abstract void setDisplayUseLogoEnabled(boolean p0);
public abstract void setIcon(Drawable p0);
public abstract void setIcon(int p0);
public abstract void setListNavigationCallbacks(SpinnerAdapter p0, ActionBar.OnNavigationListener p1);
public abstract void setLogo(Drawable p0);
public abstract void setLogo(int p0);
public abstract void setNavigationMode(int p0);
public abstract void setSelectedNavigationItem(int p0);
public abstract void setSubtitle(CharSequence p0);
public abstract void setSubtitle(int p0);
public abstract void setTitle(CharSequence p0);
public abstract void setTitle(int p0);
public abstract void show();
public boolean isHideOnContentScrollEnabled(){ return false; }
public float getElevation(){ return 0; }
public int getHideOffset(){ return 0; }
public static int DISPLAY_HOME_AS_UP = 0;
public static int DISPLAY_SHOW_CUSTOM = 0;
public static int DISPLAY_SHOW_HOME = 0;
public static int DISPLAY_SHOW_TITLE = 0;
public static int DISPLAY_USE_LOGO = 0;
public static int NAVIGATION_MODE_LIST = 0;
public static int NAVIGATION_MODE_STANDARD = 0;
public static int NAVIGATION_MODE_TABS = 0;
public void setElevation(float p0){}
public void setHideOffset(int p0){}
public void setHideOnContentScrollEnabled(boolean p0){}
public void setHomeActionContentDescription(CharSequence p0){}
public void setHomeActionContentDescription(int p0){}
public void setHomeAsUpIndicator(Drawable p0){}
public void setHomeAsUpIndicator(int p0){}
public void setHomeButtonEnabled(boolean p0){}
public void setSplitBackgroundDrawable(Drawable p0){}
public void setStackedBackgroundDrawable(Drawable p0){}
static public class LayoutParams extends ViewGroup.MarginLayoutParams
{
protected LayoutParams() {}
public LayoutParams(ActionBar.LayoutParams p0){}
public LayoutParams(Context p0, AttributeSet p1){}
public LayoutParams(ViewGroup.LayoutParams p0){}
public LayoutParams(int p0){}
public LayoutParams(int p0, int p1){}
public LayoutParams(int p0, int p1, int p2){}
public int gravity = 0;
}
static public interface OnMenuVisibilityListener
{
void onMenuVisibilityChanged(boolean p0);
}
static public interface OnNavigationListener
{
boolean onNavigationItemSelected(int p0, long p1);
}
static public interface TabListener
{
void onTabReselected(ActionBar.Tab p0, FragmentTransaction p1);
void onTabSelected(ActionBar.Tab p0, FragmentTransaction p1);
void onTabUnselected(ActionBar.Tab p0, FragmentTransaction p1);
}
}

View File

@@ -0,0 +1,215 @@
// Generated automatically from android.app.ActivityManager for testing purposes
package android.app;
import android.app.Activity;
import android.app.ApplicationExitInfo;
import android.app.PendingIntent;
import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ConfigurationInfo;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Debug;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Size;
import java.io.FileDescriptor;
import java.util.List;
public class ActivityManager
{
public ConfigurationInfo getDeviceConfigurationInfo(){ return null; }
public Debug.MemoryInfo[] getProcessMemoryInfo(int[] p0){ return null; }
public List<ActivityManager.AppTask> getAppTasks(){ return null; }
public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState(){ return null; }
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int p0, int p1){ return null; }
public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses(){ return null; }
public List<ActivityManager.RunningServiceInfo> getRunningServices(int p0){ return null; }
public List<ActivityManager.RunningTaskInfo> getRunningTasks(int p0){ return null; }
public List<ApplicationExitInfo> getHistoricalProcessExitReasons(String p0, int p1, int p2){ return null; }
public PendingIntent getRunningServiceControlPanel(ComponentName p0){ return null; }
public Size getAppTaskThumbnailSize(){ return null; }
public boolean clearApplicationUserData(){ return false; }
public boolean isActivityStartAllowedOnDisplay(Context p0, int p1, Intent p2){ return false; }
public boolean isBackgroundRestricted(){ return false; }
public boolean isInLockTaskMode(){ return false; }
public boolean isLowRamDevice(){ return false; }
public int addAppTask(Activity p0, Intent p1, ActivityManager.TaskDescription p2, Bitmap p3){ return 0; }
public int getLargeMemoryClass(){ return 0; }
public int getLauncherLargeIconDensity(){ return 0; }
public int getLauncherLargeIconSize(){ return 0; }
public int getLockTaskModeState(){ return 0; }
public int getMemoryClass(){ return 0; }
public static String ACTION_REPORT_HEAP_LIMIT = null;
public static String META_HOME_ALTERNATE = null;
public static boolean isLowMemoryKillReportSupported(){ return false; }
public static boolean isRunningInTestHarness(){ return false; }
public static boolean isRunningInUserTestHarness(){ return false; }
public static boolean isUserAMonkey(){ return false; }
public static int LOCK_TASK_MODE_LOCKED = 0;
public static int LOCK_TASK_MODE_NONE = 0;
public static int LOCK_TASK_MODE_PINNED = 0;
public static int MOVE_TASK_NO_USER_ACTION = 0;
public static int MOVE_TASK_WITH_HOME = 0;
public static int RECENT_IGNORE_UNAVAILABLE = 0;
public static int RECENT_WITH_EXCLUDED = 0;
public static void getMyMemoryState(ActivityManager.RunningAppProcessInfo p0){}
public static void setVrThread(int p0){}
public void appNotResponding(String p0){}
public void clearWatchHeapLimit(){}
public void dumpPackageState(FileDescriptor p0, String p1){}
public void getMemoryInfo(ActivityManager.MemoryInfo p0){}
public void killBackgroundProcesses(String p0){}
public void moveTaskToFront(int p0, int p1){}
public void moveTaskToFront(int p0, int p1, Bundle p2){}
public void restartPackage(String p0){}
public void setProcessStateSummary(byte[] p0){}
public void setWatchHeapLimit(long p0){}
static public class AppTask
{
public ActivityManager.RecentTaskInfo getTaskInfo(){ return null; }
public void finishAndRemoveTask(){}
public void moveToFront(){}
public void setExcludeFromRecents(boolean p0){}
public void startActivity(Context p0, Intent p1, Bundle p2){}
}
static public class MemoryInfo implements Parcelable
{
public MemoryInfo(){}
public boolean lowMemory = false;
public int describeContents(){ return 0; }
public long availMem = 0;
public long threshold = 0;
public long totalMem = 0;
public static Parcelable.Creator<ActivityManager.MemoryInfo> CREATOR = null;
public void readFromParcel(Parcel p0){}
public void writeToParcel(Parcel p0, int p1){}
}
static public class ProcessErrorStateInfo implements Parcelable
{
public ProcessErrorStateInfo(){}
public String longMsg = null;
public String processName = null;
public String shortMsg = null;
public String stackTrace = null;
public String tag = null;
public byte[] crashData = null;
public int condition = 0;
public int describeContents(){ return 0; }
public int pid = 0;
public int uid = 0;
public static Parcelable.Creator<ActivityManager.ProcessErrorStateInfo> CREATOR = null;
public static int CRASHED = 0;
public static int NOT_RESPONDING = 0;
public static int NO_ERROR = 0;
public void readFromParcel(Parcel p0){}
public void writeToParcel(Parcel p0, int p1){}
}
static public class RecentTaskInfo extends TaskInfo implements Parcelable
{
public CharSequence description = null;
public RecentTaskInfo(){}
public int affiliatedTaskId = 0;
public int describeContents(){ return 0; }
public int id = 0;
public int persistentId = 0;
public static Parcelable.Creator<ActivityManager.RecentTaskInfo> CREATOR = null;
public void readFromParcel(Parcel p0){}
public void writeToParcel(Parcel p0, int p1){}
}
static public class RunningAppProcessInfo implements Parcelable
{
public ComponentName importanceReasonComponent = null;
public RunningAppProcessInfo(){}
public RunningAppProcessInfo(String p0, int p1, String[] p2){}
public String processName = null;
public String[] pkgList = null;
public int describeContents(){ return 0; }
public int importance = 0;
public int importanceReasonCode = 0;
public int importanceReasonPid = 0;
public int lastTrimLevel = 0;
public int lru = 0;
public int pid = 0;
public int uid = 0;
public static Parcelable.Creator<ActivityManager.RunningAppProcessInfo> CREATOR = null;
public static int IMPORTANCE_BACKGROUND = 0;
public static int IMPORTANCE_CACHED = 0;
public static int IMPORTANCE_CANT_SAVE_STATE = 0;
public static int IMPORTANCE_EMPTY = 0;
public static int IMPORTANCE_FOREGROUND = 0;
public static int IMPORTANCE_FOREGROUND_SERVICE = 0;
public static int IMPORTANCE_GONE = 0;
public static int IMPORTANCE_PERCEPTIBLE = 0;
public static int IMPORTANCE_PERCEPTIBLE_PRE_26 = 0;
public static int IMPORTANCE_SERVICE = 0;
public static int IMPORTANCE_TOP_SLEEPING = 0;
public static int IMPORTANCE_TOP_SLEEPING_PRE_28 = 0;
public static int IMPORTANCE_VISIBLE = 0;
public static int REASON_PROVIDER_IN_USE = 0;
public static int REASON_SERVICE_IN_USE = 0;
public static int REASON_UNKNOWN = 0;
public void readFromParcel(Parcel p0){}
public void writeToParcel(Parcel p0, int p1){}
}
static public class RunningServiceInfo implements Parcelable
{
public ComponentName service = null;
public RunningServiceInfo(){}
public String clientPackage = null;
public String process = null;
public boolean foreground = false;
public boolean started = false;
public int clientCount = 0;
public int clientLabel = 0;
public int crashCount = 0;
public int describeContents(){ return 0; }
public int flags = 0;
public int pid = 0;
public int uid = 0;
public long activeSince = 0;
public long lastActivityTime = 0;
public long restarting = 0;
public static Parcelable.Creator<ActivityManager.RunningServiceInfo> CREATOR = null;
public static int FLAG_FOREGROUND = 0;
public static int FLAG_PERSISTENT_PROCESS = 0;
public static int FLAG_STARTED = 0;
public static int FLAG_SYSTEM_PROCESS = 0;
public void readFromParcel(Parcel p0){}
public void writeToParcel(Parcel p0, int p1){}
}
static public class RunningTaskInfo extends TaskInfo implements Parcelable
{
public Bitmap thumbnail = null;
public CharSequence description = null;
public RunningTaskInfo(){}
public int describeContents(){ return 0; }
public int id = 0;
public int numRunning = 0;
public static Parcelable.Creator<ActivityManager.RunningTaskInfo> CREATOR = null;
public void readFromParcel(Parcel p0){}
public void writeToParcel(Parcel p0, int p1){}
}
static public class TaskDescription implements Parcelable
{
public Bitmap getIcon(){ return null; }
public String getLabel(){ return null; }
public String toString(){ return null; }
public TaskDescription(){}
public TaskDescription(ActivityManager.TaskDescription p0){}
public TaskDescription(String p0){}
public TaskDescription(String p0, Bitmap p1){}
public TaskDescription(String p0, Bitmap p1, int p2){}
public TaskDescription(String p0, int p1){}
public TaskDescription(String p0, int p1, int p2){}
public boolean equals(Object p0){ return false; }
public int describeContents(){ return 0; }
public int getPrimaryColor(){ return 0; }
public static Parcelable.Creator<ActivityManager.TaskDescription> CREATOR = null;
public void readFromParcel(Parcel p0){}
public void writeToParcel(Parcel p0, int p1){}
}
}

View File

@@ -0,0 +1,95 @@
// Generated automatically from android.app.AlertDialog for testing purposes
package android.app;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
public class AlertDialog extends Dialog implements DialogInterface
{
protected AlertDialog() {}
protected AlertDialog(Context p0){}
protected AlertDialog(Context p0, boolean p1, DialogInterface.OnCancelListener p2){}
protected AlertDialog(Context p0, int p1){}
protected void onCreate(Bundle p0){}
public Button getButton(int p0){ return null; }
public ListView getListView(){ return null; }
public boolean onKeyDown(int p0, KeyEvent p1){ return false; }
public boolean onKeyUp(int p0, KeyEvent p1){ return false; }
public static int THEME_DEVICE_DEFAULT_DARK = 0;
public static int THEME_DEVICE_DEFAULT_LIGHT = 0;
public static int THEME_HOLO_DARK = 0;
public static int THEME_HOLO_LIGHT = 0;
public static int THEME_TRADITIONAL = 0;
public void setButton(CharSequence p0, DialogInterface.OnClickListener p1){}
public void setButton(CharSequence p0, Message p1){}
public void setButton(int p0, CharSequence p1, DialogInterface.OnClickListener p2){}
public void setButton(int p0, CharSequence p1, Message p2){}
public void setButton2(CharSequence p0, DialogInterface.OnClickListener p1){}
public void setButton2(CharSequence p0, Message p1){}
public void setButton3(CharSequence p0, DialogInterface.OnClickListener p1){}
public void setButton3(CharSequence p0, Message p1){}
public void setCustomTitle(View p0){}
public void setIcon(Drawable p0){}
public void setIcon(int p0){}
public void setIconAttribute(int p0){}
public void setInverseBackgroundForced(boolean p0){}
public void setMessage(CharSequence p0){}
public void setTitle(CharSequence p0){}
public void setView(View p0){}
public void setView(View p0, int p1, int p2, int p3, int p4){}
static public class Builder
{
protected Builder() {}
public AlertDialog create(){ return null; }
public AlertDialog show(){ return null; }
public AlertDialog.Builder setAdapter(ListAdapter p0, DialogInterface.OnClickListener p1){ return null; }
public AlertDialog.Builder setCancelable(boolean p0){ return null; }
public AlertDialog.Builder setCursor(Cursor p0, DialogInterface.OnClickListener p1, String p2){ return null; }
public AlertDialog.Builder setCustomTitle(View p0){ return null; }
public AlertDialog.Builder setIcon(Drawable p0){ return null; }
public AlertDialog.Builder setIcon(int p0){ return null; }
public AlertDialog.Builder setIconAttribute(int p0){ return null; }
public AlertDialog.Builder setInverseBackgroundForced(boolean p0){ return null; }
public AlertDialog.Builder setItems(CharSequence[] p0, DialogInterface.OnClickListener p1){ return null; }
public AlertDialog.Builder setItems(int p0, DialogInterface.OnClickListener p1){ return null; }
public AlertDialog.Builder setMessage(CharSequence p0){ return null; }
public AlertDialog.Builder setMessage(int p0){ return null; }
public AlertDialog.Builder setMultiChoiceItems(CharSequence[] p0, boolean[] p1, DialogInterface.OnMultiChoiceClickListener p2){ return null; }
public AlertDialog.Builder setMultiChoiceItems(Cursor p0, String p1, String p2, DialogInterface.OnMultiChoiceClickListener p3){ return null; }
public AlertDialog.Builder setMultiChoiceItems(int p0, boolean[] p1, DialogInterface.OnMultiChoiceClickListener p2){ return null; }
public AlertDialog.Builder setNegativeButton(CharSequence p0, DialogInterface.OnClickListener p1){ return null; }
public AlertDialog.Builder setNegativeButton(int p0, DialogInterface.OnClickListener p1){ return null; }
public AlertDialog.Builder setNeutralButton(CharSequence p0, DialogInterface.OnClickListener p1){ return null; }
public AlertDialog.Builder setNeutralButton(int p0, DialogInterface.OnClickListener p1){ return null; }
public AlertDialog.Builder setOnCancelListener(DialogInterface.OnCancelListener p0){ return null; }
public AlertDialog.Builder setOnDismissListener(DialogInterface.OnDismissListener p0){ return null; }
public AlertDialog.Builder setOnItemSelectedListener(AdapterView.OnItemSelectedListener p0){ return null; }
public AlertDialog.Builder setOnKeyListener(DialogInterface.OnKeyListener p0){ return null; }
public AlertDialog.Builder setPositiveButton(CharSequence p0, DialogInterface.OnClickListener p1){ return null; }
public AlertDialog.Builder setPositiveButton(int p0, DialogInterface.OnClickListener p1){ return null; }
public AlertDialog.Builder setSingleChoiceItems(CharSequence[] p0, int p1, DialogInterface.OnClickListener p2){ return null; }
public AlertDialog.Builder setSingleChoiceItems(Cursor p0, int p1, String p2, DialogInterface.OnClickListener p3){ return null; }
public AlertDialog.Builder setSingleChoiceItems(ListAdapter p0, int p1, DialogInterface.OnClickListener p2){ return null; }
public AlertDialog.Builder setSingleChoiceItems(int p0, int p1, DialogInterface.OnClickListener p2){ return null; }
public AlertDialog.Builder setTitle(CharSequence p0){ return null; }
public AlertDialog.Builder setTitle(int p0){ return null; }
public AlertDialog.Builder setView(View p0){ return null; }
public AlertDialog.Builder setView(int p0){ return null; }
public Builder(Context p0){}
public Builder(Context p0, int p1){}
public Context getContext(){ return null; }
}
}

View File

@@ -0,0 +1,55 @@
// Generated automatically from android.app.Application for testing purposes
package android.app;
import android.app.Activity;
import android.content.ComponentCallbacks2;
import android.content.ComponentCallbacks;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.os.Bundle;
public class Application extends ContextWrapper implements ComponentCallbacks2
{
public Application(){}
public static String getProcessName(){ return null; }
public void onConfigurationChanged(Configuration p0){}
public void onCreate(){}
public void onLowMemory(){}
public void onTerminate(){}
public void onTrimMemory(int p0){}
public void registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks p0){}
public void registerComponentCallbacks(ComponentCallbacks p0){}
public void registerOnProvideAssistDataListener(Application.OnProvideAssistDataListener p0){}
public void unregisterActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks p0){}
public void unregisterComponentCallbacks(ComponentCallbacks p0){}
public void unregisterOnProvideAssistDataListener(Application.OnProvideAssistDataListener p0){}
static public interface ActivityLifecycleCallbacks
{
default void onActivityPostCreated(Activity p0, Bundle p1){}
default void onActivityPostDestroyed(Activity p0){}
default void onActivityPostPaused(Activity p0){}
default void onActivityPostResumed(Activity p0){}
default void onActivityPostSaveInstanceState(Activity p0, Bundle p1){}
default void onActivityPostStarted(Activity p0){}
default void onActivityPostStopped(Activity p0){}
default void onActivityPreCreated(Activity p0, Bundle p1){}
default void onActivityPreDestroyed(Activity p0){}
default void onActivityPrePaused(Activity p0){}
default void onActivityPreResumed(Activity p0){}
default void onActivityPreSaveInstanceState(Activity p0, Bundle p1){}
default void onActivityPreStarted(Activity p0){}
default void onActivityPreStopped(Activity p0){}
void onActivityCreated(Activity p0, Bundle p1);
void onActivityDestroyed(Activity p0);
void onActivityPaused(Activity p0);
void onActivityResumed(Activity p0);
void onActivitySaveInstanceState(Activity p0, Bundle p1);
void onActivityStarted(Activity p0);
void onActivityStopped(Activity p0);
}
static public interface OnProvideAssistDataListener
{
void onProvideAssistData(Activity p0, Bundle p1);
}
}

Some files were not shown because too many files have changed in this diff Show More