Add test for dataflow vs. pattern-switch

This commit is contained in:
Chris Smowton
2023-10-25 15:18:23 +01:00
parent 6c990c2cf6
commit 0f434e7f08
5 changed files with 75 additions and 1 deletions

View File

@@ -197,7 +197,9 @@ private predicate simpleLocalFlowStep0(Node node1, Node node2) {
// Variable flow steps through adjacent def-use and use-use pairs.
exists(SsaExplicitUpdate upd |
upd.getDefiningExpr().(VariableAssign).getSource() = node1.asExpr() or
upd.getDefiningExpr().(AssignOp) = node1.asExpr()
upd.getDefiningExpr().(AssignOp) = node1.asExpr() or
upd.getDefiningExpr().(LocalVariableDeclExpr).getAssociatedSwitch().(SwitchStmt).getExpr() = node1.asExpr() or
upd.getDefiningExpr().(LocalVariableDeclExpr).getAssociatedSwitch().(SwitchExpr).getExpr() = node1.asExpr()
|
node2.asExpr() = upd.getAFirstUse() and
not capturedVariableRead(node2)

View File

@@ -0,0 +1,47 @@
public class Test {
interface I { String get(); }
static class A implements I { public String afield; public A(String a) { this.afield = a; } public String get() { return afield; } }
static class B implements I { public String bfield; public B(String b) { this.bfield = b; } public String get() { return bfield; } }
public static String sink(String s) { return s; }
public static void test(boolean inp) {
I i = inp ? new A("A") : new B("B");
switch(i) {
case A a:
sink(a.get());
break;
case B b:
sink(b.get());
break;
default:
break;
}
switch(i) {
case A a -> sink(a.get());
case B b -> sink(b.get());
default -> { }
}
var x = switch(i) {
case A a:
yield sink(a.get());
case B b:
yield sink(b.get());
default:
yield "Default case";
};
var y = switch(i) {
case A a -> sink(a.get());
case B b -> sink(b.get());
default -> "Default case";
};
}
}

View File

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

View File

@@ -0,0 +1,8 @@
| Test.java:11:23:11:25 | "A" | Test.java:15:14:15:20 | get(...) |
| Test.java:11:23:11:25 | "A" | Test.java:25:24:25:30 | get(...) |
| Test.java:11:23:11:25 | "A" | Test.java:32:20:32:26 | get(...) |
| Test.java:11:23:11:25 | "A" | Test.java:40:24:40:30 | get(...) |
| Test.java:11:36:11:38 | "B" | Test.java:18:14:18:20 | get(...) |
| Test.java:11:36:11:38 | "B" | Test.java:26:24:26:30 | get(...) |
| Test.java:11:36:11:38 | "B" | Test.java:34:20:34:26 | get(...) |
| Test.java:11:36:11:38 | "B" | Test.java:41:24:41:30 | get(...) |

View File

@@ -0,0 +1,16 @@
import java
import semmle.code.java.dataflow.DataFlow
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof StringLiteral }
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