Skip to content

Commit 36f56b5

Browse files
committed
Java: Rename StmtExpr to ValueDiscardingExpr
As mentioned by aschackmull during review, StatementExpression as defined by the JLS only lists possible types of expressions, it does _not_ specify that their value is discarded. Therefore, for example any method call could be considered a StatementExpression. The name ValueDiscardingExpr was chosen as replacement because the JLS uses the phrase "if the expression has a value, the value is discarded" multiple times.
1 parent bc5dc6a commit 36f56b5

File tree

15 files changed

+167
-126
lines changed

15 files changed

+167
-126
lines changed

java/ql/lib/change-notes/2022-03-27-statement-expression.md

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: feature
3+
---
4+
* The QL class `ValueDiscardingExpr` has been added, representing expressions for which the value of the expression as a whole is discarded.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class CollectionMutation extends MethodAccess {
8484
CollectionMutation() { this.getMethod() instanceof CollectionMutator }
8585

8686
/** Holds if the result of this call is not immediately discarded. */
87-
predicate resultIsChecked() { not this instanceof StmtExpr }
87+
predicate resultIsChecked() { not this instanceof ValueDiscardingExpr }
8888
}
8989

9090
/** A method that queries the contents of a collection without mutating it. */

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

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,38 +2135,45 @@ class Argument extends Expr {
21352135
}
21362136

21372137
/**
2138-
* A statement expression, as specified by JLS 17 section 14.8.
2139-
* The result of a statement expression, if any, is discarded.
2138+
* An expression for which the value of the expression as a whole is discarded. Only cases
2139+
* of discarded values at the language level (as described by the JLS) are considered;
2140+
* data flow, for example to determine if an assigned variable value is ever read, is not
2141+
* considered. Such expressions can for example appear as part of an `ExprStmt` or as
2142+
* initializer of a `for` loop.
21402143
*
2141-
* Not to be confused with `ExprStmt`; while the child of an `ExprStmt` is always
2142-
* a `StmtExpr`, the opposite is not true. A `StmtExpr` occurs for example also
2143-
* as 'init' of a `for` statement.
2144+
* For example, for the statement `i++;` the value of the increment expression, that is the
2145+
* old value of variable `i`, is discarded. Whereas for the statement `println(i++);` the
2146+
* value of the increment expression is not discarded but used as argument for the method call.
21442147
*/
2145-
class StmtExpr extends Expr {
2146-
StmtExpr() {
2147-
this = any(ExprStmt s).getExpr()
2148-
or
2149-
this = any(ForStmt s).getAnInit() and not this instanceof LocalVariableDeclExpr
2150-
or
2151-
this = any(ForStmt s).getAnUpdate()
2152-
or
2153-
// Only applies to SwitchStmt, but not to SwitchExpr, see JLS 17 section 14.11.2
2154-
this = any(SwitchStmt s).getACase().getRuleExpression()
2155-
or
2156-
// TODO: Workarounds for https://github.com/github/codeql/issues/3605
2157-
exists(LambdaExpr lambda |
2158-
this = lambda.getExprBody() and
2159-
lambda.asMethod().getReturnType() instanceof VoidType
2160-
)
2161-
or
2162-
exists(MemberRefExpr memberRef, Method implicitMethod, Method overridden |
2163-
implicitMethod = memberRef.asMethod()
2164-
|
2165-
this.getParent().(ReturnStmt).getEnclosingCallable() = implicitMethod and
2166-
// asMethod() has bogus method with wrong return type as result, e.g. `run(): String` (overriding `Runnable.run(): void`)
2167-
// Therefore need to check the overridden method
2168-
implicitMethod.getSourceDeclaration().overridesOrInstantiates*(overridden) and
2169-
overridden.getReturnType() instanceof VoidType
2170-
)
2148+
class ValueDiscardingExpr extends Expr {
2149+
ValueDiscardingExpr() {
2150+
(
2151+
this = any(ExprStmt s).getExpr()
2152+
or
2153+
this = any(ForStmt s).getAnInit() and not this instanceof LocalVariableDeclExpr
2154+
or
2155+
this = any(ForStmt s).getAnUpdate()
2156+
or
2157+
// Only applies to SwitchStmt, but not to SwitchExpr, see JLS 17 section 14.11.2
2158+
this = any(SwitchStmt s).getACase().getRuleExpression()
2159+
or
2160+
// TODO: Workarounds for https://github.com/github/codeql/issues/3605
2161+
exists(LambdaExpr lambda |
2162+
this = lambda.getExprBody() and
2163+
lambda.asMethod().getReturnType() instanceof VoidType
2164+
)
2165+
or
2166+
exists(MemberRefExpr memberRef, Method implicitMethod, Method overridden |
2167+
implicitMethod = memberRef.asMethod()
2168+
|
2169+
this.getParent().(ReturnStmt).getEnclosingCallable() = implicitMethod and
2170+
// asMethod() has bogus method with wrong return type as result, e.g. `run(): String` (overriding `Runnable.run(): void`)
2171+
// Therefore need to check the overridden method
2172+
implicitMethod.getSourceDeclaration().overridesOrInstantiates*(overridden) and
2173+
overridden.getReturnType() instanceof VoidType
2174+
)
2175+
) and
2176+
// Ignore if this expression is a method call with `void` as return type
2177+
not getType() instanceof VoidType
21712178
}
21722179
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class MapMutation extends MethodAccess {
5353
MapMutation() { this.getMethod() instanceof MapMutator }
5454

5555
/** Holds if the result of this call is not immediately discarded. */
56-
predicate resultIsChecked() { not this instanceof StmtExpr }
56+
predicate resultIsChecked() { not this instanceof ValueDiscardingExpr }
5757
}
5858

5959
/** A method that queries the contents of the map it belongs to without mutating it. */

java/ql/src/Likely Bugs/Statements/ReturnValueIgnored.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import Chaining
1818

1919
predicate checkedMethodCall(MethodAccess ma) {
2020
relevantMethodCall(ma, _) and
21-
not ma instanceof StmtExpr
21+
not ma instanceof ValueDiscardingExpr
2222
}
2323

2424
/**

java/ql/src/Violations of Best Practice/Exception Handling/IgnoreExceptionalReturn.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ predicate unboundedQueue(RefType t) {
4545

4646
from MethodAccess ma, SpecialMethod m
4747
where
48-
ma instanceof StmtExpr and
48+
ma instanceof ValueDiscardingExpr and
4949
m = ma.getMethod() and
5050
(
5151
m.isMethod("java.util", "Queue", "offer", 1) and not unboundedQueue(m.getDeclaringType())

java/ql/src/experimental/Security/CWE/CWE-297/IgnoredHostnameVerification.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ private class HostnameVerificationCall extends MethodAccess {
2121
}
2222

2323
/** Holds if the result of the call is not used. */
24-
predicate isIgnored() { this instanceof StmtExpr }
24+
predicate isIgnored() { this instanceof ValueDiscardingExpr }
2525
}
2626

2727
from HostnameVerificationCall verification

java/ql/test/library-tests/StmtExpr/StmtExpr.expected

Lines changed: 0 additions & 14 deletions
This file was deleted.

java/ql/test/library-tests/StmtExpr/StmtExpr.java

Lines changed: 0 additions & 68 deletions
This file was deleted.

0 commit comments

Comments
 (0)