mirror of
https://github.com/github/codeql.git
synced 2025-12-24 12:46:34 +01:00
Kotlin: Add support for more type operators
This commit is contained in:
@@ -1475,8 +1475,28 @@ class X {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun extractTypeAccess(t: IrType, parent: Label<out DbExprparent>, idx: Int, elementForLocation: IrElement) {
|
||||||
|
// TODO: elementForLocation allows us to give some sort of
|
||||||
|
// location, but a proper location for the type access will
|
||||||
|
// require upstream changes
|
||||||
|
val type = useType(t)
|
||||||
|
val id = tw.getFreshIdLabel<DbUnannotatedtypeaccess>()
|
||||||
|
tw.writeExprs_unannotatedtypeaccess(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
|
||||||
|
val locId = tw.getLocation(elementForLocation)
|
||||||
|
tw.writeHasLocation(id, locId)
|
||||||
|
}
|
||||||
|
|
||||||
fun extractTypeOperatorCall(e: IrTypeOperatorCall, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int) {
|
fun extractTypeOperatorCall(e: IrTypeOperatorCall, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int) {
|
||||||
when(e.operator) {
|
when(e.operator) {
|
||||||
|
IrTypeOperator.CAST -> {
|
||||||
|
val id = tw.getFreshIdLabel<DbCastexpr>()
|
||||||
|
val locId = tw.getLocation(e)
|
||||||
|
val type = useType(e.type)
|
||||||
|
tw.writeExprs_castexpr(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
|
||||||
|
tw.writeHasLocation(id, locId)
|
||||||
|
extractTypeAccess(e.typeOperand, id, 0, e)
|
||||||
|
extractExpressionExpr(e.argument, callable, id, 1)
|
||||||
|
}
|
||||||
IrTypeOperator.INSTANCEOF -> {
|
IrTypeOperator.INSTANCEOF -> {
|
||||||
val id = tw.getFreshIdLabel<DbInstanceofexpr>()
|
val id = tw.getFreshIdLabel<DbInstanceofexpr>()
|
||||||
val locId = tw.getLocation(e)
|
val locId = tw.getLocation(e)
|
||||||
@@ -1484,10 +1504,16 @@ class X {
|
|||||||
tw.writeExprs_instanceofexpr(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
|
tw.writeExprs_instanceofexpr(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
|
||||||
tw.writeHasLocation(id, locId)
|
tw.writeHasLocation(id, locId)
|
||||||
extractExpressionExpr(e.argument, callable, id, 0)
|
extractExpressionExpr(e.argument, callable, id, 0)
|
||||||
val typeArg = useType(e.typeOperand)
|
extractTypeAccess(e.typeOperand, id, 1, e)
|
||||||
val typeAccessId = tw.getFreshIdLabel<DbUnannotatedtypeaccess>()
|
}
|
||||||
tw.writeExprs_unannotatedtypeaccess(typeAccessId, typeArg.javaResult.id, typeArg.kotlinResult.id, id, 1)
|
IrTypeOperator.NOT_INSTANCEOF -> {
|
||||||
// TODO: Type access location
|
val id = tw.getFreshIdLabel<DbNotinstanceofexpr>()
|
||||||
|
val locId = tw.getLocation(e)
|
||||||
|
val type = useType(e.type)
|
||||||
|
tw.writeExprs_notinstanceofexpr(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
|
||||||
|
tw.writeHasLocation(id, locId)
|
||||||
|
extractExpressionExpr(e.argument, callable, id, 0)
|
||||||
|
extractTypeAccess(e.typeOperand, id, 1, e)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
logger.warnElement(Severity.ErrorSevere, "Unrecognised IrTypeOperatorCall: " + e.render(), e)
|
logger.warnElement(Severity.ErrorSevere, "Unrecognised IrTypeOperatorCall: " + e.render(), e)
|
||||||
|
|||||||
@@ -667,6 +667,8 @@ case @expr.kind of
|
|||||||
| 74 = @errorexpr
|
| 74 = @errorexpr
|
||||||
| 75 = @whenexpr
|
| 75 = @whenexpr
|
||||||
| 76 = @getclassexpr
|
| 76 = @getclassexpr
|
||||||
|
| 77 = @safecastexpr
|
||||||
|
| 78 = @notinstanceofexpr
|
||||||
;
|
;
|
||||||
|
|
||||||
/** Holds if this `when` expression was written as an `if` expression. */
|
/** Holds if this `when` expression was written as an `if` expression. */
|
||||||
|
|||||||
@@ -448,8 +448,12 @@ private module ControlFlowGraphImpl {
|
|||||||
or
|
or
|
||||||
this instanceof CastExpr
|
this instanceof CastExpr
|
||||||
or
|
or
|
||||||
|
this instanceof SafeCastExpr
|
||||||
|
or
|
||||||
this instanceof InstanceOfExpr and not this.(InstanceOfExpr).isPattern()
|
this instanceof InstanceOfExpr and not this.(InstanceOfExpr).isPattern()
|
||||||
or
|
or
|
||||||
|
this instanceof NotInstanceOfExpr
|
||||||
|
or
|
||||||
this instanceof LocalVariableDeclExpr and
|
this instanceof LocalVariableDeclExpr and
|
||||||
not this = any(InstanceOfExpr ioe).getLocalVariableDeclExpr()
|
not this = any(InstanceOfExpr ioe).getLocalVariableDeclExpr()
|
||||||
or
|
or
|
||||||
@@ -526,8 +530,12 @@ private module ControlFlowGraphImpl {
|
|||||||
or
|
or
|
||||||
index = 0 and result = this.(CastExpr).getExpr()
|
index = 0 and result = this.(CastExpr).getExpr()
|
||||||
or
|
or
|
||||||
|
index = 0 and result = this.(SafeCastExpr).getExpr()
|
||||||
|
or
|
||||||
index = 0 and result = this.(InstanceOfExpr).getExpr()
|
index = 0 and result = this.(InstanceOfExpr).getExpr()
|
||||||
or
|
or
|
||||||
|
index = 0 and result = this.(NotInstanceOfExpr).getExpr()
|
||||||
|
or
|
||||||
index = 0 and result = this.(LocalVariableDeclExpr).getInit()
|
index = 0 and result = this.(LocalVariableDeclExpr).getInit()
|
||||||
or
|
or
|
||||||
index = 0 and result = this.(RValue).getQualifier() and not result instanceof TypeAccess
|
index = 0 and result = this.(RValue).getQualifier() and not result instanceof TypeAccess
|
||||||
@@ -599,6 +607,8 @@ private module ControlFlowGraphImpl {
|
|||||||
or
|
or
|
||||||
result = first(n.(InstanceOfExpr).getExpr())
|
result = first(n.(InstanceOfExpr).getExpr())
|
||||||
or
|
or
|
||||||
|
result = first(n.(NotInstanceOfExpr).getExpr())
|
||||||
|
or
|
||||||
result = first(n.(SynchronizedStmt).getExpr())
|
result = first(n.(SynchronizedStmt).getExpr())
|
||||||
or
|
or
|
||||||
result = n and
|
result = n and
|
||||||
|
|||||||
@@ -123,6 +123,18 @@ class CastConversionContext extends ConversionSite {
|
|||||||
override string kind() { result = "cast context" }
|
override string kind() { result = "cast context" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SafeCastConversionContext extends ConversionSite {
|
||||||
|
SafeCastExpr c;
|
||||||
|
|
||||||
|
CastConversionContext() { this = c.getExpr() }
|
||||||
|
|
||||||
|
override Type getConversionTarget() { result = c.getType() }
|
||||||
|
|
||||||
|
override predicate isImplicit() { none() }
|
||||||
|
|
||||||
|
override string kind() { result = "safe cast context" }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A numeric conversion. For example, `a * b` converts `a` and
|
* A numeric conversion. For example, `a * b` converts `a` and
|
||||||
* `b` to have an appropriate numeric type.
|
* `b` to have an appropriate numeric type.
|
||||||
|
|||||||
@@ -1152,6 +1152,21 @@ class CastExpr extends Expr, @castexpr {
|
|||||||
override string getAPrimaryQlClass() { result = "CastExpr" }
|
override string getAPrimaryQlClass() { result = "CastExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Would this be better as a predicate on CastExpr?
|
||||||
|
/** A safe cast expression. */
|
||||||
|
class SafeCastExpr extends Expr, @safecastexpr {
|
||||||
|
/** Gets the target type of this cast expression. */
|
||||||
|
Expr getTypeExpr() { result.isNthChildOf(this, 0) }
|
||||||
|
|
||||||
|
/** Gets the expression to which the cast operator is applied. */
|
||||||
|
Expr getExpr() { result.isNthChildOf(this, 1) }
|
||||||
|
|
||||||
|
/** Gets a printable representation of this expression. */
|
||||||
|
override string toString() { result = "... as? ..." }
|
||||||
|
|
||||||
|
override string getAPrimaryQlClass() { result = "SafeCastExpr" }
|
||||||
|
}
|
||||||
|
|
||||||
/** A class instance creation expression. */
|
/** A class instance creation expression. */
|
||||||
class ClassInstanceExpr extends Expr, ConstructorCall, @classinstancexpr {
|
class ClassInstanceExpr extends Expr, ConstructorCall, @classinstancexpr {
|
||||||
/** Gets the number of arguments provided to the constructor of the class instance creation expression. */
|
/** Gets the number of arguments provided to the constructor of the class instance creation expression. */
|
||||||
@@ -1442,6 +1457,28 @@ class InstanceOfExpr extends Expr, @instanceofexpr {
|
|||||||
override string getAPrimaryQlClass() { result = "InstanceOfExpr" }
|
override string getAPrimaryQlClass() { result = "InstanceOfExpr" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Should this be desugared into instanceof.not()?
|
||||||
|
// Note expressions/IrTypeOperatorCall.kt says:
|
||||||
|
// NOT_INSTANCEOF, // TODO drop and replace with `INSTANCEOF<T>(x).not()`?
|
||||||
|
/** An `instanceof` expression. */
|
||||||
|
class NotInstanceOfExpr extends Expr, @notinstanceofexpr {
|
||||||
|
/** Gets the expression on the left-hand side of the `!is` operator. */
|
||||||
|
Expr getExpr() {
|
||||||
|
result.isNthChildOf(this, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the access to the type on the right-hand side of the `!is` operator. */
|
||||||
|
Expr getTypeName() { result.isNthChildOf(this, 1) }
|
||||||
|
|
||||||
|
/** Gets the type this `!is` expression checks for. */
|
||||||
|
RefType getCheckedType() { result = getTypeName().getType() }
|
||||||
|
|
||||||
|
/** Gets a printable representation of this expression. */
|
||||||
|
override string toString() { result = "... !is ..." }
|
||||||
|
|
||||||
|
override string getAPrimaryQlClass() { result = "NotInstanceOfExpr" }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A local variable declaration expression.
|
* A local variable declaration expression.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -360,8 +360,8 @@ private predicate safeCast(Type fromtyp, Type totyp) {
|
|||||||
/**
|
/**
|
||||||
* A cast that can be ignored for the purpose of range analysis.
|
* A cast that can be ignored for the purpose of range analysis.
|
||||||
*/
|
*/
|
||||||
private class SafeCastExpr extends CastExpr {
|
private class RangeAnalysisSafeCastExpr extends CastExpr {
|
||||||
SafeCastExpr() { safeCast(getExpr().getType(), getType()) }
|
RangeAnalysisSafeCastExpr() { safeCast(getExpr().getType(), getType()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -382,7 +382,7 @@ private predicate typeBound(Type typ, int lowerbound, int upperbound) {
|
|||||||
*/
|
*/
|
||||||
private class NarrowingCastExpr extends CastExpr {
|
private class NarrowingCastExpr extends CastExpr {
|
||||||
NarrowingCastExpr() {
|
NarrowingCastExpr() {
|
||||||
not this instanceof SafeCastExpr and
|
not this instanceof RangeAnalysisSafeCastExpr and
|
||||||
typeBound(getType(), _, _)
|
typeBound(getType(), _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,7 +412,7 @@ private predicate boundFlowStep(Expr e2, Expr e1, int delta, boolean upper) {
|
|||||||
valueFlowStep(e2, e1, delta) and
|
valueFlowStep(e2, e1, delta) and
|
||||||
(upper = true or upper = false)
|
(upper = true or upper = false)
|
||||||
or
|
or
|
||||||
e2.(SafeCastExpr).getExpr() = e1 and
|
e2.(RangeAnalysisSafeCastExpr).getExpr() = e1 and
|
||||||
delta = 0 and
|
delta = 0 and
|
||||||
(upper = true or upper = false)
|
(upper = true or upper = false)
|
||||||
or
|
or
|
||||||
|
|||||||
@@ -54,8 +54,15 @@
|
|||||||
| exprs.kt:40:5:40:22 | b6 | LocalVariableDeclExpr |
|
| exprs.kt:40:5:40:22 | b6 | LocalVariableDeclExpr |
|
||||||
| exprs.kt:40:14:40:15 | i1 | VarAccess |
|
| exprs.kt:40:14:40:15 | i1 | VarAccess |
|
||||||
| exprs.kt:40:14:40:22 | ...instanceof... | InstanceOfExpr |
|
| exprs.kt:40:14:40:22 | ...instanceof... | InstanceOfExpr |
|
||||||
|
| exprs.kt:40:14:40:22 | int | TypeAccess |
|
||||||
| exprs.kt:41:5:41:23 | b7 | LocalVariableDeclExpr |
|
| exprs.kt:41:5:41:23 | b7 | LocalVariableDeclExpr |
|
||||||
|
| exprs.kt:41:14:41:15 | i1 | VarAccess |
|
||||||
|
| exprs.kt:41:14:41:23 | ... !is ... | NotInstanceOfExpr |
|
||||||
|
| exprs.kt:41:14:41:23 | int | TypeAccess |
|
||||||
| exprs.kt:42:5:42:26 | b8 | LocalVariableDeclExpr |
|
| exprs.kt:42:5:42:26 | b8 | LocalVariableDeclExpr |
|
||||||
|
| exprs.kt:42:14:42:15 | b7 | VarAccess |
|
||||||
|
| exprs.kt:42:14:42:26 | (...)... | CastExpr |
|
||||||
|
| exprs.kt:42:14:42:26 | boolean | TypeAccess |
|
||||||
| exprs.kt:43:5:43:35 | str1 | LocalVariableDeclExpr |
|
| exprs.kt:43:5:43:35 | str1 | LocalVariableDeclExpr |
|
||||||
| exprs.kt:43:25:43:34 | string lit | StringLiteral |
|
| exprs.kt:43:25:43:34 | string lit | StringLiteral |
|
||||||
| exprs.kt:44:5:44:36 | str2 | LocalVariableDeclExpr |
|
| exprs.kt:44:5:44:36 | str2 | LocalVariableDeclExpr |
|
||||||
@@ -74,4 +81,3 @@
|
|||||||
| exprs.kt:53:9:53:18 | n | VarAccess |
|
| exprs.kt:53:9:53:18 | n | VarAccess |
|
||||||
| exprs.kt:54:27:54:31 | new C(...) | ClassInstanceExpr |
|
| exprs.kt:54:27:54:31 | new C(...) | ClassInstanceExpr |
|
||||||
| exprs.kt:54:29:54:30 | 42 | IntegerLiteral |
|
| exprs.kt:54:29:54:30 | 42 | IntegerLiteral |
|
||||||
| file://:0:0:0:0 | int | TypeAccess |
|
|
||||||
|
|||||||
Reference in New Issue
Block a user