Skip to content

java inline expectations proof-of-concept with tests #16911

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

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
81 changes: 81 additions & 0 deletions java/ql/test/TestUtilities/JavaInlineExpectations.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* @kind test-postprocess
*/

import java

external predicate queryResults(string relation, int row, int column, string data);

predicate parsedExpectedResults(string filename, int line, string content) {
exists(Javadoc doc |
isEolComment(doc) and
filename = doc.getLocation().getFile().getBaseName() and
line = doc.getLocation().getStartLine() and
line = doc.getLocation().getEndLine() and
content = doc.getChild(0).getText().trim()
)
}

predicate expectError(string filename, int line) {
exists(string content |
parsedExpectedResults(filename, line, content) and content.indexOf("NOT OK") = 0
)
}

predicate expectPass(string filename, int line) {
exists(string content |
parsedExpectedResults(filename, line, content) and content.indexOf("OK") = 0
)
}

predicate parsedActualResults(string filename, int line, int colStart, int colEnd, string content) {
exists(int i, string posString, string lineString |
queryResults("#select", i, 0, posString) and
filename = posString.substring(0, posString.indexOf(":", 0, 0)) and
lineString = posString.substring(posString.indexOf(":", 0, 0) + 1, posString.indexOf(":", 1, 0)) and
lineString = posString.substring(posString.indexOf(":", 2, 0) + 1, posString.indexOf(":", 3, 0)) and
colStart =
posString.substring(posString.indexOf(":", 1, 0) + 1, posString.indexOf(":", 2, 0)).toInt() and
colEnd = posString.substring(posString.indexOf(":", 3, 0) + 1, posString.length()).toInt() and
line = lineString.toInt() and
queryResults("#select", i, 2, content)
)
}

predicate actualExpectedDiff(string type, string position, string error) {
exists(string filename, int line, int colStart, int colEnd |
parsedActualResults(filename, line, colStart, colEnd, error) and
expectPass(filename, line) and
type = "unexpected alert" and
position = filename + ":" + line + ":" + colStart + ":" + line + ":" + colEnd
)
or
exists(string filename, int line |
expectError(filename, line) and
not parsedActualResults(filename, line, _, _, _) and
type = "expected alert" and
position = filename + ":" + line and
parsedExpectedResults(filename, line, error)
)
or
exists(string filename, int line, string content |
parsedExpectedResults(filename, line, content) and
not expectPass(filename, line) and
not expectError(filename, line) and
type = "invalid inline expectation" and
position = filename + ":" + line and
error = content
)
}

from int line, string position, int column, string content
where
position = rank[line](string p | actualExpectedDiff(_, p, _) | p) and
(
column = 0 and content = position
or
column = 1 and actualExpectedDiff(content, position, _)
or
column = 2 and actualExpectedDiff(_, position, content)
)
select "#select", line, column, content
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @kind test-postprocess
*/
module;

query predicate resultRelations(string name) { name = "#select" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @kind test-postprocess
*/
module;

query predicate learnEdits(string name) { none() }

select "#select", 1, 1, "foo"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @kind test-postprocess
*/
module;

query predicate extraQuery(string name) { none() }

select "#select", 1, 1, "foo"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @kind test-postprocess
*/
module;

query predicate resultRelations(string name, int arity) { name = "#select" and arity = 5 }

select "#select", 1, 1, "foo"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* @kind test-postprocess
*/

select "#select", "1", 1, "foo"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* @kind test-postprocess
*/

select "#select", 1, 1, ["foo", "bar"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* @kind test-postprocess
*/

from int i, int j
where
i in [1, 2] and
j in [1, 2] and
not (i = 2 and j = 2)
select "#select", i, j, "foo"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
select "#select", 1, 1, "foo"
17 changes: 17 additions & 0 deletions java/ql/test/TestUtilities/SinkModelNamespaceRoots.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @kind test-postprocess
*/

import semmle.code.java.dataflow.ExternalFlow

string sinkModuleNamespaceRoots() {
exists(string namespace, int dotIdx |
sinkModel(namespace, _, _, _, _, _, _, _, _, _) and
dotIdx = namespace.indexOf(".", 0, 0) and
result = namespace.substring(0, dotIdx)
)
}

from int line, string content
where content = rank[line](string c | c = sinkModuleNamespaceRoots() | c)
select "#select", line, 0, content
8 changes: 8 additions & 0 deletions java/ql/test/TestUtilities/TestResultSorting.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @kind test-postprocess
*/
query predicate resultRelations(string name) { name in ["B", "D", "F"] }

from int line, string name
where name = rank[line](string n | n in ["A", "C", "E"] | n)
select name, 0, 0, "empty"
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/TestResultSorting.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
| android |
| androidx |
| ch |
| com |
| freemarker |
| groovy |
| hudson |
| io |
| jakarta |
| java |
| javafx |
| javax |
| kotlin |
| liquibase |
| net |
| ognl |
| org |
| play |
| sun |
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/SinkModelNamespaceRoots.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/JavaInlineExpectations.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import java.util.regex.Pattern;

class SuspiciousRegexpRange {
void test() {
Pattern overlap1 = Pattern.compile("^[0-93-5]*$"); // NOT OK

Pattern overlap2 = Pattern.compile("[A-ZA-z]*"); // OK

Pattern isEmpty = Pattern.compile("^[z-a]*$"); // NOT OK

Pattern isAscii = Pattern.compile("^[\\x00-\\x7F]*$"); // NOT OK

Pattern printable = Pattern.compile("[!-~]*"); // OK - used to select most printable ASCII characters

Pattern codePoints = Pattern.compile("[^\\x21-\\x7E]|[[\\](){}<>/%]*"); // OK

Pattern NON_ALPHANUMERIC_REGEXP = Pattern.compile("([^\\#-~| |!])*"); // OK

Pattern smallOverlap = Pattern.compile("[0-9a-fA-f]*"); // NOT OK

Pattern weirdRange = Pattern.compile("[$-`]*"); // NOT OK

Pattern keywordOperator = Pattern.compile("[!\\~\\*\\/%+-<>\\^|=&]*"); // NOT OK

Pattern notYoutube = Pattern.compile("youtu.be/[a-z1-9.-_]+"); // NOT OK

Pattern numberToLetter = Pattern.compile("[7-F]*"); // NOT OK

Pattern overlapsWithClass1 = Pattern.compile("[0-9\\d]*"); // NOT OK

Pattern overlapsWithClass2 = Pattern.compile("[\\w,.-?:*+]*"); // NOT OK

Pattern nested = Pattern.compile("[[A-Za-z_][A-Za-z0-9._-]]*"); // OK, the dash it at the end

Pattern octal = Pattern.compile("[\000-\037\040-\045]*"); // OK
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/JavaInlineExpectations.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import java.util.regex.Pattern;

class SuspiciousRegexpRange {
void test() {
Pattern overlap1 = Pattern.compile("^[0-93-5]*$"); // NOT OK

Pattern overlap2 = Pattern.compile("[A-ZA-z]*"); // NOT OK

Pattern isEmpty = Pattern.compile("^[z-a]*$"); // NOT OK

Pattern isAscii = Pattern.compile("^[\\x00-\\x7F]*$"); // OK

Pattern printable = Pattern.compile("[!-~]*"); // OK - used to select most printable ASCII characters

Pattern codePoints = Pattern.compile("[^\\x21-\\x7E]|[[\\](){}<>/%]*"); // OK

Pattern NON_ALPHANUMERIC_REGEXP = Pattern.compile("([^\\#-~| |!])*"); // OK

Pattern smallOverlap = Pattern.compile("[0-9a-fA-f]*"); // NOT OK

Pattern weirdRange = Pattern.compile("[$-`]*"); // NOT OK

Pattern keywordOperator = Pattern.compile("[!\\~\\*\\/%+-<>\\^|=&]*"); // NOT OK

Pattern notYoutube = Pattern.compile("youtu.be/[a-z1-9.-_]+"); // NOT OK

Pattern numberToLetter = Pattern.compile("[7-F]*"); // NOT OK

Pattern overlapsWithClass1 = Pattern.compile("[0-9\\d]*"); // NOT OK

Pattern overlapsWithClass2 = Pattern.compile("[\\w,.-?:*+]*"); // NOT OK

Pattern nested = Pattern.compile("[[A-Za-z_][A-Za-z0-9._-]]*"); // OK, the dash it at the end

Pattern octal = Pattern.compile("[\000-\037\040-\045]*"); // OK
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
| SuspiciousRegexpRange.java:11 | expected alert | NOT OK |
| SuspiciousRegexpRange.java:7:49:7:51 | unexpected alert | Suspicious character range that overlaps with A-Z in the same character class, and is equivalent to [A-Z\\[\\\\\\]^_`a-z]. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/JavaInlineExpectations.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import java.util.regex.Pattern;

class SuspiciousRegexpRange {
void test() {
Pattern overlap1 = Pattern.compile("^[0-93-5]*$"); // NOT OK

Pattern overlap2 = Pattern.compile("[A-ZA-z]*"); // OK

Pattern isEmpty = Pattern.compile("^[z-a]*$"); // NOT OK

Pattern isAscii = Pattern.compile("^[\\x00-\\x7F]*$"); // NOT OK

Pattern printable = Pattern.compile("[!-~]*"); // OK - used to select most printable ASCII characters

Pattern codePoints = Pattern.compile("[^\\x21-\\x7E]|[[\\](){}<>/%]*"); // OK

Pattern NON_ALPHANUMERIC_REGEXP = Pattern.compile("([^\\#-~| |!])*"); // OK

Pattern smallOverlap = Pattern.compile("[0-9a-fA-f]*"); // NOT OK

Pattern weirdRange = Pattern.compile("[$-`]*"); // NOT OK

Pattern keywordOperator = Pattern.compile("[!\\~\\*\\/%+-<>\\^|=&]*"); // NOT OK

Pattern notYoutube = Pattern.compile("youtu.be/[a-z1-9.-_]+"); // NOT OK

Pattern numberToLetter = Pattern.compile("[7-F]*"); // NOT OK

Pattern overlapsWithClass1 = Pattern.compile("[0-9\\d]*"); // NOT OK

Pattern overlapsWithClass2 = Pattern.compile("[\\w,.-?:*+]*"); // NOT OK

Pattern nested = Pattern.compile("[[A-Za-z_][A-Za-z0-9._-]]*"); // OK, the dash it at the end

Pattern octal = Pattern.compile("[\000-\037\040-\045]*"); // OK
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| SuspiciousRegexpRange.java:13 | invalid inline expectation | IS OK - used to select most printable ASCII characters |
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/JavaInlineExpectations.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import java.util.regex.Pattern;

class SuspiciousRegexpRange {
void test() {
Pattern overlap1 = Pattern.compile("^[0-93-5]*$"); // NOT OK

Pattern overlap2 = Pattern.compile("[A-ZA-z]*"); // NOT OK

Pattern isEmpty = Pattern.compile("^[z-a]*$"); // NOT OK

Pattern isAscii = Pattern.compile("^[\\x00-\\x7F]*$"); // OK

Pattern printable = Pattern.compile("[!-~]*"); // IS OK - used to select most printable ASCII characters

Pattern codePoints = Pattern.compile("[^\\x21-\\x7E]|[[\\](){}<>/%]*"); // OK

Pattern NON_ALPHANUMERIC_REGEXP = Pattern.compile("([^\\#-~| |!])*"); // OK

Pattern smallOverlap = Pattern.compile("[0-9a-fA-f]*"); // NOT OK

Pattern weirdRange = Pattern.compile("[$-`]*"); // NOT OK

Pattern keywordOperator = Pattern.compile("[!\\~\\*\\/%+-<>\\^|=&]*"); // NOT OK

Pattern notYoutube = Pattern.compile("youtu.be/[a-z1-9.-_]+"); // NOT OK

Pattern numberToLetter = Pattern.compile("[7-F]*"); // NOT OK

Pattern overlapsWithClass1 = Pattern.compile("[0-9\\d]*"); // NOT OK

Pattern overlapsWithClass2 = Pattern.compile("[\\w,.-?:*+]*"); // NOT OK

Pattern nested = Pattern.compile("[[A-Za-z_][A-Za-z0-9._-]]*"); // OK, the dash it at the end

Pattern octal = Pattern.compile("[\000-\037\040-\045]*"); // OK
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/ProblematicJavaInlineExpectations1.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/ProblematicJavaInlineExpectations2.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/ProblematicJavaInlineExpectations3.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/ProblematicJavaInlineExpectations4.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/ProblematicJavaInlineExpectations5.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/ProblematicJavaInlineExpectations6.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/ProblematicJavaInlineExpectations7.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/ProblematicJavaInlineExpectations8.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
query: Security/CWE/CWE-020/OverlyLargeRange.ql
postprocess: TestUtilities/JavaInlineExpectations.ql
Loading
Loading