Skip to content

Commit 83c5673

Browse files
author
Max Schaefer
committed
Use inline expectations for negative-example tests as well.
1 parent 1ebd074 commit 83c5673

7 files changed

+87
-53
lines changed

java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,45 @@ predicate isCandidate(
397397
)
398398
}
399399

400+
/**
401+
* Holds if the given `endpoint` is a negative example for the `extensibleType`
402+
* because of the `characteristic`.
403+
*
404+
* The other parameters record various other properties of interest.
405+
*/
406+
predicate isNegativeExample(
407+
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package,
408+
string type, string subtypes, string name, string signature, string input, string output,
409+
string isVarargsArray, string extensibleType
410+
) {
411+
characteristic.appliesToEndpoint(endpoint) and
412+
// the node is known not to be an endpoint of any appropriate type
413+
forall(AutomodelEndpointTypes::EndpointType tp |
414+
tp = CharacteristicsImpl::getAPotentialType(endpoint)
415+
|
416+
characteristic.hasImplications(tp, false, _)
417+
) and
418+
// the lowest confidence across all endpoint types should be at least highConfidence
419+
confidence =
420+
min(float c |
421+
characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c)
422+
) and
423+
confidence >= SharedCharacteristics::highConfidence() and
424+
any(ApplicationModeMetadataExtractor meta)
425+
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output,
426+
isVarargsArray, _, extensibleType) and
427+
// It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes
428+
// as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here.
429+
not exists(EndpointCharacteristic characteristic2, float confidence2 |
430+
characteristic2 != characteristic
431+
|
432+
characteristic2.appliesToEndpoint(endpoint) and
433+
confidence2 >= SharedCharacteristics::maximalConfidence() and
434+
characteristic2
435+
.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2)
436+
)
437+
}
438+
400439
/*
401440
* EndpointCharacteristic classes that are specific to Automodel for Java.
402441
*/

java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -40,45 +40,15 @@ Endpoint getSampleForCharacteristic(EndpointCharacteristic c, int limit) {
4040
)
4141
}
4242

43-
predicate candidate(
44-
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package,
45-
string type, string subtypes, string name, string signature, string input, string output,
46-
string isVarargsArray, string extensibleType
47-
) {
48-
// the node is known not to be an endpoint of any appropriate type
49-
forall(EndpointType tp | tp = CharacteristicsImpl::getAPotentialType(endpoint) |
50-
characteristic.hasImplications(tp, false, _)
51-
) and
52-
// the lowest confidence across all endpoint types should be at least highConfidence
53-
confidence =
54-
min(float c |
55-
characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c)
56-
) and
57-
confidence >= SharedCharacteristics::highConfidence() and
58-
any(ApplicationModeMetadataExtractor meta)
59-
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output,
60-
isVarargsArray, _, extensibleType) and
61-
// It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes
62-
// as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here.
63-
not exists(EndpointCharacteristic characteristic2, float confidence2 |
64-
characteristic2 != characteristic
65-
|
66-
characteristic2.appliesToEndpoint(endpoint) and
67-
confidence2 >= SharedCharacteristics::maximalConfidence() and
68-
characteristic2
69-
.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2)
70-
)
71-
}
72-
7343
from
7444
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message,
7545
DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name,
7646
DollarAtString signature, DollarAtString input, DollarAtString output,
7747
DollarAtString isVarargsArray, DollarAtString extensibleType
7848
where
7949
endpoint = getSampleForCharacteristic(characteristic, 100) and
80-
candidate(endpoint, characteristic, confidence, package, type, subtypes, name, signature, input,
81-
output, isVarargsArray, extensibleType) and
50+
isNegativeExample(endpoint, characteristic, confidence, package, type, subtypes, name, signature,
51+
input, output, isVarargsArray, extensibleType) and
8252
message = characteristic
8353
select endpoint.asNode(),
8454
message + "\nrelated locations: $@, $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
| Test.java:49:4:49:5 | f2 | known non-sink\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:48:10:50:3 | compareTo(...) | CallContext | Test.java:49:4:49:5 | f2 | MethodDoc | Test.java:49:4:49:5 | f2 | 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://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
2-
| Test.java:55:4:55:4 | p | taint step\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:55:4:55:4 | p | MethodDoc | Test.java:55:4:55:4 | p | 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://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
3-
| Test.java:94:3:96:3 | deleteIfExists(...) | known sanitizer\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:94:3:96:3 | deleteIfExists(...) | CallContext | Test.java:94:3:96:3 | deleteIfExists(...) | MethodDoc | Test.java:94:3:96:3 | deleteIfExists(...) | 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://deleteIfExists:1:1:1:1 | deleteIfExists | name | file://(Path):1:1:1:1 | (Path) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
1+
testFailures
2+
failures
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import java
2+
import AutomodelApplicationModeCharacteristics
3+
import TestUtilities.InlineExpectationsTest
4+
5+
module NegativeExampleTest implements TestSig {
6+
string getARelevantTag() { result = "negativeExample" }
7+
8+
predicate hasActualResult(Location location, string element, string tag, string value) {
9+
exists(
10+
Endpoint endpoint, string name, string signature, string input,
11+
string output, string extensibleType
12+
|
13+
isNegativeExample(endpoint, _, _, _, _, _, name, signature, input, output, _,
14+
extensibleType)
15+
|
16+
endpoint.asTop().getLocation() = location and
17+
endpoint.toString() = element and
18+
tag = "negativeExample" and
19+
// for source models only the output is relevant, and vice versa for sink models
20+
if extensibleType = "sourceModel"
21+
then value = name + signature + ":" + output
22+
else value = name + signature + ":" + input
23+
)
24+
}
25+
}
26+
27+
import MakeTest<NegativeExampleTest>

java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.qlref

Lines changed: 0 additions & 1 deletion
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
| Test.java:29:4:29:9 | source | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:29:4:29:9 | source | MethodDoc | Test.java:29:4:29:9 | 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,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
2-
| Test.java:30:4:30:9 | target | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:30:4:30:9 | target | MethodDoc | Test.java:30:4:30:9 | target | 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,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
3-
| Test.java:37:4:37:11 | openPath | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:37:4:37:11 | openPath | MethodDoc | Test.java:37:4:37:11 | openPath | 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://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 | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
4-
| Test.java:63:3:63:20 | getInputStream(...) | remote\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:63:3:63:20 | getInputStream(...) | CallContext | Test.java:63:3:63:20 | getInputStream(...) | MethodDoc | Test.java:63:3:63:20 | getInputStream(...) | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
5-
| Test.java:87:28:87:28 | p | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:87:4:87:29 | createDirectories(...) | CallContext | Test.java:87:28:87:28 | p | MethodDoc | Test.java:87:28:87:28 | p | 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://createDirectories:1:1:1:1 | createDirectories | name | file://(Path,FileAttribute[]):1:1:1:1 | (Path,FileAttribute[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
6-
| Test.java:91:4:91:4 | p | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:90:3:92:3 | delete(...) | CallContext | Test.java:91:4:91:4 | p | MethodDoc | Test.java:91:4:91:4 | p | 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://delete:1:1:1:1 | delete | name | file://(Path):1:1:1:1 | (Path) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
7-
| Test.java:95:4:95:4 | p | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:94:3:96:3 | deleteIfExists(...) | CallContext | Test.java:95:4:95:4 | p | MethodDoc | Test.java:95:4:95:4 | p | 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://deleteIfExists:1:1:1:1 | deleteIfExists | name | file://(Path):1:1:1:1 | (Path) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
1+
| Test.java:30:4:30:9 | source | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:29:3:33:3 | copy(...) | CallContext | Test.java:30:4:30:9 | source | MethodDoc | Test.java:30:4:30:9 | 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,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
2+
| Test.java:31:4:31:9 | target | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:29:3:33:3 | copy(...) | CallContext | Test.java:31:4:31:9 | target | MethodDoc | Test.java:31:4:31:9 | target | 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,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
3+
| Test.java:38:4:38:11 | openPath | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:37:10:39:3 | newInputStream(...) | CallContext | Test.java:38:4:38:11 | openPath | MethodDoc | Test.java:38:4:38:11 | openPath | 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://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 | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
4+
| Test.java:66:3:66:20 | getInputStream(...) | remote\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:66:3:66:20 | getInputStream(...) | CallContext | Test.java:66:3:66:20 | getInputStream(...) | MethodDoc | Test.java:66:3:66:20 | getInputStream(...) | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
5+
| Test.java:90:28:90:28 | p | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:90:4:90:29 | createDirectories(...) | CallContext | Test.java:90:28:90:28 | p | MethodDoc | Test.java:90:28:90:28 | p | 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://createDirectories:1:1:1:1 | createDirectories | name | file://(Path,FileAttribute[]):1:1:1:1 | (Path,FileAttribute[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
6+
| Test.java:94:4:94:4 | p | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:93:3:95:3 | delete(...) | CallContext | Test.java:94:4:94:4 | p | MethodDoc | Test.java:94:4:94:4 | p | 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://delete:1:1:1:1 | delete | name | file://(Path):1:1:1:1 | (Path) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
7+
| Test.java:98:4:98:4 | p | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:97:3:99:3 | deleteIfExists(...) | CallContext | Test.java:98:4:98:4 | p | MethodDoc | Test.java:98:4:98:4 | p | 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://deleteIfExists:1:1:1:1 | deleteIfExists | name | file://(Path):1:1:1:1 | (Path) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |

0 commit comments

Comments
 (0)