Skip to content

Commit 11bd356

Browse files
authored
Merge branch 'main' into jcogs33/exclude-funcexpr-from-dataflowtargetapi
2 parents 91c1ec3 + 8a89849 commit 11bd356

File tree

107 files changed

+479
-607
lines changed

Some content is hidden

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

107 files changed

+479
-607
lines changed

csharp/ql/lib/semmle/code/csharp/Callable.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,9 @@ class Constructor extends DotNet::Constructor, Callable, Member, Attributable, @
358358
if this.isStatic() then result = this.getParameter(i) else result = this.getParameter(i - 1)
359359
}
360360

361+
/** Holds if this is a constructor without parameters. */
362+
predicate isParameterless() { this.getNumberOfParameters() = 0 }
363+
361364
override string getUndecoratedName() { result = ".ctor" }
362365
}
363366

csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ private predicate isRelevantForModels(CS::Callable api) {
3939
not api instanceof CS::ConversionOperator and
4040
not api instanceof Util::MainMethod and
4141
not api instanceof CS::Destructor and
42-
not api instanceof CS::AnonymousFunctionExpr
42+
not api instanceof CS::AnonymousFunctionExpr and
43+
not api.(CS::Constructor).isParameterless()
4344
}
4445

4546
/**

csharp/ql/test/utils/model-generator/dataflow/NoSummaries.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,15 @@ public Dictionary<int, int> ReturnSimpleTypeDictionary(Dictionary<int, int> a)
131131
{
132132
return a;
133133
}
134-
}
134+
}
135+
136+
// A neutral model should not be created for a parameterless constructor.
137+
public class ParameterlessConstructor
138+
{
139+
public bool IsInitialized;
140+
141+
public ParameterlessConstructor()
142+
{
143+
IsInitialized = true;
144+
}
145+
}

java/ql/consistency-queries/cfgDeadEnds.ql

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ predicate shouldBeDeadEnd(ControlFlowNode n) {
5353
not exists(n.getFile().getRelativePath()) // TODO
5454
or
5555
n = any(ConstCase c).getValue(_) // TODO
56-
or
57-
n instanceof ErrorExpr // TODO
5856
}
5957

6058
from ControlFlowNode n, string s
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added support for Android Manifest `<activity-aliases>` elements in data flow sources.

java/ql/lib/semmle/code/java/Member.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,9 @@ class Constructor extends Callable, @constructor {
628628
/** Holds if this is a default constructor, not explicitly declared in source code. */
629629
predicate isDefaultConstructor() { isDefConstr(this) }
630630

631+
/** Holds if this is a constructor without parameters. */
632+
predicate isParameterless() { this.getNumberOfParameters() = 0 }
633+
631634
override Constructor getSourceDeclaration() { constrs(this, _, _, _, _, result) }
632635

633636
override string getSignature() { constrs(this, _, result, _, _, _) }

java/ql/lib/semmle/code/java/frameworks/android/Android.qll

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ class AndroidComponent extends Class {
2626

2727
/** The XML element corresponding to this Android component. */
2828
AndroidComponentXmlElement getAndroidComponentXmlElement() {
29-
result.getResolvedComponentName() = this.getQualifiedName()
29+
// Find an element with an identifier matching the qualified name of the component.
30+
// Aliases have two identifiers (name and target), so check both identifiers (if present).
31+
exists(AndroidIdentifierXmlAttribute identifier |
32+
identifier = result.getAnAttribute() and
33+
result.getResolvedIdentifier(identifier) = this.getQualifiedName()
34+
)
3035
}
3136

3237
/** Holds if this Android component is configured as `exported` in an `AndroidManifest.xml` file. */
@@ -52,6 +57,12 @@ class ExportableAndroidComponent extends AndroidComponent {
5257
or
5358
this.hasIntentFilter() and
5459
not this.getAndroidComponentXmlElement().isNotExported()
60+
or
61+
exists(AndroidActivityAliasXmlElement e |
62+
e = this.getAndroidComponentXmlElement() and
63+
not e.isNotExported() and
64+
e.hasAnIntentFilterElement()
65+
)
5566
}
5667
}
5768

java/ql/lib/semmle/code/xml/AndroidManifest.qll

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,42 @@ class AndroidApplicationXmlElement extends XmlElement {
129129
*/
130130
class AndroidActivityXmlElement extends AndroidComponentXmlElement {
131131
AndroidActivityXmlElement() { this.getName() = "activity" }
132+
133+
/**
134+
* Gets an `<activity-alias>` element aliasing the activity.
135+
*/
136+
AndroidActivityAliasXmlElement getAnAlias() {
137+
exists(AndroidActivityAliasXmlElement alias | this = alias.getTarget() | result = alias)
138+
}
139+
}
140+
141+
/**
142+
* An `<activity-alias>` element in an Android manifest file.
143+
*/
144+
class AndroidActivityAliasXmlElement extends AndroidComponentXmlElement {
145+
AndroidActivityAliasXmlElement() { this.getName() = "activity-alias" }
146+
147+
/**
148+
* Get and resolve the name of the target activity from the `android:targetActivity` attribute.
149+
*/
150+
string getResolvedTargetActivityName() {
151+
exists(AndroidXmlAttribute attr |
152+
attr = this.getAnAttribute() and attr.getName() = "targetActivity"
153+
|
154+
result = this.getResolvedIdentifier(attr)
155+
)
156+
}
157+
158+
/**
159+
* Gets the `<activity>` element referenced by the `android:targetActivity` attribute.
160+
*/
161+
AndroidActivityXmlElement getTarget() {
162+
exists(AndroidActivityXmlElement activity |
163+
activity.getResolvedComponentName() = this.getResolvedTargetActivityName()
164+
|
165+
result = activity
166+
)
167+
}
132168
}
133169

134170
/**
@@ -212,6 +248,13 @@ class AndroidPermissionXmlAttribute extends XmlAttribute {
212248
predicate isWrite() { this.getName() = "writePermission" }
213249
}
214250

251+
/**
252+
* The attribute `android:name` or `android:targetActivity`.
253+
*/
254+
class AndroidIdentifierXmlAttribute extends AndroidXmlAttribute {
255+
AndroidIdentifierXmlAttribute() { this.getName() = ["name", "targetActivity"] }
256+
}
257+
215258
/**
216259
* The `<path-permission`> element of a `<provider>` in an Android manifest file.
217260
*/
@@ -228,7 +271,7 @@ class AndroidPathPermissionXmlElement extends XmlElement {
228271
class AndroidComponentXmlElement extends XmlElement {
229272
AndroidComponentXmlElement() {
230273
this.getParent() instanceof AndroidApplicationXmlElement and
231-
this.getName().regexpMatch("(activity|service|receiver|provider)")
274+
this.getName().regexpMatch("(activity|activity-alias|service|receiver|provider)")
232275
}
233276

234277
/**
@@ -254,19 +297,30 @@ class AndroidComponentXmlElement extends XmlElement {
254297
)
255298
}
256299

300+
/**
301+
* Gets the value of an identifier attribute, and tries to resolve it into a fully qualified identifier.
302+
*/
303+
string getResolvedIdentifier(AndroidIdentifierXmlAttribute identifier) {
304+
exists(string name | name = identifier.getValue() |
305+
if name.matches(".%")
306+
then
307+
result =
308+
this.getParent()
309+
.(XmlElement)
310+
.getParent()
311+
.(AndroidManifestXmlElement)
312+
.getPackageAttributeValue() + name
313+
else result = name
314+
)
315+
}
316+
257317
/**
258318
* Gets the resolved value of the `android:name` attribute of this component element.
259319
*/
260320
string getResolvedComponentName() {
261-
if this.getComponentName().matches(".%")
262-
then
263-
result =
264-
this.getParent()
265-
.(XmlElement)
266-
.getParent()
267-
.(AndroidManifestXmlElement)
268-
.getPackageAttributeValue() + this.getComponentName()
269-
else result = this.getComponentName()
321+
exists(AndroidXmlAttribute attr | attr = this.getAnAttribute() and attr.getName() = "name" |
322+
result = this.getResolvedIdentifier(attr)
323+
)
270324
}
271325

272326
/**

java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ private predicate isRelevantForModels(J::Callable api) {
6060
not isJdkInternal(api.getCompilationUnit()) and
6161
not api instanceof J::MainMethod and
6262
not api instanceof J::StaticInitializer and
63-
not exists(J::FunctionalExpr funcExpr | api = funcExpr.asMethod())
63+
not exists(J::FunctionalExpr funcExpr | api = funcExpr.asMethod()) and
64+
not api.(J::Constructor).isParameterless()
6465
}
6566

6667
/**
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
| exprs.kt:278:52:278:66 | <error expr> | ErrorExpr | unexpected dead end |
12
| exprs.kt:278:52:278:66 | { ... } | BlockStmt | unexpected dead end |

0 commit comments

Comments
 (0)