mirror of
https://github.com/github/codeql.git
synced 2026-04-27 17:55:19 +02:00
Merge branch 'main' into repeatedWord
This commit is contained in:
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
Added additional flow sources for uses of external storage on Android.
|
||||
@@ -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.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
Added `Modifier.isInline()`.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
12
java/ql/lib/change-notes/released/0.3.1.md
Normal file
12
java/ql/lib/change-notes/released/0.3.1.md
Normal 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.
|
||||
10
java/ql/lib/change-notes/released/0.3.2.md
Normal file
10
java/ql/lib/change-notes/released/0.3.2.md
Normal 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`.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.3.0
|
||||
lastReleaseVersion: 0.3.2
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
}
|
||||
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() + "'."
|
||||
|
||||
@@ -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() + "'."
|
||||
|
||||
@@ -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() +
|
||||
"."
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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."
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* Contextual queries and the query libraries they depend on have been moved to the `codeql/java-all` package.
|
||||
4
java/ql/src/change-notes/2022-08-03-tainted-path-mad.md
Normal file
4
java/ql/src/change-notes/2022-08-03-tainted-path-mad.md
Normal 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.
|
||||
11
java/ql/src/change-notes/released/0.3.0.md
Normal file
11
java/ql/src/change-notes/released/0.3.0.md
Normal 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.
|
||||
1
java/ql/src/change-notes/released/0.3.1.md
Normal file
1
java/ql/src/change-notes/released/0.3.1.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.3.1
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.2.0
|
||||
lastReleaseVersion: 0.3.1
|
||||
|
||||
@@ -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);
|
||||
@@ -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>
|
||||
@@ -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."
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-queries
|
||||
version: 0.2.1-dev
|
||||
version: 0.3.2-dev
|
||||
groups:
|
||||
- java
|
||||
- queries
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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(...) |
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import java
|
||||
|
||||
from MethodAccess ma
|
||||
select ma
|
||||
@@ -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 |
|
||||
|
||||
@@ -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(...)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
public class Test {
|
||||
|
||||
public char f(String s) { return s.charAt(0); }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
| Test.java:3:36:3:46 | charAt(...) |
|
||||
| test.kt:2:20:2:23 | charAt(...) |
|
||||
2
java/ql/test/kotlin/library-tests/string-charat/test.kt
Normal file
2
java/ql/test/kotlin/library-tests/string-charat/test.kt
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
fun f(x: String) = x[0]
|
||||
4
java/ql/test/kotlin/library-tests/string-charat/test.ql
Normal file
4
java/ql/test/kotlin/library-tests/string-charat/test.ql
Normal file
@@ -0,0 +1,4 @@
|
||||
import java
|
||||
|
||||
from MethodAccess ma
|
||||
select ma
|
||||
@@ -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(...) |
|
||||
36
java/ql/test/kotlin/library-tests/super-method-calls/test.kt
Normal file
36
java/ql/test/kotlin/library-tests/super-method-calls/test.kt
Normal 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()))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
18
java/ql/test/kotlin/library-tests/super-method-calls/test.ql
Normal file
18
java/ql/test/kotlin/library-tests/super-method-calls/test.ql
Normal 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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,2 @@
|
||||
import java
|
||||
import TestUtilities.InlineFlowTest
|
||||
|
||||
class AsyncTaskTest extends InlineFlowTest {
|
||||
override TaintTracking::Configuration getTaintFlowConfig() { none() }
|
||||
}
|
||||
|
||||
328
java/ql/test/library-tests/scanner/Test.java
Normal file
328
java/ql/test/library-tests/scanner/Test.java
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
0
java/ql/test/library-tests/scanner/test.expected
Normal file
0
java/ql/test/library-tests/scanner/test.expected
Normal file
2
java/ql/test/library-tests/scanner/test.ql
Normal file
2
java/ql/test/library-tests/scanner/test.ql
Normal file
@@ -0,0 +1,2 @@
|
||||
import java
|
||||
import TestUtilities.InlineFlowTest
|
||||
20
java/ql/test/library-tests/wildcard-substitution/Lib.java
Normal file
20
java/ql/test/library-tests/wildcard-substitution/Lib.java
Normal 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; }
|
||||
|
||||
}
|
||||
12
java/ql/test/library-tests/wildcard-substitution/User.java
Normal file
12
java/ql/test/library-tests/wildcard-substitution/User.java
Normal 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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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> |
|
||||
7
java/ql/test/library-tests/wildcard-substitution/test.ql
Normal file
7
java/ql/test/library-tests/wildcard-substitution/test.ql
Normal 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()
|
||||
3
java/ql/test/library-tests/xml/Test.java
Normal file
3
java/ql/test/library-tests/xml/Test.java
Normal file
@@ -0,0 +1,3 @@
|
||||
public class Test {
|
||||
|
||||
}
|
||||
2
java/ql/test/library-tests/xml/XMLTest.expected
Normal file
2
java/ql/test/library-tests/xml/XMLTest.expected
Normal 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= |
|
||||
17
java/ql/test/library-tests/xml/XMLTest.ql
Normal file
17
java/ql/test/library-tests/xml/XMLTest.ql
Normal 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 = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
6
java/ql/test/library-tests/xml/test.xml
Normal file
6
java/ql/test/library-tests/xml/test.xml
Normal 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>
|
||||
@@ -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 |
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0
|
||||
@@ -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 = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
7
java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/output/LockableFileWriter.java
generated
Normal file
7
java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/output/LockableFileWriter.java
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
package org.apache.commons.io.output;
|
||||
|
||||
public class LockableFileWriter {
|
||||
|
||||
public LockableFileWriter(String filename) { }
|
||||
|
||||
}
|
||||
132
java/ql/test/stubs/google-android-9.0.0/android/app/ActionBar.java
generated
Normal file
132
java/ql/test/stubs/google-android-9.0.0/android/app/ActionBar.java
generated
Normal 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);
|
||||
}
|
||||
}
|
||||
215
java/ql/test/stubs/google-android-9.0.0/android/app/ActivityManager.java
generated
Normal file
215
java/ql/test/stubs/google-android-9.0.0/android/app/ActivityManager.java
generated
Normal 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){}
|
||||
}
|
||||
}
|
||||
95
java/ql/test/stubs/google-android-9.0.0/android/app/AlertDialog.java
generated
Normal file
95
java/ql/test/stubs/google-android-9.0.0/android/app/AlertDialog.java
generated
Normal 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; }
|
||||
}
|
||||
}
|
||||
55
java/ql/test/stubs/google-android-9.0.0/android/app/Application.java
generated
Normal file
55
java/ql/test/stubs/google-android-9.0.0/android/app/Application.java
generated
Normal 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
Reference in New Issue
Block a user