-
Notifications
You must be signed in to change notification settings - Fork 67
Implement InvalidMemory1 package #176
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
1c3570d
M5-3-2: correct test-case comment typo
2a0429b
Implement InvalidMemory1 queries
7c41fe7
Correct package files
4ce7391
Update DereferenceOfNullPointer.expected
90fb93b
Update MEM30-C to include all pointer accesses
a92f73a
Merge branch 'main' into InvalidMemory1
knewbury01 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
417 changes: 417 additions & 0 deletions
417
c/cert/src/rules/EXP33-C/DoNotReadUninitializedMemory.md
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* @id c/cert/do-not-read-uninitialized-memory | ||
* @name EXP33-C: Do not read uninitialized memory | ||
* @description Using the value of an object with automatic storage duration while it is | ||
* indeterminate is undefined behavior. | ||
* @kind problem | ||
* @precision medium | ||
* @problem.severity error | ||
* @tags external/cert/id/exp33-c | ||
* correctness | ||
* security | ||
* external/cert/obligation/rule | ||
*/ | ||
|
||
import cpp | ||
import codingstandards.c.cert | ||
import codingstandards.cpp.rules.readofuninitializedmemory.ReadOfUninitializedMemory | ||
|
||
class DoNotReadUninitializedMemoryQuery extends ReadOfUninitializedMemorySharedQuery { | ||
DoNotReadUninitializedMemoryQuery() { | ||
this = InvalidMemory1Package::doNotReadUninitializedMemoryQuery() | ||
} | ||
} |
219 changes: 219 additions & 0 deletions
219
c/cert/src/rules/EXP34-C/DoNotDereferenceNullPointers.md
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* @id c/cert/do-not-dereference-null-pointers | ||
* @name EXP34-C: Do not dereference null pointers | ||
* @description Dereferencing a null pointer leads to undefined behavior. | ||
* @kind problem | ||
* @precision medium | ||
* @problem.severity error | ||
* @tags external/cert/id/exp34-c | ||
* correctness | ||
* external/cert/obligation/rule | ||
*/ | ||
|
||
import cpp | ||
import codingstandards.c.cert | ||
import codingstandards.cpp.rules.dereferenceofnullpointer.DereferenceOfNullPointer | ||
|
||
class DoNotDereferenceNullPointersQuery extends DereferenceOfNullPointerSharedQuery { | ||
DoNotDereferenceNullPointersQuery() { | ||
this = InvalidMemory1Package::doNotDereferenceNullPointersQuery() | ||
} | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/** | ||
* @id c/cert/do-not-access-freed-memory | ||
* @name MEM30-C: Do not access freed memory | ||
* @description Accessing memory that has been deallocated is undefined behavior. | ||
* @kind problem | ||
* @precision high | ||
* @problem.severity error | ||
* @tags external/cert/id/mem30-c | ||
* correctness | ||
* security | ||
* external/cert/obligation/rule | ||
*/ | ||
|
||
import cpp | ||
import codingstandards.c.cert | ||
import codingstandards.cpp.Allocations | ||
import semmle.code.cpp.controlflow.StackVariableReachability | ||
|
||
/** `e` is an expression that frees the memory pointed to by `v`. */ | ||
predicate isFreeExpr(Expr e, StackVariable v) { | ||
exists(VariableAccess va | va.getTarget() = v and freeExprOrIndirect(e, va, _)) | ||
} | ||
|
||
/** `e` is an expression that accesses `v` but is not the lvalue of an assignment. */ | ||
predicate isAccessExpr(Expr e, StackVariable v) { | ||
v.getAnAccess() = e and | ||
not exists(Assignment a | a.getLValue() = e) | ||
or | ||
isDerefByCallExpr(_, _, e, v) | ||
} | ||
|
||
/** | ||
* `va` is passed by value as (part of) the `i`th argument in | ||
* call `c`. The target function is either a library function | ||
* or a source code function that dereferences the relevant | ||
* parameter. | ||
*/ | ||
predicate isDerefByCallExpr(Call c, int i, VariableAccess va, StackVariable v) { | ||
v.getAnAccess() = va and | ||
va = c.getAnArgumentSubExpr(i) and | ||
not c.passesByReference(i, va) and | ||
(c.getTarget().hasEntryPoint() implies isAccessExpr(_, c.getTarget().getParameter(i))) | ||
} | ||
|
||
class UseAfterFreeReachability extends StackVariableReachability { | ||
UseAfterFreeReachability() { this = "UseAfterFree" } | ||
|
||
override predicate isSource(ControlFlowNode node, StackVariable v) { isFreeExpr(node, v) } | ||
|
||
override predicate isSink(ControlFlowNode node, StackVariable v) { isAccessExpr(node, v) } | ||
|
||
override predicate isBarrier(ControlFlowNode node, StackVariable v) { | ||
definitionBarrier(v, node) or | ||
isFreeExpr(node, v) | ||
knewbury01 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
// This query is a modified version of the `UseAfterFree.ql` | ||
// (cpp/use-after-free) query from the CodeQL standard library. | ||
from UseAfterFreeReachability r, StackVariable v, Expr free, Expr e | ||
where | ||
not isExcluded(e, InvalidMemory1Package::doNotAccessFreedMemoryQuery()) and | ||
r.reaches(free, v, e) | ||
select e, | ||
"Pointer '" + v.getName().toString() + "' accessed but may have been previously freed $@.", free, | ||
"here" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
c/common/test/rules/readofuninitializedmemory/ReadOfUninitializedMemory.ql |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
c/common/test/rules/dereferenceofnullpointer/DereferenceOfNullPointer.ql |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
| 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 | | ||
| 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 | | ||
| 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 | | ||
| 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 | | ||
| 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 | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
rules/MEM30-C/DoNotAccessFreedMemory.ql |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#include <stdlib.h> | ||
knewbury01 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#include <string.h> | ||
|
||
struct node { | ||
struct node *next; | ||
}; | ||
|
||
void test_freed_loop_var(struct node *list1, struct node *list2) { | ||
struct node *tmp; | ||
|
||
for (struct node *p = list1; p != NULL; p = p->next) { // NON_COMPLIANT | ||
free(p); | ||
} | ||
|
||
for (struct node *p = list2; p != NULL; p = tmp) { // COMPLIANT | ||
tmp = p->next; | ||
free(p); | ||
} | ||
} | ||
|
||
void test_freed_arg(char *input) { | ||
char *buf = (char *)malloc(strlen(input) + 1); | ||
strcpy(buf, input); // COMPLIANT | ||
free(buf); | ||
strcpy(buf, input); // NON_COMPLIANT | ||
} | ||
|
||
void test_freed_access_no_deref(char *input) { | ||
char *buf = (char *)malloc(strlen(input) + 1); | ||
strcpy(buf, input); // COMPLIANT | ||
free(buf); | ||
char *tmp = buf; // NON_COMPLIANT | ||
tmp = buf + 1; // NON_COMPLIANT | ||
char *tmp2 = buf; // NON_COMPLIANT | ||
buf = NULL; // COMPLIANT | ||
(char *)buf; // COMPLIANT | ||
tmp2 = buf + 1; // COMPLIANT | ||
} |
2 changes: 2 additions & 0 deletions
2
c/common/test/rules/dereferenceofnullpointer/DereferenceOfNullPointer.expected
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
| test.c:11:4:11:5 | l1 | Null may be dereferenced here because a null value was assigned $@. | test.c:4:21:4:21 | 0 | here | | ||
| test.c:18:6:18:7 | l1 | Null may be dereferenced here because a null value was assigned $@. | test.c:4:21:4:21 | 0 | here | |
2 changes: 2 additions & 0 deletions
2
c/common/test/rules/dereferenceofnullpointer/DereferenceOfNullPointer.ql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// GENERATED FILE - DO NOT MODIFY | ||
import codingstandards.cpp.rules.dereferenceofnullpointer.DereferenceOfNullPointer |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#include <stdlib.h> | ||
|
||
void test_null(int p1) { | ||
int *l1 = (void *)0; | ||
|
||
if (p1 > 10) { | ||
// l1 is only conditionally initialized | ||
l1 = malloc(10 * sizeof(int)); | ||
} | ||
|
||
*l1; // NON_COMPLIANT - dereferenced and still null | ||
|
||
if (l1) { | ||
*l1; // COMPLIANT - null check before dereference | ||
} | ||
|
||
if (!l1) { | ||
*l1; // NON_COMPLIANT - dereferenced and definitely null | ||
} else { | ||
*l1; // COMPLIANT - null check before dereference | ||
} | ||
|
||
free(l1); // COMPLIANT - free of `NULL` is not undefined behavior | ||
} | ||
|
||
void test_default_value_init() { | ||
int *l1; // indeterminate and thus invalid but non-null state | ||
|
||
*l1; // COMPLIANT - considered an uninitialized pointer, | ||
// not a null pointer | ||
} |
4 changes: 4 additions & 0 deletions
4
c/common/test/rules/readofuninitializedmemory/ReadOfUninitializedMemory.expected
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
| test.c:33:11:33:12 | l1 | Local variable $@ is read here and may not be initialized on all paths. | test.c:32:7:32:8 | l1 | l1 | | ||
| test.c:35:15:35:16 | l2 | Local variable $@ is read here and may not be initialized on all paths. | test.c:34:8:34:9 | l2 | l2 | | ||
| test.c:37:20:37:21 | l3 | Local variable $@ is read here and may not be initialized on all paths. | test.c:36:13:36:14 | l3 | l3 | | ||
| test.c:84:17:84:24 | arrayPtr | Local variable $@ is read here and may not be initialized on all paths. | test.c:77:8:77:15 | arrayPtr | arrayPtr | |
2 changes: 2 additions & 0 deletions
2
c/common/test/rules/readofuninitializedmemory/ReadOfUninitializedMemory.ql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// GENERATED FILE - DO NOT MODIFY | ||
import codingstandards.cpp.rules.readofuninitializedmemory.ReadOfUninitializedMemory |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
#include <stdlib.h> | ||
|
||
struct A { | ||
int m1; | ||
}; | ||
|
||
void use_int(int a); | ||
void use_struct_A(struct A a); | ||
void use_int_ptr(int *a); | ||
void use_struct_A_ptr(struct A *a); | ||
|
||
void init_by_pointer(int *pointer_param); | ||
|
||
void test_basic_init() { | ||
int l1 = 0; | ||
use_int(l1); // COMPLIANT | ||
struct A l2 = {}; | ||
use_struct_A(l2); // COMPLIANT | ||
int l3; | ||
init_by_pointer(&l3); | ||
use_int(l3); // COMPLIANT | ||
struct A l4; | ||
l4.m1 = 1; // COMPLIANT | ||
use_struct_A(l4); // COMPLIANT | ||
int l5[10] = {1, 0}; | ||
use_int_ptr(l5); // COMPLIANT | ||
struct A l6; | ||
use_struct_A(l6); // COMPLIANT[FALSE_NEGATIVE] | ||
} | ||
|
||
void test_basic_uninit() { | ||
int l1; | ||
use_int(l1); // NON_COMPLIANT | ||
int *l2; | ||
use_int_ptr(l2); // NON_COMPLIANT | ||
struct A *l3; | ||
use_struct_A_ptr(l3); // NON_COMPLIANT | ||
struct A l4; | ||
use_int(l4.m1); // NON_COMPLIANT[FALSE_NEGATIVE] - field is not initialized | ||
int l5[10]; | ||
use_int( | ||
l5[0]); // NON_COMPLIANT[FALSE_NEGATIVE] - array entry is not initialized | ||
} | ||
|
||
int run1(); | ||
|
||
void test_conditional(int x) { | ||
|
||
int l1; // l1 is defined and used only when x is true | ||
if (x) { | ||
l1 = 0; | ||
} | ||
if (x) { | ||
use_int(l1); // COMPLIANT | ||
} | ||
|
||
int l2; // l2 is defined and used only when x is false | ||
if (!x) { | ||
l2 = 0; | ||
} | ||
if (!x) { | ||
use_int(l2); // COMPLIANT | ||
} | ||
|
||
int l3 = 0; | ||
int l4; | ||
if (x) { | ||
l3 = 1; | ||
l4 = 1; | ||
} | ||
|
||
if (l3) { // l3 true indicates l4 is initialized | ||
use_int(l4); // COMPLIANT | ||
} | ||
|
||
int numElements = 0; | ||
int *arrayPtr; | ||
if (x) { | ||
numElements = 5; | ||
arrayPtr = malloc(sizeof(int) * numElements); | ||
} | ||
|
||
if (numElements > 0) { // numElements > 0 indicates arrayPtr is initialized | ||
use_int_ptr(arrayPtr); // COMPLIANT[FALSE_POSITIVE] | ||
} | ||
} | ||
|
||
void test_non_default_init() { | ||
static int sl; | ||
use_int(sl); // COMPLIANT - static int type variables are zero initialized | ||
static int *slp; | ||
use_int_ptr( | ||
slp); // COMPLIANT - static pointer type variables are zero initialized | ||
static struct A ss; | ||
use_struct_A( | ||
ss); // COMPLIANT - static struct type variables are zero initialized | ||
} |
22 changes: 22 additions & 0 deletions
22
c/misra/src/rules/RULE-9-1/ObjectWithAutoStorageDurationReadBeforeInit.ql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* @id c/misra/object-with-auto-storage-duration-read-before-init | ||
* @name RULE-9-1: The value of an object with automatic storage duration shall not be read before it has been set | ||
* @description Accessing an object before it has been initialized can lead to undefined behavior. | ||
* @kind problem | ||
* @precision medium | ||
* @problem.severity error | ||
* @tags external/misra/id/rule-9-1 | ||
* correctness | ||
* security | ||
* external/misra/obligation/mandatory | ||
*/ | ||
|
||
import cpp | ||
import codingstandards.c.misra | ||
import codingstandards.cpp.rules.readofuninitializedmemory.ReadOfUninitializedMemory | ||
|
||
class ObjectWithAutoStorageDurationReadBeforeInitQuery extends ReadOfUninitializedMemorySharedQuery { | ||
ObjectWithAutoStorageDurationReadBeforeInitQuery() { | ||
this = InvalidMemory1Package::objectWithAutoStorageDurationReadBeforeInitQuery() | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
c/misra/test/rules/RULE-9-1/ObjectWithAutoStorageDurationReadBeforeInit.testref
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
c/common/test/rules/readofuninitializedmemory/ReadOfUninitializedMemory.ql |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
cpp/common/test/rules/dereferenceofnullpointer/DereferenceOfNullPointer.ql |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.