Skip to content

Commit 7245591

Browse files
authored
Merge pull request #7763 from erik-krogh/unused-field
QL: add unused-field query
2 parents d352253 + dfe2140 commit 7245591

File tree

7 files changed

+39
-15
lines changed

7 files changed

+39
-15
lines changed

java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,6 @@ private class IntentFlagsOrDataChangedSanitizer extends IntentUriPermissionManip
9696
* ```
9797
*/
9898
private class IntentFlagsOrDataCheckedGuard extends IntentUriPermissionManipulationGuard {
99-
Expr condition;
100-
10199
IntentFlagsOrDataCheckedGuard() { intentFlagsOrDataChecked(this, _, _) }
102100

103101
override predicate checks(Expr e, boolean branch) { intentFlagsOrDataChecked(this, e, branch) }

java/ql/src/experimental/semmle/code/java/PathSanitizer.qll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,6 @@ private predicate isDisallowedWord(CompileTimeConstantExpr word) {
148148

149149
/** A complementary guard that protects against path traversal, by looking for the literal `..`. */
150150
class PathTraversalGuard extends Guard instanceof MethodAccess {
151-
Expr checked;
152-
153151
PathTraversalGuard() {
154152
super.getMethod().getDeclaringType() instanceof TypeString and
155153
super.getMethod().hasName(["contains", "indexOf"]) and

javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,6 @@ module ClientRequest {
330330
* A model of a URL request made using `require("needle")(...)`.
331331
*/
332332
class PromisedNeedleRequest extends ClientRequest::Range {
333-
DataFlow::Node url;
334-
335333
PromisedNeedleRequest() { this = DataFlow::moduleImport("needle").getACall() }
336334

337335
override DataFlow::Node getUrl() { result = this.getArgument(1) }

javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,8 +683,6 @@ private module ExpressJwt {
683683
*/
684684
private module NodeRsa {
685685
private class CreateKey extends CryptographicKeyCreation, API::InvokeNode {
686-
CryptographicAlgorithm algorithm;
687-
688686
CreateKey() {
689687
this = API::moduleImport("node-rsa").getAnInstantiation()
690688
or

python/ql/src/experimental/semmle/python/frameworks/Flask.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ module ExperimentalFlask {
6767
private class FlaskResponse extends DataFlow::CallCfgNode, HeaderDeclaration::Range {
6868
KeyValuePair item;
6969

70-
FlaskResponse() { this = Flask::Response::classRef().getACall() }
70+
FlaskResponse() {
71+
this = Flask::Response::classRef().getACall() and
72+
item = this.getArg(_).asExpr().(Dict).getAnItem()
73+
}
7174

7275
override DataFlow::Node getNameArg() { result.asExpr() = item.getKey() }
7376

python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ edges
1313
| flask_bad.py:35:18:35:24 | ControlFlowNode for request | flask_bad.py:35:18:35:29 | ControlFlowNode for Attribute |
1414
| flask_bad.py:35:18:35:29 | ControlFlowNode for Attribute | flask_bad.py:35:18:35:43 | ControlFlowNode for Subscript |
1515
| flask_bad.py:35:18:35:43 | ControlFlowNode for Subscript | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header |
16-
| flask_bad.py:44:44:44:50 | ControlFlowNode for request | flask_bad.py:44:44:44:55 | ControlFlowNode for Attribute |
17-
| flask_bad.py:44:44:44:55 | ControlFlowNode for Attribute | flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript |
1816
nodes
1917
| django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
2018
| django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
@@ -36,9 +34,6 @@ nodes
3634
| flask_bad.py:35:18:35:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
3735
| flask_bad.py:35:18:35:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
3836
| flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header |
39-
| flask_bad.py:44:44:44:50 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
40-
| flask_bad.py:44:44:44:55 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
41-
| flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
4237
subpaths
4338
#select
4439
| django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | This | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | user-provided value |
@@ -47,4 +42,3 @@ subpaths
4742
| flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | flask_bad.py:19:18:19:24 | ControlFlowNode for request | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | This | flask_bad.py:19:18:19:24 | ControlFlowNode for request | user-provided value |
4843
| flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | flask_bad.py:27:18:27:24 | ControlFlowNode for request | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | This | flask_bad.py:27:18:27:24 | ControlFlowNode for request | user-provided value |
4944
| flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | flask_bad.py:35:18:35:24 | ControlFlowNode for request | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | This | flask_bad.py:35:18:35:24 | ControlFlowNode for request | user-provided value |
50-
| flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | flask_bad.py:44:44:44:50 | ControlFlowNode for request | flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | $@ HTTP header is constructed from a $@. | flask_bad.py:44:44:44:69 | ControlFlowNode for Subscript | This | flask_bad.py:44:44:44:50 | ControlFlowNode for request | user-provided value |
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* @name UnusedField
3+
* @description A field that is not used in the characteristic predicate will contain every value
4+
* of its type when accessed in other predicates, which is probably not intended.
5+
* @kind problem
6+
* @problem.severity warning
7+
* @id ql/unused-field
8+
* @precision high
9+
*/
10+
11+
import ql
12+
13+
from ClassType clz, ClassType implClz, FieldDecl field, string extraMsg
14+
where
15+
clz.getDeclaration().getAField() = field and
16+
implClz.getASuperType*() = clz and
17+
// The field is not accessed in the charpred (of any of the classes)
18+
not exists(FieldAccess access |
19+
access.getEnclosingPredicate() = [clz, implClz].getDeclaration().getCharPred()
20+
) and
21+
// The implementation class is not abstract, and the field is not an override
22+
not implClz.getDeclaration().isAbstract() and
23+
not field.isOverride() and
24+
// There doesn't exist a class in between `clz` and `implClz` that binds `field`.
25+
not exists(ClassType c, CharPred p |
26+
c.getASuperType*() = clz and
27+
implClz.getASuperType*() = c and
28+
p = c.getDeclaration().getCharPred() and
29+
exists(FieldAccess access | access.getName() = field.getName() |
30+
access.getEnclosingPredicate() = p
31+
)
32+
) and
33+
(if clz = implClz then extraMsg = "." else extraMsg = " of any class between it and $@.")
34+
select clz, "The field $@ declared in $@ is not used in the characteristic predicate" + extraMsg,
35+
field, field.getName(), clz, clz.getName(), implClz, implClz.getName()

0 commit comments

Comments
 (0)