Skip to content
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

Shared: Post-processing query for inline test expectations #17548

Merged
merged 15 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 1 addition & 27 deletions cpp/ql/test/TestUtilities/InlineExpectationsTest.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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>
21 changes: 21 additions & 0 deletions cpp/ql/test/TestUtilities/InlineExpectationsTestQuery.ql
Original file line number Diff line number Diff line change
@@ -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
)
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Critical/SizeCheck.ql
query: Critical/SizeCheck.ql
postprocess: TestUtilities/InlineExpectationsTestQuery.ql
14 changes: 7 additions & 7 deletions cpp/ql/test/query-tests/Critical/SizeCheck/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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 ---
Expand All @@ -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)
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Security/CWE/CWE-022/TaintedPath.ql
query: Security/CWE/CWE-022/TaintedPath.ql
postprocess: TestUtilities/InlineExpectationsTestQuery.ql
34 changes: 17 additions & 17 deletions cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];

{
Expand All @@ -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
}

{
Expand All @@ -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)
}

Expand All @@ -66,22 +66,22 @@ 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
geoffw0 marked this conversation as resolved.
Show resolved Hide resolved
}

{
char *userAndFile = argv[2];
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
}

{
Expand All @@ -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
}

{
Expand Down
2 changes: 1 addition & 1 deletion csharp/ql/test/TestUtilities/InlineExpectationsTest.qll
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Inline expectation tests for CSharp.
* Inline expectation tests for C#.
* See `shared/util/codeql/util/test/InlineExpectationsTest.qll`
*/

Expand Down
21 changes: 21 additions & 0 deletions csharp/ql/test/TestUtilities/InlineExpectationsTestQuery.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @kind test-postprocess
*/

private import csharp
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
)
}
}
4 changes: 0 additions & 4 deletions csharp/ql/test/TestUtilities/PrettyPrintModels.ql
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,3 @@
import semmle.code.csharp.dataflow.internal.ExternalFlow
import codeql.dataflow.test.ProvenancePathGraph
import codeql.dataflow.test.ProvenancePathGraph::TestPostProcessing::TranslateProvenanceResults<interpretModelForTest/2>

from string relation, int row, int column, string data
where results(relation, row, column, data)
select relation, row, column, data
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ public class Pages_Index : global::Microsoft.AspNetCore.Mvc.RazorPages.Page
#line 3 "Index.cshtml"

ViewData["Title"] = "ASP.NET Core";
var message = Request.Query["m"];
var message = Request.Query["m"]; // $ Source=message

#line default
#line hidden
#nullable disable
WriteLiteral("<div class=\"cli\">\n <div class=\"cli-example\"> \n");
#nullable restore
#line 14 "Index.cshtml"
Write(Html.Raw(message)); // BAD
Write(Html.Raw(message)); // $ Alert=message

#line default
#line hidden
Expand Down
Loading
Loading