mirror of
https://github.com/github/codeql.git
synced 2025-12-21 19:26:31 +01:00
Merge pull request #13788 from github/kaeluka/automodel-telemetry-testing
Java: Tests for Automodel Extraction Queries
This commit is contained in:
@@ -56,7 +56,7 @@ abstract class FrameworkModeEndpoint extends TFrameworkModeEndpoint {
|
|||||||
class ExplicitParameterEndpoint extends FrameworkModeEndpoint, TExplicitParameter {
|
class ExplicitParameterEndpoint extends FrameworkModeEndpoint, TExplicitParameter {
|
||||||
Parameter param;
|
Parameter param;
|
||||||
|
|
||||||
ExplicitParameterEndpoint() { this = TExplicitParameter(param) }
|
ExplicitParameterEndpoint() { this = TExplicitParameter(param) and param.fromSource() }
|
||||||
|
|
||||||
override int getIndex() { result = param.getPosition() }
|
override int getIndex() { result = param.getPosition() }
|
||||||
|
|
||||||
@@ -70,7 +70,9 @@ class ExplicitParameterEndpoint extends FrameworkModeEndpoint, TExplicitParamete
|
|||||||
class QualifierEndpoint extends FrameworkModeEndpoint, TQualifier {
|
class QualifierEndpoint extends FrameworkModeEndpoint, TQualifier {
|
||||||
Callable callable;
|
Callable callable;
|
||||||
|
|
||||||
QualifierEndpoint() { this = TQualifier(callable) }
|
QualifierEndpoint() {
|
||||||
|
this = TQualifier(callable) and not callable.isStatic() and callable.fromSource()
|
||||||
|
}
|
||||||
|
|
||||||
override int getIndex() { result = -1 }
|
override int getIndex() { result = -1 }
|
||||||
|
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ module SharedCharacteristics<CandidateSig Candidate> {
|
|||||||
* analyzed.
|
* analyzed.
|
||||||
*/
|
*/
|
||||||
private class IsSanitizerCharacteristic extends NotASinkCharacteristic {
|
private class IsSanitizerCharacteristic extends NotASinkCharacteristic {
|
||||||
IsSanitizerCharacteristic() { this = "external" }
|
IsSanitizerCharacteristic() { this = "known sanitizer" }
|
||||||
|
|
||||||
override predicate appliesToEndpoint(Candidate::Endpoint e) { Candidate::isSanitizer(e, _) }
|
override predicate appliesToEndpoint(Candidate::Endpoint e) { Candidate::isSanitizer(e, _) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
| Test.java:16:3:16:11 | reference | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:16:3:16:24 | set(...) | CallContext | file://java.util.concurrent.atomic:1:1:1:1 | java.util.concurrent.atomic | package | file://AtomicReference:1:1:1:1 | AtomicReference | type | file://false:1:1:1:1 | false | subtypes | file://set:1:1:1:1 | set | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input |
|
||||||
|
| Test.java:21:3:21:10 | supplier | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:21:3:21:16 | get(...) | CallContext | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Telemetry/AutomodelApplicationModeExtractCandidates.ql
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
| Test.java:40:14:40:21 | openPath | taint step\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:40:4:40:22 | get(...) | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Paths:1:1:1:1 | Paths | type | file://false:1:1:1:1 | false | subtypes | file://get:1:1:1:1 | get | name | file://(String,String[]):1:1:1:1 | (String,String[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input |
|
||||||
|
| Test.java:46:4:46:5 | f2 | known non-sink\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:45:10:47:3 | compareTo(...) | CallContext | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Telemetry/AutomodelApplicationModeExtractNegativeExamples.ql
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
| Test.java:26:4:26:9 | source | path-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:25:3:29:3 | copy(...) | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input |
|
||||||
|
| Test.java:27:4:27:9 | target | path-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:25:3:29:3 | copy(...) | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input |
|
||||||
|
| Test.java:34:4:34:11 | openPath | path-injection\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@. | Test.java:33:10:35:3 | newInputStream(...) | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Telemetry/AutomodelApplicationModeExtractPositiveExamples.ql
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.github.codeql.test;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.CopyOption;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
AtomicReference<String> reference = new AtomicReference<>(); // uninteresting (parameterless constructor)
|
||||||
|
reference.set(args[0]); // arg[0] is not a candidate (modeled as value flow step)
|
||||||
|
// ^^^^^^ Argument[this] is a candidate
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void callSupplier(Supplier<String> supplier) {
|
||||||
|
supplier.get(); // Argument[this] is a candidate
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void copyFiles(Path source, Path target, CopyOption option) throws Exception {
|
||||||
|
Files.copy(
|
||||||
|
source, // positive example (known sink)
|
||||||
|
target, // positive example (known sink)
|
||||||
|
option // no candidate (not modeled, but source and target are modeled)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InputStream getInputStream(Path openPath) throws Exception {
|
||||||
|
return Files.newInputStream(
|
||||||
|
openPath // positive example (known sink)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InputStream getInputStream(String openPath) throws Exception {
|
||||||
|
return Test.getInputStream(
|
||||||
|
Paths.get(openPath) // no candidate (argument to local call)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int compareFiles(File f1, File f2) {
|
||||||
|
return f1.compareTo(
|
||||||
|
f2 // negative example (modeled as not a sink)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
| com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | MethodDoc | com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://this:1:1:1:1 | this | parameterName |
|
||||||
|
| com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName |
|
||||||
|
| com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://false:1:1:1:1 | false | subtypes | file://staticStuff:1:1:1:1 | staticStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName |
|
||||||
|
| com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:17:4:21 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://this:1:1:1:1 | this | parameterName |
|
||||||
|
| com/github/codeql/test/PublicInterface.java:4:23:4:32 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:23:4:32 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:4:23:4:32 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName |
|
||||||
|
| com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://false:1:1:1:1 | false | subtypes | file://staticStuff:1:1:1:1 | staticStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://arg:1:1:1:1 | arg | parameterName |
|
||||||
|
| java/nio/file/Files.java:10:9:10:24 | out | command-injection, path-injection, request-forgery, sql-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:10:9:10:24 | out | MethodDoc | java/nio/file/Files.java:10:9:10:24 | out | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,OutputStream):1:1:1:1 | (Path,OutputStream) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://out:1:1:1:1 | out | parameterName |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Telemetry/AutomodelFrameworkModeExtractCandidates.ql
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
| java/io/File.java:4:9:4:17 | compareTo | known non-sink\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:4:9:4:17 | compareTo | MethodDoc | java/io/File.java:4:9:4:17 | compareTo | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://this:1:1:1:1 | this | parameterName |
|
||||||
|
| java/io/File.java:5:9:5:21 | pathname | known non-sink\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:5:9:5:21 | pathname | MethodDoc | java/io/File.java:5:9:5:21 | pathname | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://pathname:1:1:1:1 | pathname | parameterName |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
| java/nio/file/Files.java:9:9:9:19 | source | path-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:9:9:9:19 | source | MethodDoc | java/nio/file/Files.java:9:9:9:19 | source | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,OutputStream):1:1:1:1 | (Path,OutputStream) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://source:1:1:1:1 | source | parameterName |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.github.codeql.test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No candidates in this class, as it's not public!
|
||||||
|
*/
|
||||||
|
class NonPublicClass {
|
||||||
|
public void noCandidates(String here) {
|
||||||
|
System.out.println(here);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.github.codeql.test;
|
||||||
|
|
||||||
|
public class PublicClass {
|
||||||
|
public void stuff(String arg) { // `arg` is a candidate, `this` is a candidate
|
||||||
|
System.out.println(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void staticStuff(String arg) { // `arg` is a candidate, `this` is not a candidate (static method)
|
||||||
|
System.out.println(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// `arg` and `this` are not a candidate because the method is not public:
|
||||||
|
protected void nonPublicStuff(String arg) {
|
||||||
|
System.out.println(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// `arg` and `this are not candidates because the method is not public:
|
||||||
|
void packagePrivateStuff(String arg) {
|
||||||
|
System.out.println(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.github.codeql.test;
|
||||||
|
|
||||||
|
public interface PublicInterface {
|
||||||
|
public void stuff(String arg); // `arg` is a candidate, `this` is a candidate
|
||||||
|
|
||||||
|
public static void staticStuff(String arg) { // `arg` is a candidate, `this` is not a candidate (static method)
|
||||||
|
System.out.println(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package java.io;
|
||||||
|
|
||||||
|
public class File {
|
||||||
|
int compareTo( // `this` is a negative example - this is modeled as a neutral model
|
||||||
|
File pathname // negative example - this is modeled as a neutral model
|
||||||
|
) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package java.nio.file;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class Files {
|
||||||
|
public static void copy(
|
||||||
|
Path source, // a positive example because a manual model exists
|
||||||
|
OutputStream out /* a candidate. NB: may be worthwhile to implement the
|
||||||
|
same behavior as in application mode where out would not be a
|
||||||
|
candidate because there already is a model for another parameter of
|
||||||
|
the same method and we assume that methods are always modeled
|
||||||
|
completely.
|
||||||
|
*/
|
||||||
|
) throws IOException {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user