Skip to content

Commit d787d94

Browse files
authored
Merge branch 'main' into download-db-vs-code
2 parents 45182c2 + b38ad13 commit d787d94

File tree

46 files changed

+350
-249
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+350
-249
lines changed

.github/workflows/ql-for-ql-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ jobs:
108108
### Run the analysis ###
109109
- name: Hack codeql-action options
110110
run: |
111-
JSON=$(jq -nc --arg pack "${PACK}" '.database."run-queries"=["--search-path", $pack] | .resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
111+
JSON=$(jq -nc --arg pack "${PACK}" '.database."run-queries"=["--search-path", $pack] | .resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .resolve.languages=["--search-path", $pack] | .database.init=["--search-path", $pack]')
112112
echo "CODEQL_ACTION_EXTRA_OPTIONS=${JSON}" >> ${GITHUB_ENV}
113113
env:
114114
PACK: ${{ runner.temp }}/pack

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3845,7 +3845,11 @@ open class KotlinFileExtractor(
38453845
return
38463846
}
38473847

3848-
val parameterTypes = type.arguments.map { it as IrType }
3848+
val parameterTypes = type.arguments.map { it as? IrType }.requireNoNullsOrNull()
3849+
if (parameterTypes == null) {
3850+
logger.errorElement("Unexpected: Non-IrType parameter.", functionReferenceExpr)
3851+
return
3852+
}
38493853

38503854
val dispatchReceiverIdx: Int
38513855
val expressionTypeArguments: List<IrType>
@@ -4669,14 +4673,18 @@ open class KotlinFileExtractor(
46694673
if (baseClass == null) {
46704674
logger.warnElement("Cannot find base class", currentDeclaration)
46714675
} else {
4672-
val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>()
4673-
tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor)
4674-
46754676
val baseConstructor = baseClass.owner.declarations.findSubType<IrFunction> { it.symbol is IrConstructorSymbol }
4676-
val baseConstructorId = useFunction<DbConstructor>(baseConstructor as IrFunction)
4677+
if (baseConstructor == null) {
4678+
logger.warnElement("Cannot find base constructor", currentDeclaration)
4679+
} else {
4680+
val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>()
4681+
tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor)
4682+
4683+
val baseConstructorId = useFunction<DbConstructor>(baseConstructor)
46774684

4678-
tw.writeHasLocation(superCallId, locId)
4679-
tw.writeCallableBinding(superCallId.cast<DbCaller>(), baseConstructorId)
4685+
tw.writeHasLocation(superCallId, locId)
4686+
tw.writeCallableBinding(superCallId.cast<DbCaller>(), baseConstructorId)
4687+
}
46804688
}
46814689

46824690
addModifiers(id, "final")

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

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ open class KotlinUsesExtractor(
709709
return useSimpleTypeClass(owner, args, s.hasQuestionMark)
710710
}
711711
owner is IrTypeParameter -> {
712-
val javaResult = useTypeParameter(owner as IrTypeParameter)
712+
val javaResult = useTypeParameter(owner)
713713
val aClassId = makeClass("kotlin", "TypeParam") // TODO: Wrong
714714
val kotlinResult = if (true) TypeResult(fakeKotlinType(), "TODO", "TODO") else
715715
if (s.hasQuestionMark) {
@@ -921,10 +921,17 @@ open class KotlinUsesExtractor(
921921
}
922922

923923
private fun extendsAdditionAllowed(t: IrType) =
924-
if (t.isBoxedArray)
925-
arrayExtendsAdditionAllowed(t as IrSimpleType)
926-
else
924+
if (t.isBoxedArray) {
925+
if (t is IrSimpleType) {
926+
arrayExtendsAdditionAllowed(t)
927+
} else {
928+
logger.warn("Boxed array of unexpected kind ${t.javaClass}")
929+
// Return false, for no particular reason
930+
false
931+
}
932+
} else {
927933
((t as? IrSimpleType)?.classOrNull?.owner?.isFinalClass) != true
934+
}
928935

929936
private fun wildcardAdditionAllowed(v: Variance, t: IrType, addByDefault: Boolean) =
930937
when {
@@ -1133,10 +1140,6 @@ open class KotlinUsesExtractor(
11331140
// Note not using `parentsWithSelf` as that only works if `d` is an IrDeclarationParent
11341141
d.parents.any { (it as? IrAnnotationContainer)?.hasAnnotation(jvmWildcardSuppressionAnnotaton) == true }
11351142

1136-
protected fun IrFunction.isLocalFunction(): Boolean {
1137-
return this.visibility == DescriptorVisibilities.LOCAL
1138-
}
1139-
11401143
/**
11411144
* Class to hold labels for generated classes around local functions, lambdas, function references, and property references.
11421145
*/
@@ -1178,6 +1181,14 @@ open class KotlinUsesExtractor(
11781181
return res
11791182
}
11801183

1184+
fun getExistingLocallyVisibleFunctionLabel(f: IrFunction): Label<DbMethod>? {
1185+
if (!f.isLocalFunction()){
1186+
return null
1187+
}
1188+
1189+
return tw.lm.locallyVisibleFunctionLabelMapping[f]?.function
1190+
}
1191+
11811192
// These are classes with Java equivalents, but whose methods don't all exist on those Java equivalents--
11821193
// for example, the numeric classes define arithmetic functions (Int.plus, Long.or and so on) that lower to
11831194
// primitive arithmetic on the JVM, but which we extract as calls to reflect the source syntax more closely.

java/kotlin-extractor/src/main/kotlin/comments/CommentExtractor.kt

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.github.codeql.comments
22

33
import com.github.codeql.*
44
import com.github.codeql.utils.IrVisitorLookup
5+
import com.github.codeql.utils.isLocalFunction
56
import com.github.codeql.utils.versions.Psi2Ir
67
import com.intellij.psi.PsiComment
78
import com.intellij.psi.PsiElement
@@ -92,29 +93,10 @@ class CommentExtractor(private val fileExtractor: KotlinFileExtractor, private v
9293
file.accept(IrVisitorLookup(psi2Ir, ownerPsi, file), owners)
9394

9495
for (ownerIr in owners) {
95-
val ownerLabel =
96-
if (ownerIr == file)
97-
fileLabel
98-
else {
99-
if (ownerIr is IrValueParameter && ownerIr.index == -1) {
100-
// Don't attribute comments to the implicit `this` parameter of a function.
101-
continue
102-
}
103-
val label: String
104-
val existingLabel = if (ownerIr is IrVariable) {
105-
label = "variable ${ownerIr.name.asString()}"
106-
tw.getExistingVariableLabelFor(ownerIr)
107-
} else {
108-
label = getLabel(ownerIr) ?: continue
109-
tw.getExistingLabelFor<DbTop>(label)
110-
}
111-
if (existingLabel == null) {
112-
logger.warn("Couldn't get existing label for $label")
113-
continue
114-
}
115-
existingLabel
116-
}
117-
tw.writeKtCommentOwners(commentLabel, ownerLabel)
96+
val ownerLabel = getLabel(ownerIr)
97+
if (ownerLabel != null) {
98+
tw.writeKtCommentOwners(commentLabel, ownerLabel)
99+
}
118100
}
119101
}
120102

@@ -126,11 +108,47 @@ class CommentExtractor(private val fileExtractor: KotlinFileExtractor, private v
126108
return owner
127109
}
128110

129-
private fun getLabel(element: IrElement) : String? {
111+
private fun getLabel(element: IrElement): Label<out DbTop>? {
112+
if (element == file)
113+
return fileLabel
114+
115+
if (element is IrValueParameter && element.index == -1) {
116+
// Don't attribute comments to the implicit `this` parameter of a function.
117+
return null
118+
}
119+
120+
val label: String
121+
val existingLabel = if (element is IrVariable) {
122+
// local variables are not named globally, so we need to get them from the variable label cache
123+
label = "variable ${element.name.asString()}"
124+
tw.getExistingVariableLabelFor(element)
125+
} else if (element is IrFunction && element.isLocalFunction()) {
126+
// local functions are not named globally, so we need to get them from the local function label cache
127+
label = "local function ${element.name.asString()}"
128+
fileExtractor.getExistingLocallyVisibleFunctionLabel(element)
129+
}
130+
else {
131+
label = getLabelForNamedElement(element) ?: return null
132+
tw.getExistingLabelFor<DbTop>(label)
133+
}
134+
if (existingLabel == null) {
135+
logger.warn("Couldn't get existing label for $label")
136+
return null
137+
}
138+
return existingLabel
139+
}
140+
141+
private fun getLabelForNamedElement(element: IrElement) : String? {
130142
when (element) {
131143
is IrClass -> return fileExtractor.getClassLabel(element, listOf()).classLabel
132144
is IrTypeParameter -> return fileExtractor.getTypeParameterLabel(element)
133-
is IrFunction -> return fileExtractor.getFunctionLabel(element, null)
145+
is IrFunction -> {
146+
return if (element.isLocalFunction()) {
147+
null
148+
} else {
149+
fileExtractor.getFunctionLabel(element, null)
150+
}
151+
}
134152
is IrValueParameter -> return fileExtractor.getValueParameterLabel(element, null)
135153
is IrProperty -> return fileExtractor.getPropertyLabel(element)
136154
is IrField -> return fileExtractor.getFieldLabel(element)
@@ -144,10 +162,10 @@ class CommentExtractor(private val fileExtractor: KotlinFileExtractor, private v
144162
return null
145163
}
146164
// Assign the comment to the class. The content of the `init` blocks might be extracted in multiple constructors.
147-
return getLabel(parentClass)
165+
return getLabelForNamedElement(parentClass)
148166
}
149167

150-
// Fresh entities:
168+
// Fresh entities, not named elements:
151169
is IrBody -> return null
152170
is IrExpression -> return null
153171

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.github.codeql.utils
2+
3+
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
4+
import org.jetbrains.kotlin.ir.declarations.IrFunction
5+
6+
fun IrFunction.isLocalFunction(): Boolean {
7+
return this.visibility == DescriptorVisibilities.LOCAL
8+
}

java/ql/test/kotlin/library-tests/comments/comments.expected

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ comments
77
| comments.kt:28:5:30:6 | /*\n A block comment\n */ | /*\n A block comment\n */ |
88
| comments.kt:35:5:35:34 | /** Medium is in the middle */ | /** Medium is in the middle */ |
99
| comments.kt:37:5:37:23 | /** This is high */ | /** This is high */ |
10-
| comments.kt:42:5:44:6 | /**\n * A variable.\n */ | /**\n * A variable.\n */ |
10+
| comments.kt:42:5:44:7 | /**\n * A variable.\n */ | /**\n * A variable.\n */ |
1111
| comments.kt:48:1:50:3 | /**\n * A type alias comment\n */ | /**\n * A type alias comment\n */ |
1212
| comments.kt:54:5:56:7 | /**\n * An init block comment\n */ | /**\n * An init block comment\n */ |
13+
| comments.kt:61:5:63:7 | /**\n * A prop comment\n */ | /**\n * A prop comment\n */ |
14+
| comments.kt:65:9:67:11 | /**\n * An accessor comment\n */ | /**\n * An accessor comment\n */ |
15+
| comments.kt:71:9:73:11 | /**\n * An anonymous function comment\n */ | /**\n * An anonymous function comment\n */ |
16+
| comments.kt:79:9:81:11 | /**\n * A local function comment\n */ | /**\n * A local function comment\n */ |
1317
commentOwners
1418
| comments.kt:4:1:11:3 | /**\n * A group of *members*.\n *\n * This class has no useful logic; it's just a documentation example.\n *\n * @property name the name of this group.\n * @constructor Creates an empty group.\n */ | comments.kt:12:1:31:1 | Group |
1519
| comments.kt:4:1:11:3 | /**\n * A group of *members*.\n *\n * This class has no useful logic; it's just a documentation example.\n *\n * @property name the name of this group.\n * @constructor Creates an empty group.\n */ | comments.kt:12:1:31:1 | Group |
@@ -19,9 +23,19 @@ commentOwners
1923
| comments.kt:19:5:22:7 | /**\n * Adds a [member] to this group.\n * @return the new size of the group.\n */ | comments.kt:23:5:26:5 | add |
2024
| comments.kt:35:5:35:34 | /** Medium is in the middle */ | comments.kt:36:5:36:14 | Medium |
2125
| comments.kt:37:5:37:23 | /** This is high */ | comments.kt:38:5:38:11 | High |
22-
| comments.kt:42:5:44:6 | /**\n * A variable.\n */ | comments.kt:45:5:45:13 | int a |
26+
| comments.kt:42:5:44:7 | /**\n * A variable.\n */ | comments.kt:45:5:45:13 | int a |
2327
| comments.kt:48:1:50:3 | /**\n * A type alias comment\n */ | comments.kt:51:1:51:24 | MyType |
2428
| comments.kt:54:5:56:7 | /**\n * An init block comment\n */ | comments.kt:53:1:58:1 | InitBlock |
29+
| comments.kt:61:5:63:7 | /**\n * A prop comment\n */ | comments.kt:64:5:68:17 | prop |
30+
| comments.kt:65:9:67:11 | /**\n * An accessor comment\n */ | comments.kt:68:9:68:17 | getProp |
31+
| comments.kt:71:9:73:11 | /**\n * An anonymous function comment\n */ | comments.kt:70:5:76:10 | getL |
32+
| comments.kt:71:9:73:11 | /**\n * An anonymous function comment\n */ | comments.kt:70:5:76:10 | l |
33+
| comments.kt:71:9:73:11 | /**\n * An anonymous function comment\n */ | comments.kt:70:5:76:10 | l |
34+
| comments.kt:79:9:81:11 | /**\n * A local function comment\n */ | comments.kt:82:9:82:24 | localFn |
35+
commentNoOwners
36+
| comments.kt:1:1:1:25 | /** Kdoc with no owner */ |
37+
| comments.kt:24:9:24:25 | // A line comment |
38+
| comments.kt:28:5:30:6 | /*\n A block comment\n */ |
2539
commentSections
2640
| comments.kt:1:1:1:25 | /** Kdoc with no owner */ | Kdoc with no owner |
2741
| comments.kt:4:1:11:3 | /**\n * A group of *members*.\n *\n * This class has no useful logic; it's just a documentation example.\n *\n * @property name the name of this group.\n * @constructor Creates an empty group.\n */ | A group of *members*.\n\nThis class has no useful logic; it's just a documentation example.\n\n |
@@ -31,14 +45,22 @@ commentSections
3145
| comments.kt:19:5:22:7 | /**\n * Adds a [member] to this group.\n * @return the new size of the group.\n */ | Adds a [member] to this group.\n |
3246
| comments.kt:35:5:35:34 | /** Medium is in the middle */ | Medium is in the middle |
3347
| comments.kt:37:5:37:23 | /** This is high */ | This is high |
34-
| comments.kt:42:5:44:6 | /**\n * A variable.\n */ | A variable. |
48+
| comments.kt:42:5:44:7 | /**\n * A variable.\n */ | A variable. |
3549
| comments.kt:48:1:50:3 | /**\n * A type alias comment\n */ | A type alias comment |
3650
| comments.kt:54:5:56:7 | /**\n * An init block comment\n */ | An init block comment |
51+
| comments.kt:61:5:63:7 | /**\n * A prop comment\n */ | A prop comment |
52+
| comments.kt:65:9:67:11 | /**\n * An accessor comment\n */ | An accessor comment |
53+
| comments.kt:71:9:73:11 | /**\n * An anonymous function comment\n */ | An anonymous function comment |
54+
| comments.kt:79:9:81:11 | /**\n * A local function comment\n */ | A local function comment |
3755
commentSectionContents
3856
| A group of *members*.\n\nThis class has no useful logic; it's just a documentation example.\n\n | A group of *members*.\n\nThis class has no useful logic; it's just a documentation example.\n\n |
57+
| A local function comment | A local function comment |
58+
| A prop comment | A prop comment |
3959
| A type alias comment | A type alias comment |
4060
| A variable. | A variable. |
4161
| Adds a [member] to this group.\n | Adds a [member] to this group.\n |
62+
| An accessor comment | An accessor comment |
63+
| An anonymous function comment | An anonymous function comment |
4264
| An init block comment | An init block comment |
4365
| Creates an empty group. | Creates an empty group. |
4466
| Kdoc with no owner | Kdoc with no owner |

java/ql/test/kotlin/library-tests/comments/comments.kt

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ enum class Severity(val sev: Int) {
4141
fun fn1() {
4242
/**
4343
* A variable.
44-
*/
44+
*/
4545
val a = 1
4646
}
4747

@@ -56,3 +56,29 @@ class InitBlock {
5656
*/
5757
init { }
5858
}
59+
60+
class X {
61+
/**
62+
* A prop comment
63+
*/
64+
val prop: Int
65+
/**
66+
* An accessor comment
67+
*/
68+
get() = 5
69+
70+
val l: Lazy<Int> = lazy(
71+
/**
72+
* An anonymous function comment
73+
*/
74+
fun(): Int {
75+
return 5
76+
})
77+
78+
fun fn() {
79+
/**
80+
* A local function comment
81+
*/
82+
fun localFn() {}
83+
}
84+
}

java/ql/test/kotlin/library-tests/comments/comments.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ query predicate comments(KtComment c, string s) { c.getText() = s }
44

55
query predicate commentOwners(KtComment c, Top t) { c.getOwner() = t }
66

7+
query predicate commentNoOwners(KtComment c) { not exists(c.getOwner()) }
8+
79
query predicate commentSections(KtComment c, KtCommentSection s) { c.getSections() = s }
810

911
query predicate commentSectionContents(KtCommentSection s, string c) { s.getContent() = c }

python/ql/src/Exceptions/EmptyExcept.ql

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313

1414
import python
15+
import semmle.python.ApiGraphs
1516

1617
predicate empty_except(ExceptStmt ex) {
1718
not exists(Stmt s | s = ex.getAStmt() and not s instanceof Pass)
@@ -28,7 +29,7 @@ predicate no_comment(ExceptStmt ex) {
2829
}
2930

3031
predicate non_local_control_flow(ExceptStmt ex) {
31-
ex.getType().pointsTo(ClassValue::stopIteration())
32+
ex.getType() = API::builtin("StopIteration").getAValueReachableFromSource().asExpr()
3233
}
3334

3435
predicate try_has_normal_exit(Try try) {
@@ -61,27 +62,32 @@ predicate subscript(Stmt s) {
6162
s.(Delete).getATarget() instanceof Subscript
6263
}
6364

64-
predicate encode_decode(Call ex, ClassValue type) {
65+
predicate encode_decode(Call ex, Expr type) {
6566
exists(string name | ex.getFunc().(Attribute).getName() = name |
66-
name = "encode" and type = ClassValue::unicodeEncodeError()
67+
name = "encode" and
68+
type = API::builtin("UnicodeEncodeError").getAValueReachableFromSource().asExpr()
6769
or
68-
name = "decode" and type = ClassValue::unicodeDecodeError()
70+
name = "decode" and
71+
type = API::builtin("UnicodeDecodeError").getAValueReachableFromSource().asExpr()
6972
)
7073
}
7174

72-
predicate small_handler(ExceptStmt ex, Stmt s, ClassValue type) {
75+
predicate small_handler(ExceptStmt ex, Stmt s, Expr type) {
7376
not exists(ex.getTry().getStmt(1)) and
7477
s = ex.getTry().getStmt(0) and
75-
ex.getType().pointsTo(type)
78+
ex.getType() = type
7679
}
7780

7881
predicate focussed_handler(ExceptStmt ex) {
79-
exists(Stmt s, ClassValue type | small_handler(ex, s, type) |
80-
subscript(s) and type.getASuperType() = ClassValue::lookupError()
82+
exists(Stmt s, Expr type | small_handler(ex, s, type) |
83+
subscript(s) and
84+
type = API::builtin("IndexError").getASubclass*().getAValueReachableFromSource().asExpr()
8185
or
82-
attribute_access(s) and type = ClassValue::attributeError()
86+
attribute_access(s) and
87+
type = API::builtin("AttributeError").getAValueReachableFromSource().asExpr()
8388
or
84-
s.(ExprStmt).getValue() instanceof Name and type = ClassValue::nameError()
89+
s.(ExprStmt).getValue() instanceof Name and
90+
type = API::builtin("NameError").getAValueReachableFromSource().asExpr()
8591
or
8692
encode_decode(s.(ExprStmt).getValue(), type)
8793
)

python/ql/src/Functions/ModificationOfParameterWithDefault.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ from
1919
ModificationOfParameterWithDefault::Configuration config, DataFlow::PathNode source,
2020
DataFlow::PathNode sink
2121
where config.hasFlowPath(source, sink)
22-
select sink.getNode(), source, sink, "$@ flows to here and is mutated.", source.getNode(),
23-
"Default value"
22+
select sink.getNode(), source, sink, "This expression mutates $@.", source.getNode(),
23+
"a default value"

0 commit comments

Comments
 (0)