From 250d4e341fd0a2785cf9b7d74c4ef58321e7aff2 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Thu, 1 Oct 2026 09:53:50 -0700 Subject: [PATCH] Update EXP43-C to use new dataflow. Updating to new dataflow introduced test failures in the old test.c file caused by an assignment that aliased the two primary global values under test. Most of the test assumed these were distinct pointer values, and yet, there was one assignment between them, contradicting this intention. The old dataflow library seemed to model this as a function called once, which would produce the results that the test expected. However, the new dataflow seems to assume that the function could be called multiple times, and therefore the fact that these globals were ever aliased means they have flow between them. Broke the main test function apart into separate functions testing against separate global values, to preserve old test results as much as possible, and cleanly exercise the new justifiable difference in behavior. --- ...trictPointerReferencesOverlappingObject.ql | 2 +- ...ointerReferencesOverlappingObject.expected | 28 +++++------ c/cert/test/rules/EXP43-C/test.c | 50 ++++++++++++++----- .../2026-10-01-use-new-dataflow-in-exp43-c.md | 2 + 4 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 change_notes/2026-10-01-use-new-dataflow-in-exp43-c.md diff --git a/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql b/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql index 31618785d2..0f85dabd0b 100644 --- a/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql +++ b/c/cert/src/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.ql @@ -16,7 +16,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow import semmle.code.cpp.controlflow.Dominance import codingstandards.c.cert import codingstandards.cpp.Variable diff --git a/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected b/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected index 40009edc03..e5ced8c5aa 100644 --- a/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected +++ b/c/cert/test/rules/EXP43-C/RestrictPointerReferencesOverlappingObject.expected @@ -1,16 +1,12 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:47,57-65) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:48,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:52,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:58,3-11) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:61,58-66) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:77,64-72) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (RestrictPointerReferencesOverlappingObject.ql:78,64-72) -| test.c:18:22:18:23 | i2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:18:17:18:18 | i3 | i3 | test.c:18:22:18:23 | i2 | the object pointed to by i2 | -| test.c:19:8:19:9 | g2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:5:15:5:16 | g1 | g1 | test.c:19:8:19:9 | g2 | the object pointed to by g2 | -| test.c:20:8:20:9 | i2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:16:17:16:18 | i1 | i1 | test.c:20:8:20:9 | i2 | the object pointed to by i2 | -| test.c:27:10:27:11 | g1 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:23:19:23:20 | i5 | i5 | test.c:19:8:19:9 | g2 | the same source value | -| test.c:28:10:28:11 | g1 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:22:19:22:20 | i4 | i4 | test.c:19:8:19:9 | g2 | the same source value | -| test.c:39:22:39:26 | & ... | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:39:17:39:18 | px | px | test.c:38:28:38:30 | & ... | v1 via address-of | -| test.c:45:10:45:14 | & ... | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:42:19:42:20 | pz | pz | test.c:43:10:43:14 | & ... | v1 via address-of | -| test.c:46:10:46:14 | & ... | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:41:19:41:20 | py | py | test.c:43:10:43:14 | & ... | v1 via address-of | -| test.c:46:10:46:14 | & ... | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:41:19:41:20 | py | py | test.c:45:10:45:14 | & ... | v1 via address-of | +| test.c:15:22:15:23 | i2 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:15:17:15:18 | i3 | i3 | test.c:15:22:15:23 | i2 | the object pointed to by i2 | +| test.c:34:22:34:23 | g4 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:34:17:34:18 | i2 | i2 | test.c:34:22:34:23 | g4 | the same source value | +| test.c:35:8:35:9 | g4 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:18:15:18:16 | g3 | g3 | test.c:35:8:35:9 | g4 | the object pointed to by g4 | +| test.c:49:10:49:11 | g5 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:45:19:45:20 | i5 | i5 | test.c:41:22:41:23 | g5 | the same source value | +| test.c:49:10:49:11 | g5 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:45:19:45:20 | i5 | i5 | test.c:47:10:47:11 | g5 | the same source value | +| test.c:50:10:50:11 | g5 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:44:19:44:20 | i4 | i4 | test.c:41:22:41:23 | g5 | the same source value | +| test.c:50:10:50:11 | g5 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:44:19:44:20 | i4 | i4 | test.c:47:10:47:11 | g5 | the same source value | +| test.c:50:10:50:11 | g5 | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:44:19:44:20 | i4 | i4 | test.c:49:10:49:11 | g5 | the same source value | +| test.c:63:22:63:26 | & ... | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:63:17:63:18 | px | px | test.c:62:28:62:30 | & ... | v1 via address-of | +| test.c:69:10:69:14 | & ... | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:66:19:66:20 | pz | pz | test.c:67:10:67:14 | & ... | v1 via address-of | +| test.c:70:10:70:14 | & ... | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:65:19:65:20 | py | py | test.c:67:10:67:14 | & ... | v1 via address-of | +| test.c:70:10:70:14 | & ... | Assignment to restrict-qualified pointer $@ results in pointers aliasing $@. | test.c:65:19:65:20 | py | py | test.c:69:10:69:14 | & ... | v1 via address-of | diff --git a/c/cert/test/rules/EXP43-C/test.c b/c/cert/test/rules/EXP43-C/test.c index 3bf7cfa490..1a62fdc6ef 100644 --- a/c/cert/test/rules/EXP43-C/test.c +++ b/c/cert/test/rules/EXP43-C/test.c @@ -2,35 +2,59 @@ #include #include -int *restrict g1; -int *restrict g2; -int *restrict g1_1; -int *g2_1; - struct s1 { int x, y, z; }; struct s1 v1; -void test_global_local() { +int *restrict g1; +int *restrict g2; +void test_global_local_1() { int *restrict i1 = g1; // COMPLIANT int *restrict i2 = g2; // COMPLIANT int *restrict i3 = i2; // NON_COMPLIANT - g1 = g2; // NON_COMPLIANT - i1 = i2; // NON_COMPLIANT +} + +int *restrict g3; +int *restrict g4; +void test_global_local_2() { + // The second assignment in this block is non-compliant for subtle reasons. + // + // If we assume that `test_global_local_2` is only called once, then `g3` and + // `g4` will likely point to different values and therefore `i1` and `i2` do + // not alias each other. from g3 to g4 is too late to cause an issue. This was + // how this query worked under the old dataflow library. + // + // However, if we assume this function is called more than once, then the + // assignment that causes `g3` and `g4` to have the same value, at the end of + // this function, can predate the assignments that initialize `i1` and `i2` + // within this function, leading to aliasing that violates the rule. This is + // how the new dataflow library handles this case. + int *restrict i1 = g3; // COMPLIANT + int *restrict i2 = g4; // NON_COMPLIANT + g3 = g4; // NON_COMPLIANT +} + +int *restrict g5; +int *restrict g6; +void test_global_local_3() { + int *restrict i2 = g5; // COMPLIANT + int *restrict i3 = g6; // COMPLIANT { int *restrict i4; int *restrict i5; int *restrict i6; - i4 = g1; // COMPLIANT + i4 = g5; // COMPLIANT -- first assignment within this block i4 = (void *)0; // COMPLIANT - i5 = g1; // NON_COMPLIANT - block rather than statement scope matters - i4 = g1; // NON_COMPLIANT - i6 = g2; // COMPLIANT + i5 = g5; // NON_COMPLIANT - block rather than statement scope matters + i4 = g5; // NON_COMPLIANT + i6 = g6; // COMPLIANT -- first assignment within this block } } -void test_global_local_1() { +int *restrict g1_1; +int *g2_1; +void test_global_local_4() { g1_1 = g2_1; // COMPLIANT } diff --git a/change_notes/2026-10-01-use-new-dataflow-in-exp43-c.md b/change_notes/2026-10-01-use-new-dataflow-in-exp43-c.md new file mode 100644 index 0000000000..e4d2c198b7 --- /dev/null +++ b/change_notes/2026-10-01-use-new-dataflow-in-exp43-c.md @@ -0,0 +1,2 @@ + - `EXP43-C` - `RestrictPointerReferencesOverlappingObject.ql`: + - Updated to use the new dataflow library for tracking assignments to restrict-qualified pointers. Using the new dataflow library may introduce a different set of false positives and false negatives compared to the previous implementation, though it has higher precision overall. \ No newline at end of file