C++: Post-processing query for inline test expectations

This commit is contained in:
Tom Hvitved
2024-09-23 14:14:58 +02:00
parent 540b433f5a
commit 4750b0de94
7 changed files with 78 additions and 53 deletions

View File

@@ -5,31 +5,5 @@
import cpp as C
private import codeql.util.test.InlineExpectationsTest
private module Impl implements InlineExpectationsTestSig {
private newtype TExpectationComment = MkExpectationComment(C::CppStyleComment c)
/**
* A class representing a line comment in the CPP style.
* Unlike the `CppStyleComment` class, however, the string returned by `getContents` does _not_
* include the preceding comment marker (`//`).
*/
class ExpectationComment extends TExpectationComment {
C::CppStyleComment comment;
ExpectationComment() { this = MkExpectationComment(comment) }
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
string getContents() { result = comment.getContents().suffix(2) }
/** Gets a textual representation of this element. */
string toString() { result = comment.toString() }
/** Gets the location of this comment. */
Location getLocation() { result = comment.getLocation() }
}
class Location = C::Location;
}
private import internal.InlineExpectationsTestImpl
import Make<Impl>

View File

@@ -0,0 +1,21 @@
/**
* @kind test-postprocess
*/
private import cpp
private import codeql.util.test.InlineExpectationsTest as T
private import internal.InlineExpectationsTestImpl
import T::TestPostProcessing
import T::TestPostProcessing::Make<Impl, Input>
private module Input implements T::TestPostProcessing::InputSig<Impl> {
string getRelativeUrl(Location location) {
exists(File f, int startline, int startcolumn, int endline, int endcolumn |
location.hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and
f = location.getFile()
|
result =
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
)
}
}

View File

@@ -0,0 +1,28 @@
import cpp as C
private import codeql.util.test.InlineExpectationsTest
module Impl implements InlineExpectationsTestSig {
private newtype TExpectationComment = MkExpectationComment(C::CppStyleComment c)
/**
* A class representing a line comment in the CPP style.
* Unlike the `CppStyleComment` class, however, the string returned by `getContents` does _not_
* include the preceding comment marker (`//`).
*/
class ExpectationComment extends TExpectationComment {
C::CppStyleComment comment;
ExpectationComment() { this = MkExpectationComment(comment) }
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
string getContents() { result = comment.getContents().suffix(2) }
/** Gets a textual representation of this element. */
string toString() { result = comment.toString() }
/** Gets the location of this comment. */
Location getLocation() { result = comment.getLocation() }
}
class Location = C::Location;
}

View File

@@ -1 +1,2 @@
Critical/SizeCheck.ql
query: Critical/SizeCheck.ql
postprocess: TestUtilities/InlineExpectationsTestQuery.ql

View File

@@ -13,8 +13,8 @@ void free(void *ptr);
void bad0(void) {
float *fptr = malloc(3); // BAD -- Too small
double *dptr = malloc(5); // BAD -- Too small
float *fptr = malloc(3); // $ Alert -- Too small
double *dptr = malloc(5); // $ Alert -- Too small
free(fptr);
free(dptr);
}
@@ -29,8 +29,8 @@ void good0(void) {
void bad1(void) {
float *fptr = malloc(sizeof(short)); // BAD -- Too small
double *dptr = malloc(sizeof(float)); // BAD -- Too small
float *fptr = malloc(sizeof(short)); // $ Alert -- Too small
double *dptr = malloc(sizeof(float)); // $ Alert -- Too small
free(fptr);
free(dptr);
}
@@ -56,7 +56,7 @@ typedef union _myUnion
void test_union() {
MyUnion *a = malloc(sizeof(MyUnion)); // GOOD
MyUnion *b = malloc(sizeof(MyStruct)); // BAD (too small)
MyUnion *b = malloc(sizeof(MyStruct)); // $ Alert (too small)
}
// --- custom allocators ---
@@ -66,6 +66,6 @@ void *MyMalloc2(size_t size);
void customAllocatorTests()
{
float *fptr1 = MyMalloc1(3); // BAD (too small) [NOT DETECTED]
float *fptr2 = MyMalloc2(3); // BAD (too small) [NOT DETECTED]
float *fptr1 = MyMalloc1(3); // $ MISSING: BAD (too small)
float *fptr2 = MyMalloc2(3); // $ MISSING: BAD (too small)
}

View File

@@ -1 +1,2 @@
Security/CWE/CWE-022/TaintedPath.ql
query: Security/CWE/CWE-022/TaintedPath.ql
postprocess: TestUtilities/InlineExpectationsTestQuery.ql

View File

@@ -5,7 +5,7 @@
#define PATH_MAX 4096
///// Test code /////
int main(int argc, char** argv) {
int main(int argc, char** argv) { // $ Source=argv
char *userAndFile = argv[2];
{
@@ -14,7 +14,7 @@ int main(int argc, char** argv) {
size_t len = strlen(fileName);
strncat(fileName+len, userAndFile, FILENAME_MAX-len-1);
// BAD: a string from the user is used in a filename
fopen(fileName, "wb+");
fopen(fileName, "wb+"); // $ Alert=argv
}
{
@@ -29,30 +29,30 @@ int main(int argc, char** argv) {
{
char *fileName = argv[1];
fopen(fileName, "wb+"); // BAD
fopen(fileName, "wb+"); // $ Alert=argv
}
{
char fileName[20];
scanf("%s", fileName);
fopen(fileName, "wb+"); // BAD
scanf("%s", fileName); // $ Source=scanf_output1
fopen(fileName, "wb+"); // $ Alert=scanf_output1
}
{
char *fileName = (char*)malloc(20 * sizeof(char));
scanf("%s", fileName);
fopen(fileName, "wb+"); // BAD
scanf("%s", fileName); // $ Source=scanf_output2
fopen(fileName, "wb+"); // $ Alert=scanf_output2
}
{
char *tainted = getenv("A_STRING");
fopen(tainted, "wb+"); // BAD
char *tainted = getenv("A_STRING"); // $ Source=getenv1
fopen(tainted, "wb+"); // $ Alert=getenv1
}
{
char buffer[1024];
strncpy(buffer, getenv("A_STRING"), 1024);
fopen(buffer, "wb+"); // BAD
strncpy(buffer, getenv("A_STRING"), 1024); // $ Source=getenv2
fopen(buffer, "wb+"); // $ Alert=getenv2
fopen(buffer, "wb+"); // (we don't want a duplicate result here)
}
@@ -66,14 +66,14 @@ int main(int argc, char** argv) {
{
void readFile(const char *fileName);
readFile(argv[1]); // BAD
readFile(argv[1]); // $ Alert=argv
}
{
char buffer[1024];
read(0, buffer, 1024);
read(0, buffer, 1024);
fopen(buffer, "wb+"); // BAD [duplicated with both sources]
read(0, buffer, 1024); // $ Source=read_output1
read(0, buffer, 1024); // $ Source=read_output2
fopen(buffer, "wb+"); // $ Alert=read_output1 $ Alert=read_output2
}
{
@@ -81,7 +81,7 @@ int main(int argc, char** argv) {
char fileBuffer[PATH_MAX];
snprintf(fileBuffer, sizeof(fileBuffer), "/home/%s", userAndFile);
// BAD: a string from the user is used in a filename
fopen(fileBuffer, "wb+");
fopen(fileBuffer, "wb+"); // $ Alert=argv
}
{
@@ -95,7 +95,7 @@ int main(int argc, char** argv) {
char fileBuffer[PATH_MAX];
snprintf(fileBuffer, sizeof(fileBuffer), "/home/user/files/%s", fileName);
// GOOD: We know that the filename is safe and stays within the public folder. But we currently get an FP here.
FILE *file = fopen(fileBuffer, "wb+");
FILE *file = fopen(fileBuffer, "wb+"); // $ SPURIOUS: Alert=argv
}
{