From c01f570d9e5abe0caeb15529164e6ad3c262944e Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 22 Jun 2020 20:28:04 +0200 Subject: [PATCH] Java: Implement `clearsContent()` --- .../code/java/dataflow/internal/DataFlowPrivate.qll | 9 +++++++++ java/ql/test/library-tests/dataflow/fields/F.java | 6 +++--- java/ql/test/library-tests/dataflow/fields/flow.expected | 7 ------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 324b026ca2e..693ce2d5aba 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -195,6 +195,15 @@ predicate readStep(Node node1, Content f, Node node2) { ) } +/** + * Holds if values stored inside content `c` are cleared at node `n`. For example, + * any value stored inside `f` is cleared at the pre-update node associated with `x` + * in `x.f = newValue`. + */ +predicate clearsContent(Node n, Content c) { + n = any(PostUpdateNode pun | storeStep(_, c, pun)).getPreUpdateNode() +} + /** * Gets a representative (boxed) type for `t` for the purpose of pruning * possible flow. A single type is used for all numeric types to account for diff --git a/java/ql/test/library-tests/dataflow/fields/F.java b/java/ql/test/library-tests/dataflow/fields/F.java index 317c08d7f6c..221d514d674 100644 --- a/java/ql/test/library-tests/dataflow/fields/F.java +++ b/java/ql/test/library-tests/dataflow/fields/F.java @@ -13,12 +13,12 @@ public class F { f.Field2 = o; f.Field2 = null; sink(f.Field1); // flow - sink(f.Field2); // no flow [FALSE POSITIVE] + sink(f.Field2); // no flow f = new F(); f.Field2 = null; sink(f.Field1); // flow - sink(f.Field2); // no flow [FALSE POSITIVE] + sink(f.Field2); // no flow f = new F(); o = new Object(); @@ -31,7 +31,7 @@ public class F { { f.Field2 = null; sink(f.Field1); // flow - sink(f.Field2); // no flow [FALSE POSITIVE] + sink(f.Field2); // no flow } public static void sink(Object o) { } diff --git a/java/ql/test/library-tests/dataflow/fields/flow.expected b/java/ql/test/library-tests/dataflow/fields/flow.expected index af6050a3a9b..382819fbdbb 100644 --- a/java/ql/test/library-tests/dataflow/fields/flow.expected +++ b/java/ql/test/library-tests/dataflow/fields/flow.expected @@ -26,13 +26,6 @@ | E.java:2:32:2:43 | new Object(...) | E.java:21:10:21:24 | bh2.buf.content | | E.java:2:32:2:43 | new Object(...) | E.java:24:10:24:28 | p2.data.buf.content | | E.java:2:32:2:43 | new Object(...) | E.java:30:10:30:27 | p.data.buf.content | -| F.java:5:14:5:25 | new Object(...) | F.java:15:10:15:17 | f.Field1 | | F.java:5:14:5:25 | new Object(...) | F.java:20:10:20:17 | f.Field1 | -| F.java:5:14:5:25 | new Object(...) | F.java:33:10:33:17 | f.Field1 | -| F.java:6:14:6:25 | new Object(...) | F.java:16:10:16:17 | f.Field2 | -| F.java:6:14:6:25 | new Object(...) | F.java:21:10:21:17 | f.Field2 | -| F.java:6:14:6:25 | new Object(...) | F.java:34:10:34:17 | f.Field2 | | F.java:10:16:10:27 | new Object(...) | F.java:15:10:15:17 | f.Field1 | -| F.java:10:16:10:27 | new Object(...) | F.java:16:10:16:17 | f.Field2 | | F.java:24:9:24:20 | new Object(...) | F.java:33:10:33:17 | f.Field1 | -| F.java:24:9:24:20 | new Object(...) | F.java:34:10:34:17 | f.Field2 |