Skip to content

Commit

Permalink
Merge pull request #281 from kraiouchkine/OutOfBounds
Browse files Browse the repository at this point in the history
Implement OutOfBounds package
  • Loading branch information
rvermeulen authored Apr 8, 2023
2 parents d25e575 + ea9b0f4 commit c2961f3
Show file tree
Hide file tree
Showing 24 changed files with 3,565 additions and 0 deletions.
1 change: 1 addition & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@
"Null",
"OperatorInvariants",
"Operators",
"OutOfBounds",
"Pointers",
"Pointers1",
"Pointers2",
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* @id c/cert/do-not-form-out-of-bounds-pointers-or-array-subscripts
* @name ARR30-C: Do not form or use out-of-bounds pointers or array subscripts
* @description Forming or using an out-of-bounds pointer is undefined behavior and can result in
* invalid memory accesses.
* @kind problem
* @precision medium
* @problem.severity error
* @tags external/cert/id/arr30-c
* correctness
* security
* external/cert/obligation/rule
*/

import cpp
import codingstandards.c.cert
import codingstandards.c.OutOfBounds

from
OOB::BufferAccess ba, Expr bufferArg, Expr sizeArg, OOB::PointerToObjectSource bufferSource,
string message
where
not isExcluded(ba, OutOfBoundsPackage::doNotFormOutOfBoundsPointersOrArraySubscriptsQuery()) and
// exclude loops
not exists(Loop loop | loop.getStmt().getChildStmt*() = ba.getEnclosingStmt()) and
// exclude size arguments that are of type ssize_t
not sizeArg.getAChild*().(VariableAccess).getTarget().getType() instanceof Ssize_t and
// exclude size arguments that are assigned the result of a function call e.g. ftell
not sizeArg.getAChild*().(VariableAccess).getTarget().getAnAssignedValue() instanceof FunctionCall and
// exclude field or array accesses for the size arguments
not sizeArg.getAChild*() instanceof FieldAccess and
not sizeArg.getAChild*() instanceof ArrayExpr and
(
exists(int sizeArgValue, int bufferArgSize |
OOB::isSizeArgGreaterThanBufferSize(bufferArg, sizeArg, bufferSource, bufferArgSize, sizeArgValue, ba) and
message =
"Buffer accesses offset " + sizeArgValue +
" which is greater than the fixed size " + bufferArgSize + " of the $@."
)
or
exists(int sizeArgUpperBound, int sizeMult, int bufferArgSize |
OOB::isSizeArgNotCheckedLessThanFixedBufferSize(bufferArg, sizeArg, bufferSource,
bufferArgSize, ba, sizeArgUpperBound, sizeMult) and
message =
"Buffer may access up to offset " + sizeArgUpperBound + "*" + sizeMult +
" which is greater than the fixed size " + bufferArgSize + " of the $@."
)
or
OOB::isSizeArgNotCheckedGreaterThanZero(bufferArg, sizeArg, bufferSource, ba) and
message = "Buffer access may be to a negative index in the buffer."
)
select ba, message, bufferSource, "buffer"
486 changes: 486 additions & 0 deletions c/cert/src/rules/ARR38-C/LibraryFunctionArgumentOutOfBounds.md

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions c/cert/src/rules/ARR38-C/LibraryFunctionArgumentOutOfBounds.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @id c/cert/library-function-argument-out-of-bounds
* @name ARR38-C: Guarantee that library functions do not form invalid pointers
* @description Passing out-of-bounds pointers or erroneous size arguments to standard library
* functions can result in out-of-bounds accesses and other undefined behavior.
* @kind problem
* @precision high
* @problem.severity error
* @tags external/cert/id/arr38-c
* correctness
* security
* external/cert/obligation/rule
*/

import cpp
import codingstandards.c.cert
import codingstandards.c.OutOfBounds

from
OOB::BufferAccessLibraryFunctionCall fc, string message, Expr bufferArg, string bufferArgStr,
Expr sizeOrOtherBufferArg, string otherStr
where
not isExcluded(fc, OutOfBoundsPackage::libraryFunctionArgumentOutOfBoundsQuery()) and
OOB::problems(fc, message, bufferArg, bufferArgStr, sizeOrOtherBufferArg, otherStr)
select fc, message, bufferArg, bufferArgStr, sizeOrOtherBufferArg, otherStr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
| test.c:8:3:8:11 | ... + ... | Buffer accesses offset 404 which is greater than the fixed size 400 of the $@. | test.c:8:3:8:5 | arr | buffer |
| test.c:16:3:16:13 | ... + ... | Buffer access may be to a negative index in the buffer. | test.c:16:3:16:5 | arr | buffer |
| test.c:21:5:21:15 | ... + ... | Buffer access may be to a negative index in the buffer. | test.c:21:5:21:7 | arr | buffer |
| test.c:41:17:41:30 | ... + ... | Buffer access may be to a negative index in the buffer. | test.c:41:17:41:22 | buffer | buffer |
| test.c:45:17:45:30 | ... + ... | Buffer may access up to offset 101*1 which is greater than the fixed size 100 of the $@. | test.c:45:17:45:22 | buffer | buffer |
| test.c:55:5:55:13 | ... - ... | Buffer access may be to a negative index in the buffer. | test.c:55:5:55:9 | ptr16 | buffer |
| test.c:57:5:57:14 | ... + ... | Buffer accesses offset 22 which is greater than the fixed size 20 of the $@. | test.c:57:5:57:9 | ptr16 | buffer |
| test.c:58:5:58:14 | ... - ... | Buffer access may be to a negative index in the buffer. | test.c:58:5:58:9 | ptr16 | buffer |
| test.c:63:3:63:9 | access to array | Buffer access may be to a negative index in the buffer. | test.c:63:3:63:5 | arr | buffer |
| test.c:65:3:65:9 | access to array | Buffer accesses offset 44 which is greater than the fixed size 40 of the $@. | test.c:65:3:65:5 | arr | buffer |
| test.c:66:3:66:10 | access to array | Buffer access may be to a negative index in the buffer. | test.c:66:3:66:5 | arr | buffer |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/ARR30-C/DoNotFormOutOfBoundsPointersOrArraySubscripts.ql
67 changes: 67 additions & 0 deletions c/cert/test/rules/ARR30-C/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@


enum { ARRAY_SIZE = 100 };

static int arr[ARRAY_SIZE];

void test_fixed_wrong(void) {
arr + 101; // NON_COMPLIANT
}

void test_fixed_right(void) {
arr + 2; // COMPLIANT
}

void test_no_check(int index) {
arr + index; // NON_COMPLIANT
}

void test_invalid_check(int index) {
if (index < ARRAY_SIZE) {
arr + index; // NON_COMPLIANT - `index` could be negative
}
}

void test_valid_check(int index) {
if (index > 0 && index < ARRAY_SIZE) {
arr + index; // COMPLIANT - `index` cannot be negative
}
}

void test_valid_check_by_type(unsigned int index) {
if (index < ARRAY_SIZE) {
arr + index; // COMPLIANT - `index` cannot be be negative
}
}

void test_local_buffer_invalid_check(int index) {
char buffer[ARRAY_SIZE];

if (index < ARRAY_SIZE) {
char *ptr = buffer + index; // NON_COMPLIANT - `index` could be negative
}

if (index >= 0 && index < ARRAY_SIZE + 2) {
char *ptr = buffer + index; // NON_COMPLIANT - `index` could be too large
}

if (index >= 0 && index < ARRAY_SIZE) {
char *ptr = buffer + index; // COMPLIANT
}
}

void test_dereference_pointer_arithmetic_const(void) {
short ptr16[10];
*(ptr16 - 1); // NON_COMPLIANT - offset is negative
*(ptr16 + 5); // COMPLIANT
*(ptr16 + 11); // NON_COMPLIANT - offset is too large
*(ptr16 - 11); // NON_COMPLIANT - offset is negative
}

void test_array_expr_const(void) {
int arr[10];
arr[-1]; // NON_COMPLIANT - offset is negative
arr[5]; // COMPLIANT
arr[11]; // NON_COMPLIANT - offset is too large
arr[-11]; // NON_COMPLIANT - offset is negative
}
Loading

0 comments on commit c2961f3

Please sign in to comment.