Skip to content

Commit 90fb93b

Browse files
author
Nikita Kraiouchkine
committed
Update MEM30-C to include all pointer accesses
1 parent 4ce7391 commit 90fb93b

File tree

3 files changed

+27
-9
lines changed

3 files changed

+27
-9
lines changed

c/cert/src/rules/MEM30-C/DoNotAccessFreedMemory.ql

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ predicate isFreeExpr(Expr e, StackVariable v) {
2121
exists(VariableAccess va | va.getTarget() = v and freeExprOrIndirect(e, va, _))
2222
}
2323

24-
/** `e` is an expression that (may) dereference `v`. */
25-
predicate isDerefExpr(Expr e, StackVariable v) {
26-
v.getAnAccess() = e and dereferenced(e)
24+
/** `e` is an expression that accesses `v` but is not the lvalue of an assignment. */
25+
predicate isAccessExpr(Expr e, StackVariable v) {
26+
v.getAnAccess() = e and
27+
not exists(Assignment a | a.getLValue() = e)
2728
or
2829
isDerefByCallExpr(_, _, e, v)
2930
}
@@ -38,26 +39,28 @@ predicate isDerefByCallExpr(Call c, int i, VariableAccess va, StackVariable v) {
3839
v.getAnAccess() = va and
3940
va = c.getAnArgumentSubExpr(i) and
4041
not c.passesByReference(i, va) and
41-
(c.getTarget().hasEntryPoint() implies isDerefExpr(_, c.getTarget().getParameter(i)))
42+
(c.getTarget().hasEntryPoint() implies isAccessExpr(_, c.getTarget().getParameter(i)))
4243
}
4344

4445
class UseAfterFreeReachability extends StackVariableReachability {
4546
UseAfterFreeReachability() { this = "UseAfterFree" }
4647

4748
override predicate isSource(ControlFlowNode node, StackVariable v) { isFreeExpr(node, v) }
4849

49-
override predicate isSink(ControlFlowNode node, StackVariable v) { isDerefExpr(node, v) }
50+
override predicate isSink(ControlFlowNode node, StackVariable v) { isAccessExpr(node, v) }
5051

5152
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
5253
definitionBarrier(v, node) or
5354
isFreeExpr(node, v)
5455
}
5556
}
5657

58+
// This query is a modified version of the `UseAfterFree.ql`
59+
// (cpp/use-after-free) query from the CodeQL standard library.
5760
from UseAfterFreeReachability r, StackVariable v, Expr free, Expr e
5861
where
5962
not isExcluded(e, InvalidMemory1Package::doNotAccessFreedMemoryQuery()) and
6063
r.reaches(free, v, e)
6164
select e,
62-
"Memory pointed to by '" + v.getName().toString() +
63-
"' accessed but may have been previously freed $@.", free, "here"
65+
"Pointer '" + v.getName().toString() + "' accessed but may have been previously freed $@.", free,
66+
"here"
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
| test.c:11:47:11:47 | p | Memory pointed to by 'p' accessed but may have been previously freed $@. | test.c:12:5:12:8 | call to free | here |
2-
| test.c:25:10:25:12 | buf | Memory pointed to by 'buf' accessed but may have been previously freed $@. | test.c:24:3:24:6 | call to free | here |
1+
| test.c:11:47:11:47 | p | Pointer 'p' accessed but may have been previously freed $@. | test.c:12:5:12:8 | call to free | here |
2+
| test.c:25:10:25:12 | buf | Pointer 'buf' accessed but may have been previously freed $@. | test.c:24:3:24:6 | call to free | here |
3+
| test.c:32:15:32:17 | buf | Pointer 'buf' accessed but may have been previously freed $@. | test.c:31:3:31:6 | call to free | here |
4+
| test.c:33:9:33:11 | buf | Pointer 'buf' accessed but may have been previously freed $@. | test.c:31:3:31:6 | call to free | here |
5+
| test.c:34:16:34:18 | buf | Pointer 'buf' accessed but may have been previously freed $@. | test.c:31:3:31:6 | call to free | here |

c/cert/test/rules/MEM30-C/test.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,16 @@ void test_freed_arg(char *input) {
2323
strcpy(buf, input); // COMPLIANT
2424
free(buf);
2525
strcpy(buf, input); // NON_COMPLIANT
26+
}
27+
28+
void test_freed_access_no_deref(char *input) {
29+
char *buf = (char *)malloc(strlen(input) + 1);
30+
strcpy(buf, input); // COMPLIANT
31+
free(buf);
32+
char *tmp = buf; // NON_COMPLIANT
33+
tmp = buf + 1; // NON_COMPLIANT
34+
char *tmp2 = buf; // NON_COMPLIANT
35+
buf = NULL; // COMPLIANT
36+
(char *)buf; // COMPLIANT
37+
tmp2 = buf + 1; // COMPLIANT
2638
}

0 commit comments

Comments
 (0)