Skip to content

Commit fe38154

Browse files
Kotlin: include !! operands in qualified-call locations under K1
For a call qualified through a not-null assertion (e.g. `s!!.foo()`), `TrapWriter.getStartOffset` derives the call's start from its receiver. Under K1 the receiver is the `CHECK_NOT_NULL`/EXCLEXCL intrinsic IrCall, whose own `startOffset` points at the first `!` character rather than at the operand `s`. The enclosing call therefore inherited the `!!` offset and omitted the receiver operand from its span. The `!!` intrinsic carries its operand as value argument 0 (not as a dispatch/extension receiver), so the existing receiver-based adjustment did not reach it. Extend `getStartOffset` to also consider value argument 0 of an EXCLEXCL call, recursively. This makes a `!!`-qualified call span from the operand, matching K2, which already anchors the receiver at the operand. The change affects source locations only; AST structure, call targets, and dataflow relationships are unchanged. K2 output is unaffected because its offsets already start at the operand. Fully converges dataflow/notnullexpr and exprs/binop between the K1 and K2 suites and removes 6 divergent rows overall. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 86bfc022-3ecc-4746-ba23-3b76c4e4c3e4
1 parent 8d67df0 commit fe38154

4 files changed

Lines changed: 16 additions & 4 deletions

File tree

java/kotlin-extractor/src/main/kotlin/TrapWriter.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.github.codeql
22

33
import com.github.codeql.KotlinUsesExtractor.LocallyVisibleFunctionLabels
44
import com.github.codeql.utils.versions.codeQlExtensionReceiver
5+
import com.github.codeql.utils.versions.codeQlGetValueArgument
56
import com.semmle.extractor.java.PopulateFile
67
import com.semmle.util.unicode.UTF8Util
78
import java.io.BufferedWriter
@@ -14,6 +15,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
1415
import org.jetbrains.kotlin.ir.declarations.IrVariable
1516
import org.jetbrains.kotlin.ir.declarations.path
1617
import org.jetbrains.kotlin.ir.expressions.IrCall
18+
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
1719
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
1820

1921
/**
@@ -347,7 +349,17 @@ open class FileTrapWriter(
347349
// Calls have incorrect startOffset, so we adjust them:
348350
val dr = e.dispatchReceiver?.let { getStartOffset(it) }
349351
val er = e.codeQlExtensionReceiver?.let { getStartOffset(it) }
350-
offsetMinOf(e.startOffset, dr, er)
352+
// The `!!` (CHECK_NOT_NULL / EXCLEXCL) intrinsic carries its operand as value
353+
// argument 0 rather than as a dispatch/extension receiver, and in K1 its own
354+
// startOffset points at the `!` token rather than the operand. Consider the
355+
// operand's start so that a call qualified through a `!!` expression (e.g.
356+
// `s!!.foo()`) spans from the operand. K2 already starts at the operand, so it is
357+
// unaffected.
358+
val exclOperand =
359+
if (e.origin == IrStatementOrigin.EXCLEXCL)
360+
e.codeQlGetValueArgument(0)?.let { getStartOffset(it) }
361+
else null
362+
offsetMinOf(e.startOffset, dr, er, exclOperand)
351363
}
352364
else -> e.startOffset
353365
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| NotNullExpr.kt:7:14:7:20 | taint(...) | NotNullExpr.kt:8:12:8:33 | getQueryParameter(...) |
1+
| NotNullExpr.kt:7:14:7:20 | taint(...) | NotNullExpr.kt:8:10:8:33 | getQueryParameter(...) |

java/ql/test-kotlin1/library-tests/exprs/binop.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
| exprs.kt:141:12:141:20 | ... + ... | exprs.kt:141:12:141:14 | 123 | exprs.kt:141:18:141:20 | 456 |
9797
| exprs.kt:167:8:167:16 | ... (value not-equals) ... | exprs.kt:167:8:167:8 | r | exprs.kt:167:13:167:16 | null |
9898
| exprs.kt:196:31:196:37 | ... + ... | exprs.kt:196:31:196:32 | getA1(...) | exprs.kt:196:36:196:37 | a2 |
99-
| exprs.kt:211:20:211:29 | ... + ... | exprs.kt:211:19:211:21 | ...!! | exprs.kt:211:28:211:28 | 5 |
99+
| exprs.kt:211:19:211:29 | ... + ... | exprs.kt:211:19:211:21 | ...!! | exprs.kt:211:28:211:28 | 5 |
100100
| exprs.kt:212:19:212:25 | ... + ... | exprs.kt:212:19:212:21 | ...!! | exprs.kt:212:25:212:25 | 5 |
101101
| exprs.kt:230:12:230:47 | ... (value equals) ... | exprs.kt:230:12:230:27 | notNullPrimitive | exprs.kt:230:32:230:47 | notNullPrimitive |
102102
| exprs.kt:231:12:231:48 | ... (value equals) ... | exprs.kt:231:12:231:27 | notNullPrimitive | exprs.kt:231:32:231:48 | nullablePrimitive |

java/ql/test-kotlin1/library-tests/exprs/exprs.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,7 @@
15931593
| exprs.kt:211:9:211:29 | b2 | exprs.kt:206:5:217:5 | x | LocalVariableDeclExpr |
15941594
| exprs.kt:211:19:211:19 | s | exprs.kt:206:5:217:5 | x | VarAccess |
15951595
| exprs.kt:211:19:211:21 | ...!! | exprs.kt:206:5:217:5 | x | NotNullExpr |
1596-
| exprs.kt:211:20:211:29 | ... + ... | exprs.kt:206:5:217:5 | x | AddExpr |
1596+
| exprs.kt:211:19:211:29 | ... + ... | exprs.kt:206:5:217:5 | x | AddExpr |
15971597
| exprs.kt:211:28:211:28 | 5 | exprs.kt:206:5:217:5 | x | IntegerLiteral |
15981598
| exprs.kt:212:9:212:25 | b3 | exprs.kt:206:5:217:5 | x | LocalVariableDeclExpr |
15991599
| exprs.kt:212:19:212:19 | s | exprs.kt:206:5:217:5 | x | VarAccess |

0 commit comments

Comments
 (0)