Note that binding variables may be casting nodes

This commit is contained in:
Chris Smowton
2023-11-20 18:14:36 +00:00
parent c11a260369
commit da62a04653
5 changed files with 76 additions and 1 deletions

View File

@@ -375,7 +375,18 @@ predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { compatibleTypes0(t
/** A node that performs a type cast. */ /** A node that performs a type cast. */
class CastNode extends ExprNode { class CastNode extends ExprNode {
CastNode() { this.getExpr() instanceof CastingExpr } CastNode() {
this.getExpr() instanceof CastingExpr
or
exists(SsaExplicitUpdate upd |
upd.getDefiningExpr().(VariableAssign).getSource() =
[
any(SwitchStmt ss).getExpr(), any(SwitchExpr se).getExpr(),
any(InstanceOfExpr ioe).getExpr()
] and
this.asExpr() = upd.getAFirstUse()
)
}
} }
private newtype TDataFlowCallable = private newtype TDataFlowCallable =

View File

@@ -0,0 +1,42 @@
public class Test {
public static Object testFlowThroughSwitchStmt(String s, Integer i, boolean unknown) {
Object o = unknown ? s : i;
switch (o) {
case Integer i2 -> { return i2; }
default -> { return null; }
}
}
public static Object testFlowThroughSwitchExpr(String s, Integer i, boolean unknown) {
Object o = unknown ? s : i;
Integer toRet = switch (o) {
case Integer i2 -> i2;
default -> null;
};
return toRet;
}
public static Object testFlowThroughBindingInstanceOf(String s, Integer i, boolean unknown) {
Object o = unknown ? s : i;
if (o instanceof Integer i2)
return i2;
else
return null;
}
public static <T> T source() { return null; }
public static void sink(Object o) { }
public static void test(boolean unknown, boolean unknown2) {
String source1 = source();
Integer source2 = source();
sink(testFlowThroughSwitchStmt(source1, source2, unknown));
sink(testFlowThroughSwitchExpr(source1, source2, unknown));
sink(testFlowThroughBindingInstanceOf(source1, source2, unknown));
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args --release 21

View File

@@ -0,0 +1,3 @@
| Test.java:35:23:35:30 | source(...) | Test.java:36:10:36:61 | testFlowThroughSwitchStmt(...) |
| Test.java:35:23:35:30 | source(...) | Test.java:37:10:37:61 | testFlowThroughSwitchExpr(...) |
| Test.java:35:23:35:30 | source(...) | Test.java:38:10:38:68 | testFlowThroughBindingInstanceOf(...) |

View File

@@ -0,0 +1,18 @@
import java
import semmle.code.java.dataflow.DataFlow
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr() = any(MethodCall mc | mc.getCallee().getName() = "source")
}
predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(MethodCall mc | mc.getMethod().getName() = "sink").getAnArgument()
}
}
module Flow = DataFlow::Global<TestConfig>;
from DataFlow::Node source, DataFlow::Node sink
where Flow::flow(source, sink)
select source, sink