diff --git a/java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll b/java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll index 44d74a5565f6..6c68c5b6359b 100644 --- a/java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll +++ b/java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll @@ -239,13 +239,12 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig // Sanitizers are currently not modeled in MaD. TODO: check if this has large negative impact. predicate isSanitizer(Endpoint e, EndpointType t) { exists(t) and - ( - e.asNode().getType() instanceof BoxedType - or - e.asNode().getType() instanceof PrimitiveType - or - e.asNode().getType() instanceof NumberType - ) + AutomodelJavaUtil::isUnexploitableType([ + // for most endpoints, we can get the type from the node + e.asNode().getType(), + // but not for calls to void methods, where we need to go via the AST + e.asTop().(Expr).getType() + ]) or t instanceof AutomodelEndpointTypes::PathInjectionSinkType and e.asNode() instanceof PathSanitizer::PathInjectionSanitizer @@ -372,13 +371,92 @@ class ApplicationModeMetadataExtractor extends string { } } +/** + * Holds if the given `endpoint` should be considered a candidate for the `extensibleType`. + * + * The other parameters record various other properties of interest. + */ +predicate isCandidate( + Endpoint endpoint, string package, string type, string subtypes, string name, string signature, + string input, string output, string isVarargs, string extensibleType, string alreadyAiModeled +) { + CharacteristicsImpl::isCandidate(endpoint, _) and + not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u | + u.appliesToEndpoint(endpoint) + ) and + any(ApplicationModeMetadataExtractor meta) + .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, isVarargs, + alreadyAiModeled, extensibleType) and + // If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a + // candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's + // already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We + // assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink + // types, and we don't need to reexamine it. + alreadyAiModeled.matches(["", "%ai-%"]) and + AutomodelJavaUtil::includeAutomodelCandidate(package, type, name, signature) +} + +/** + * Holds if the given `endpoint` is a negative example for the `extensibleType` + * because of the `characteristic`. + * + * The other parameters record various other properties of interest. + */ +predicate isNegativeExample( + Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package, + string type, string subtypes, string name, string signature, string input, string output, + string isVarargsArray, string extensibleType +) { + characteristic.appliesToEndpoint(endpoint) and + // the node is known not to be an endpoint of any appropriate type + forall(AutomodelEndpointTypes::EndpointType tp | + tp = CharacteristicsImpl::getAPotentialType(endpoint) + | + characteristic.hasImplications(tp, false, _) + ) and + // the lowest confidence across all endpoint types should be at least highConfidence + confidence = + min(float c | + characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c) + ) and + confidence >= SharedCharacteristics::highConfidence() and + any(ApplicationModeMetadataExtractor meta) + .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, + isVarargsArray, _, extensibleType) and + // It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes + // as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here. + not exists(EndpointCharacteristic characteristic2, float confidence2 | + characteristic2 != characteristic + | + characteristic2.appliesToEndpoint(endpoint) and + confidence2 >= SharedCharacteristics::maximalConfidence() and + characteristic2 + .hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2) + ) +} + +/** + * Holds if the given `endpoint` is a positive example for the `endpointType`. + * + * The other parameters record various other properties of interest. + */ +predicate isPositiveExample( + Endpoint endpoint, string endpointType, string package, string type, string subtypes, string name, + string signature, string input, string output, string isVarargsArray, string extensibleType +) { + any(ApplicationModeMetadataExtractor meta) + .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, + isVarargsArray, _, extensibleType) and + CharacteristicsImpl::isKnownAs(endpoint, endpointType, _) and + exists(CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext())) +} + /* * EndpointCharacteristic classes that are specific to Automodel for Java. */ /** - * A negative characteristic that indicates that parameters of an is-style boolean method should not be considered sinks, - * and its return value should not be considered a source. + * A negative characteristic that indicates that parameters of an is-style boolean method should not be considered sinks. * * A sink is highly unlikely to be exploitable if its callable's name starts with `is` and the callable has a boolean return * type (e.g. `isDirectory`). These kinds of calls normally do only checks, and appear before the proper call that does @@ -386,48 +464,31 @@ class ApplicationModeMetadataExtractor extends string { * * TODO: this might filter too much, it's possible that methods with more than one parameter contain interesting sinks */ -private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic -{ +private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic { UnexploitableIsCharacteristic() { this = "unexploitable (is-style boolean method)" } override predicate appliesToEndpoint(Endpoint e) { e.getCallable().getName().matches("is%") and e.getCallable().getReturnType() instanceof BooleanType and - ( - e.getExtensibleType() = "sinkModel" and - not ApplicationCandidatesImpl::isSink(e, _, _) - or - e.getExtensibleType() = "sourceModel" and - not ApplicationCandidatesImpl::isSource(e, _, _) and - e.getMaDOutput() = "ReturnValue" - ) + not ApplicationCandidatesImpl::isSink(e, _, _) } } /** * A negative characteristic that indicates that parameters of an existence-checking boolean method should not be - * considered sinks, and its return value should not be considered a source. + * considered sinks. * * A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a * boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the * dangerous/interesting thing, so we want the latter to be modeled as the sink. */ -private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic -{ +private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic { UnexploitableExistsCharacteristic() { this = "unexploitable (existence-checking boolean method)" } override predicate appliesToEndpoint(Endpoint e) { - exists(Callable callable | - callable = e.getCallable() and + exists(Callable callable | callable = e.getCallable() | callable.getName().toLowerCase() = ["exists", "notexists"] and callable.getReturnType() instanceof BooleanType - | - e.getExtensibleType() = "sinkModel" and - not ApplicationCandidatesImpl::isSink(e, _, _) - or - e.getExtensibleType() = "sourceModel" and - not ApplicationCandidatesImpl::isSource(e, _, _) and - e.getMaDOutput() = "ReturnValue" ) } } diff --git a/java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql b/java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql index e3384a52bb8d..a3fa8b9b46fa 100644 --- a/java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql +++ b/java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql @@ -55,27 +55,15 @@ private Endpoint getSampleForSignature( } from - Endpoint endpoint, ApplicationModeMetadataExtractor meta, DollarAtString package, - DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature, - DollarAtString input, DollarAtString output, DollarAtString isVarargsArray, - DollarAtString alreadyAiModeled, DollarAtString extensibleType + Endpoint endpoint, DollarAtString package, DollarAtString type, DollarAtString subtypes, + DollarAtString name, DollarAtString signature, DollarAtString input, DollarAtString output, + DollarAtString isVarargsArray, DollarAtString alreadyAiModeled, DollarAtString extensibleType where - not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u | - u.appliesToEndpoint(endpoint) - ) and - CharacteristicsImpl::isCandidate(endpoint, _) and + isCandidate(endpoint, package, type, subtypes, name, signature, input, output, isVarargsArray, + extensibleType, alreadyAiModeled) and endpoint = getSampleForSignature(9, package, type, subtypes, name, signature, input, output, - isVarargsArray, extensibleType, alreadyAiModeled) and - meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, - isVarargsArray, alreadyAiModeled, extensibleType) and - // If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a - // candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's - // already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We - // assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink - // types, and we don't need to reexamine it. - alreadyAiModeled.matches(["", "%ai-%"]) and - includeAutomodelCandidate(package, type, name, signature) + isVarargsArray, extensibleType, alreadyAiModeled) select endpoint.asNode(), "Related locations: $@, $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@.", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", // diff --git a/java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql b/java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql index f4ee90331f69..a399c413fa4a 100644 --- a/java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql +++ b/java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql @@ -40,36 +40,6 @@ Endpoint getSampleForCharacteristic(EndpointCharacteristic c, int limit) { ) } -predicate candidate( - Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package, - string type, string subtypes, string name, string signature, string input, string output, - string isVarargsArray, string extensibleType -) { - // the node is known not to be an endpoint of any appropriate type - forall(EndpointType tp | tp = CharacteristicsImpl::getAPotentialType(endpoint) | - characteristic.hasImplications(tp, false, _) - ) and - // the lowest confidence across all endpoint types should be at least highConfidence - confidence = - min(float c | - characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c) - ) and - confidence >= SharedCharacteristics::highConfidence() and - any(ApplicationModeMetadataExtractor meta) - .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, - isVarargsArray, _, extensibleType) and - // It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes - // as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here. - not exists(EndpointCharacteristic characteristic2, float confidence2 | - characteristic2 != characteristic - | - characteristic2.appliesToEndpoint(endpoint) and - confidence2 >= SharedCharacteristics::maximalConfidence() and - characteristic2 - .hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2) - ) -} - from Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message, DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name, @@ -77,8 +47,8 @@ from DollarAtString isVarargsArray, DollarAtString extensibleType where endpoint = getSampleForCharacteristic(characteristic, 100) and - candidate(endpoint, characteristic, confidence, package, type, subtypes, name, signature, input, - output, isVarargsArray, extensibleType) and + isNegativeExample(endpoint, characteristic, confidence, package, type, subtypes, name, signature, + input, output, isVarargsArray, extensibleType) and message = characteristic select endpoint.asNode(), message + "\nrelated locations: $@, $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", // diff --git a/java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql b/java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql index 8702e6808a45..faf49b73fc14 100644 --- a/java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql +++ b/java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql @@ -18,10 +18,8 @@ from DollarAtString signature, DollarAtString input, DollarAtString output, DollarAtString isVarargsArray, DollarAtString extensibleType where - meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, - isVarargsArray, _, extensibleType) and - CharacteristicsImpl::isKnownAs(endpoint, endpointType, _) and - exists(CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext())) + isPositiveExample(endpoint, endpointType, package, type, subtypes, name, signature, input, output, + isVarargsArray, extensibleType) select endpoint.asNode(), endpointType + "\nrelated locations: $@, $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", // diff --git a/java/ql/automodel/src/AutomodelFrameworkModeCharacteristics.qll b/java/ql/automodel/src/AutomodelFrameworkModeCharacteristics.qll index a47e470b4a18..6981e0369b51 100644 --- a/java/ql/automodel/src/AutomodelFrameworkModeCharacteristics.qll +++ b/java/ql/automodel/src/AutomodelFrameworkModeCharacteristics.qll @@ -25,9 +25,7 @@ newtype JavaRelatedLocationType = newtype TFrameworkModeEndpoint = TExplicitParameter(Parameter p) { AutomodelJavaUtil::isFromSource(p) and - not p.getType() instanceof PrimitiveType and - not p.getType() instanceof BoxedType and - not p.getType() instanceof NumberType + not AutomodelJavaUtil::isUnexploitableType(p.getType()) } or TQualifier(Callable c) { AutomodelJavaUtil::isFromSource(c) and not c instanceof Constructor } or TReturnValue(Callable c) { @@ -36,25 +34,19 @@ newtype TFrameworkModeEndpoint = or AutomodelJavaUtil::isFromSource(c) and c instanceof Method and - ( - not c.getReturnType() instanceof VoidType and - not c.getReturnType() instanceof PrimitiveType - ) + not AutomodelJavaUtil::isUnexploitableType(c.getReturnType()) } or TOverridableParameter(Method m, Parameter p) { AutomodelJavaUtil::isFromSource(p) and + not AutomodelJavaUtil::isUnexploitableType(p.getType()) and p.getCallable() = m and m instanceof ModelExclusions::ModelApi and - not m.getDeclaringType().isFinal() and - not m.isFinal() and - not m.isStatic() + AutomodelJavaUtil::isOverridable(m) } or TOverridableQualifier(Method m) { AutomodelJavaUtil::isFromSource(m) and m instanceof ModelExclusions::ModelApi and - not m.getDeclaringType().isFinal() and - not m.isFinal() and - not m.isStatic() + AutomodelJavaUtil::isOverridable(m) } /** @@ -317,6 +309,85 @@ class FrameworkModeMetadataExtractor extends string { } } +/** + * Holds if the given `endpoint` should be considered a candidate for the `extensibleType`. + * + * The other parameters record various other properties of interest. + */ +predicate isCandidate( + Endpoint endpoint, string package, string type, string subtypes, string name, string signature, + string input, string output, string parameterName, string extensibleType, string alreadyAiModeled +) { + CharacteristicsImpl::isCandidate(endpoint, _) and + not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u | + u.appliesToEndpoint(endpoint) + ) and + any(FrameworkModeMetadataExtractor meta) + .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName, + alreadyAiModeled, extensibleType) and + // If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a + // candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's + // already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We + // assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink + // types, and we don't need to reexamine it. + alreadyAiModeled.matches(["", "%ai-%"]) and + AutomodelJavaUtil::includeAutomodelCandidate(package, type, name, signature) +} + +/** + * Holds if the given `endpoint` is a negative example for the `extensibleType` + * because of the `characteristic`. + * + * The other parameters record various other properties of interest. + */ +predicate isNegativeExample( + Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package, + string type, string subtypes, string name, string signature, string input, string output, + string parameterName, string extensibleType +) { + characteristic.appliesToEndpoint(endpoint) and + // the node is known not to be an endpoint of any appropriate type + forall(AutomodelEndpointTypes::EndpointType tp | + tp = CharacteristicsImpl::getAPotentialType(endpoint) + | + characteristic.hasImplications(tp, false, _) + ) and + // the lowest confidence across all endpoint types should be at least highConfidence + confidence = + min(float c | + characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c) + ) and + confidence >= SharedCharacteristics::highConfidence() and + any(FrameworkModeMetadataExtractor meta) + .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName, + _, extensibleType) and + // It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes + // as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here. + not exists(EndpointCharacteristic characteristic2, float confidence2 | + characteristic2 != characteristic + | + characteristic2.appliesToEndpoint(endpoint) and + confidence2 >= SharedCharacteristics::maximalConfidence() and + characteristic2 + .hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2) + ) +} + +/** + * Holds if the given `endpoint` is a positive example for the `endpointType`. + * + * The other parameters record various other properties of interest. + */ +predicate isPositiveExample( + Endpoint endpoint, string endpointType, string package, string type, string subtypes, string name, + string signature, string input, string output, string parameterName, string extensibleType +) { + any(FrameworkModeMetadataExtractor meta) + .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName, + _, extensibleType) and + CharacteristicsImpl::isKnownAs(endpoint, endpointType, _) +} + /* * EndpointCharacteristic classes that are specific to Automodel for Java. */ diff --git a/java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql b/java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql index 80f3d3089c07..83683b4e78f5 100644 --- a/java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql +++ b/java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql @@ -16,24 +16,12 @@ private import AutomodelFrameworkModeCharacteristics private import AutomodelJavaUtil from - Endpoint endpoint, FrameworkModeMetadataExtractor meta, DollarAtString package, - DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature, - DollarAtString input, DollarAtString output, DollarAtString parameterName, - DollarAtString alreadyAiModeled, DollarAtString extensibleType + Endpoint endpoint, DollarAtString package, DollarAtString type, DollarAtString subtypes, + DollarAtString name, DollarAtString signature, DollarAtString input, DollarAtString output, + DollarAtString parameterName, DollarAtString alreadyAiModeled, DollarAtString extensibleType where - not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u | - u.appliesToEndpoint(endpoint) - ) and - CharacteristicsImpl::isCandidate(endpoint, _) and - meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName, - alreadyAiModeled, extensibleType) and - // If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a - // candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's - // already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We - // assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink - // types, and we don't need to reexamine it. - alreadyAiModeled.matches(["", "%ai-%"]) and - includeAutomodelCandidate(package, type, name, signature) + isCandidate(endpoint, package, type, subtypes, name, signature, input, output, parameterName, + extensibleType, alreadyAiModeled) select endpoint, "Related locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@.", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // diff --git a/java/ql/automodel/src/AutomodelFrameworkModeExtractNegativeExamples.ql b/java/ql/automodel/src/AutomodelFrameworkModeExtractNegativeExamples.ql index dc9f61ab49c0..05e5951b0610 100644 --- a/java/ql/automodel/src/AutomodelFrameworkModeExtractNegativeExamples.ql +++ b/java/ql/automodel/src/AutomodelFrameworkModeExtractNegativeExamples.ql @@ -14,37 +14,15 @@ private import AutomodelJavaUtil from Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, - DollarAtString message, FrameworkModeMetadataExtractor meta, DollarAtString package, - DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature, - DollarAtString input, DollarAtString output, DollarAtString parameterName, - DollarAtString extensibleType + DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name, + DollarAtString signature, DollarAtString input, DollarAtString output, + DollarAtString parameterName, DollarAtString extensibleType where - characteristic.appliesToEndpoint(endpoint) and - // the node is known not to be an endpoint of any appropriate type - forall(EndpointType tp | tp = CharacteristicsImpl::getAPotentialType(endpoint) | - characteristic.hasImplications(tp, false, _) - ) and - // the lowest confidence across all endpoint types should be at least highConfidence - confidence = - min(float c | - characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c) - ) and - confidence >= SharedCharacteristics::highConfidence() and - meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName, - _, extensibleType) and - // It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes - // as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here. - not exists(EndpointCharacteristic characteristic2, float confidence2 | - characteristic2 != characteristic - | - characteristic2.appliesToEndpoint(endpoint) and - confidence2 >= SharedCharacteristics::maximalConfidence() and - characteristic2 - .hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2) - ) and - message = characteristic + isNegativeExample(endpoint, characteristic, confidence, package, type, subtypes, name, signature, + input, output, parameterName, extensibleType) select endpoint, - message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", // + characteristic + "\nrelated locations: $@, $@." + + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // package, "package", // diff --git a/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql b/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql index d83ac04c5824..7cb023949ed9 100644 --- a/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql +++ b/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql @@ -13,14 +13,12 @@ private import AutomodelEndpointTypes private import AutomodelJavaUtil from - Endpoint endpoint, EndpointType endpointType, FrameworkModeMetadataExtractor meta, - DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name, - DollarAtString signature, DollarAtString input, DollarAtString output, - DollarAtString parameterName, DollarAtString extensibleType + Endpoint endpoint, EndpointType endpointType, DollarAtString package, DollarAtString type, + DollarAtString subtypes, DollarAtString name, DollarAtString signature, DollarAtString input, + DollarAtString output, DollarAtString parameterName, DollarAtString extensibleType where - meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName, - _, extensibleType) and - CharacteristicsImpl::isKnownAs(endpoint, endpointType, _) + isPositiveExample(endpoint, endpointType, package, type, subtypes, name, signature, input, output, + parameterName, extensibleType) select endpoint, endpointType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", // CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // diff --git a/java/ql/automodel/src/AutomodelJavaUtil.qll b/java/ql/automodel/src/AutomodelJavaUtil.qll index e1a1d36c1a0c..ba42806e9539 100644 --- a/java/ql/automodel/src/AutomodelJavaUtil.qll +++ b/java/ql/automodel/src/AutomodelJavaUtil.qll @@ -100,3 +100,25 @@ predicate isFromSource(Element e) { // does not have a dummy location not e.hasLocationInfo(_, 0, 0, 0, 0) } + +/** + * Holds if taint cannot flow through the given type (because it is a numeric + * type or some other type with a fixed set of values). + */ +predicate isUnexploitableType(Type tp) { + tp instanceof PrimitiveType or + tp instanceof BoxedType or + tp instanceof NumberType or + tp instanceof VoidType +} + +/** + * Holds if the given method can be overridden, that is, it is not final, + * static, or private. + */ +predicate isOverridable(Method m) { + not m.getDeclaringType().isFinal() and + not m.isFinal() and + not m.isStatic() and + not m.isPrivate() +} diff --git a/java/ql/automodel/src/AutomodelSharedCharacteristics.qll b/java/ql/automodel/src/AutomodelSharedCharacteristics.qll index 5641a5346607..273c5d30dec9 100644 --- a/java/ql/automodel/src/AutomodelSharedCharacteristics.qll +++ b/java/ql/automodel/src/AutomodelSharedCharacteristics.qll @@ -21,6 +21,11 @@ signature module CandidateSig { * Gets the kind of this endpoint, either "sourceModel" or "sinkModel". */ string getExtensibleType(); + + /** + * Gets a string representation of this endpoint. + */ + string toString(); } /** diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.expected b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.expected deleted file mode 100644 index 41598f8858cb..000000000000 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.expected +++ /dev/null @@ -1,15 +0,0 @@ -| PluginImpl.java:5:27:5:37 | name | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | PluginImpl.java:5:27:5:37 | name | CallContext | hudson/Plugin.java:5:5:5:31 | /** Configure method doc */ | MethodDoc | hudson/Plugin.java:3:1:3:17 | /** Plugin doc */ | ClassDoc | file://hudson:1:1:1:1 | hudson | package | file://Plugin:1:1:1:1 | Plugin | type | file://true:1:1:1:1 | true | subtypes | file://configure:1:1:1:1 | configure | name | file://(String,String):1:1:1:1 | (String,String) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| PluginImpl.java:5:40:5:51 | value | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | PluginImpl.java:5:40:5:51 | value | CallContext | hudson/Plugin.java:5:5:5:31 | /** Configure method doc */ | MethodDoc | hudson/Plugin.java:3:1:3:17 | /** Plugin doc */ | ClassDoc | file://hudson:1:1:1:1 | hudson | package | file://Plugin:1:1:1:1 | Plugin | type | file://true:1:1:1:1 | true | subtypes | file://configure:1:1:1:1 | configure | name | file://(String,String):1:1:1:1 | (String,String) | signature | file://:1:1:1:1 | | input | file://Parameter[1]:1:1:1:1 | Parameter[1] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| Test.java:19:3:19:11 | reference | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:19:3:19:24 | set(...) | CallContext | Test.java:19:3:19:11 | reference | MethodDoc | Test.java:19:3:19:11 | reference | ClassDoc | 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://(Object):1:1:1:1 | (Object) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| Test.java:24:3:24:10 | supplier | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:24:3:24:16 | get(...) | CallContext | Test.java:24:3:24:10 | supplier | MethodDoc | Test.java:24:3:24:10 | supplier | ClassDoc | 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 | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| Test.java:24:3:24:16 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:24:3:24:16 | get(...) | CallContext | Test.java:24:3:24:16 | get(...) | MethodDoc | Test.java:24:3:24:16 | get(...) | ClassDoc | 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://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| Test.java:28:3:32:3 | copy(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:28:3:32:3 | copy(...) | MethodDoc | Test.java:28:3:32:3 | copy(...) | 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://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| Test.java:36:10:38:3 | newInputStream(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:36:10:38:3 | newInputStream(...) | MethodDoc | Test.java:36:10:38:3 | newInputStream(...) | 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://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| Test.java:37:4:37:11 | openPath | Related 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://ai-manual:1:1:1:1 | ai-manual | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| Test.java:43:4:43:22 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:43:4:43:22 | get(...) | CallContext | Test.java:43:4:43:22 | get(...) | MethodDoc | Test.java:43:4:43:22 | get(...) | ClassDoc | 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://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| Test.java:54:3:59:3 | walk(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:54:3:59:3 | walk(...) | MethodDoc | Test.java:54:3:59:3 | walk(...) | 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://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| Test.java:56:4:56:4 | o | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:54:3:59:3 | walk(...) | MethodDoc | Test.java:54:3:59:3 | walk(...) | 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[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://true:1:1:1:1 | true | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| Test.java:63:3:63:3 | c | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:63:3:63:20 | getInputStream(...) | CallContext | Test.java:63:3:63:3 | c | MethodDoc | Test.java:63:3:63:3 | c | 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://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| Test.java:68:30:68:47 | writer | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:68:30:68:47 | writer | CallContext | Test.java:68:30:68:47 | writer | MethodDoc | Test.java:68:30:68:47 | writer | ClassDoc | file://java.lang:1:1:1:1 | java.lang | package | file://Throwable:1:1:1:1 | Throwable | type | file://true:1:1:1:1 | true | subtypes | file://printStackTrace:1:1:1:1 | printStackTrace | name | file://(PrintWriter):1:1:1:1 | (PrintWriter) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| Test.java:86:3:88:3 | list(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:86:3:88:3 | list(...) | CallContext | Test.java:86:3:88:3 | list(...) | MethodDoc | Test.java:86:3:88:3 | list(...) | 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://list:1:1:1:1 | list | 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://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| Test.java:87:4:87:29 | createDirectories(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:87:4:87:29 | createDirectories(...) | CallContext | Test.java:87:4:87:29 | createDirectories(...) | MethodDoc | Test.java:87:4:87:29 | createDirectories(...) | 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://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.qlref b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.qlref deleted file mode 100644 index 5ea712b0239a..000000000000 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractCandidates.qlref +++ /dev/null @@ -1 +0,0 @@ -AutomodelApplicationModeExtractCandidates.ql diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.expected b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.expected deleted file mode 100644 index 91f33b6fb05b..000000000000 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.expected +++ /dev/null @@ -1,3 +0,0 @@ -| Test.java:48:10:50:3 | compareTo(...) | known sanitizer\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:48:10:50:3 | compareTo(...) | CallContext | Test.java:48:10:50:3 | compareTo(...) | MethodDoc | Test.java:48:10:50:3 | 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://: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 | -| 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 | -| 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 | diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.qlref b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.qlref deleted file mode 100644 index ccd3827571ee..000000000000 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractNegativeExamples.qlref +++ /dev/null @@ -1 +0,0 @@ -AutomodelApplicationModeExtractNegativeExamples.ql diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.expected b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.expected deleted file mode 100644 index bdc5667935bb..000000000000 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.expected +++ /dev/null @@ -1,5 +0,0 @@ -| 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 | -| 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 | -| 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 | -| 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 | -| 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 | diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.qlref b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.qlref deleted file mode 100644 index 5cf6baa1dba0..000000000000 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractPositiveExamples.qlref +++ /dev/null @@ -1 +0,0 @@ -AutomodelApplicationModeExtractPositiveExamples.ql diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.expected b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.expected new file mode 100644 index 000000000000..8ec8033d086e --- /dev/null +++ b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.expected @@ -0,0 +1,2 @@ +testFailures +failures diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.ql b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.ql new file mode 100644 index 000000000000..b7e1efc45325 --- /dev/null +++ b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.ql @@ -0,0 +1,35 @@ +import java +import AutomodelApplicationModeCharacteristics as Characteristics +import AutomodelExtractionTests + +module TestHelper implements TestHelperSig { + Location getEndpointLocation(Characteristics::Endpoint endpoint) { + result = endpoint.asTop().getLocation() + } + + predicate isCandidate( + Characteristics::Endpoint endpoint, string name, string signature, string input, string output, + string extensibleType + ) { + Characteristics::isCandidate(endpoint, _, _, _, name, signature, input, output, _, + extensibleType, _) + } + + predicate isPositiveExample( + Characteristics::Endpoint endpoint, string endpointType, string name, string signature, + string input, string output, string extensibleType + ) { + Characteristics::isPositiveExample(endpoint, endpointType, _, _, _, name, signature, input, + output, _, extensibleType) + } + + predicate isNegativeExample( + Characteristics::Endpoint endpoint, string name, string signature, string input, string output, + string extensibleType + ) { + Characteristics::isNegativeExample(endpoint, _, _, _, _, _, name, signature, input, output, _, + extensibleType) + } +} + +import MakeTest> diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/PluginImpl.java b/java/ql/automodel/test/AutomodelApplicationModeExtraction/PluginImpl.java index 11c0384f7592..b0f3482a7322 100644 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/PluginImpl.java +++ b/java/ql/automodel/test/AutomodelApplicationModeExtraction/PluginImpl.java @@ -2,7 +2,7 @@ public class PluginImpl extends Plugin { @Override - public void configure(String name, String value) { + public void configure(String name, String value) { // $ sourceModelCandidate=configure(String,String):Parameter[0] sourceModelCandidate=configure(String,String):Parameter[1] // ... } } diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/Test.java b/java/ql/automodel/test/AutomodelApplicationModeExtraction/Test.java index e915d452ad81..c7f73130369c 100644 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/Test.java +++ b/java/ql/automodel/test/AutomodelApplicationModeExtraction/Test.java @@ -16,56 +16,59 @@ class Test { public static void main(String[] args) throws Exception { AtomicReference 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 + reference.set( // $ sinkModelCandidate=set(Object):Argument[this] + args[0] // $ negativeSinkExample=set(Object):Argument[0] // modeled as a flow step + ); // $ negativeSourceExample=set(Object):ReturnValue // return type is void } public static void callSupplier(Supplier supplier) { - supplier.get(); // Argument[this] is a sink candidate; the call is a source candidate + supplier.get(); // $ sourceModelCandidate=get():ReturnValue sinkModelCandidate=get():Argument[this] } public static void copyFiles(Path source, Path target, CopyOption option) throws Exception { - Files.copy( // the call is a source candidate - source, // positive example (known sink) - target, // positive example (known sink) + Files.copy( + source, // $ positiveSinkExample=copy(Path,Path,CopyOption[]):Argument[0](path-injection) + target, // $ positiveSinkExample=copy(Path,Path,CopyOption[]):Argument[1](path-injection) option // no candidate (not modeled, but source and target are modeled) - ); + ); // $ sourceModelCandidate=copy(Path,Path,CopyOption[]):ReturnValue } public static InputStream getInputStream(Path openPath) throws Exception { - return Files.newInputStream( // the call is a source candidate - openPath // positive example (known sink), candidate ("only" ai-modeled, and useful as a candidate in regression testing) - ); + return Files.newInputStream( + openPath // $ sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[0] positiveSinkExample=newInputStream(Path,OpenOption[]):Argument[0](path-injection) // sink candidate because "only" ai-modeled, and useful as a candidate in regression testing + ); // $ sourceModelCandidate=newInputStream(Path,OpenOption[]):ReturnValue } public static InputStream getInputStream(String openPath) throws Exception { return Test.getInputStream( // the call is not a source candidate (argument to local call) - Paths.get(openPath) // no sink candidate (argument to local call); the call is a source candidate + Paths.get( + openPath // $ negativeSinkExample=get(String,String[]):Argument[0] // modeled as a flow step + ) // $ sourceModelCandidate=get(String,String[]):ReturnValue ); } public static int compareFiles(File f1, File f2) { - return f1.compareTo( // compareTo call is a known sanitizer - f2 // negative sink example (modeled as not a sink) - ); // the call is a negative source candidate (sanitizer) + return f1.compareTo( // $ negativeSinkExample=compareTo(File):Argument[this] + f2 // $ negativeSinkExample=compareTo(File):Argument[0] // modeled as not a sink + ); // $ negativeSourceExample=compareTo(File):ReturnValue // return type is int } public static void FilesWalkExample(Path p, FileVisitOption o) throws Exception { - Files.walk( // the call is a source candidate - p, // negative sink example (modeled as a taint step) - o, // the implicit varargs array is a candidate + Files.walk( + p, // $ negativeSinkExample=walk(Path,FileVisitOption[]):Argument[0] // modeled as a flow step + o, // the implicit varargs array is a candidate, annotated on the last line of the call o // not a candidate (only the first arg corresponding to a varargs array // is extracted) - ); + ); // $ sourceModelCandidate=walk(Path,FileVisitOption[]):ReturnValue sinkModelCandidate=walk(Path,FileVisitOption[]):Argument[1] } public static void WebSocketExample(URLConnection c) throws Exception { - c.getInputStream(); // the call is a source example, c is a sink candidate + c.getInputStream(); // $ sinkModelCandidate=getInputStream():Argument[this] positiveSourceExample=getInputStream():ReturnValue(remote) // not a source candidate (manual modeling) } } class OverrideTest extends Exception { - public void printStackTrace(PrintWriter writer) { // writer is a source candidate because it overrides an existing method + public void printStackTrace(PrintWriter writer) { // $ sourceModelCandidate=printStackTrace(PrintWriter):Parameter[0] return; } @@ -83,8 +86,18 @@ public FutureTask getTask() { class MoreTests { public static void FilesListExample(Path p) throws Exception { - Files.list( // the call is a source candidate - Files.createDirectories(p) // the call is a source candidate, but not a sink candidate (modeled as a taint step) - ); + Files.list( + Files.createDirectories( + p // $ positiveSinkExample=createDirectories(Path,FileAttribute[]):Argument[0](path-injection) + ) // $ sourceModelCandidate=createDirectories(Path,FileAttribute[]):ReturnValue negativeSinkExample=list(Path):Argument[0] // modeled as a flow step + ); // $ sourceModelCandidate=list(Path):ReturnValue + + Files.delete( + p // $ sinkModelCandidate=delete(Path):Argument[0] positiveSinkExample=delete(Path):Argument[0](path-injection) + ); // $ negativeSourceExample=delete(Path):ReturnValue // return type is void + + Files.deleteIfExists( + p // $ sinkModelCandidate=deleteIfExists(Path):Argument[0] positiveSinkExample=deleteIfExists(Path):Argument[0](path-injection) + ); // $ negativeSourceExample=deleteIfExists(Path):ReturnValue // return type is boolean } } \ No newline at end of file diff --git a/java/ql/automodel/test/AutomodelExtractionTests.qll b/java/ql/automodel/test/AutomodelExtractionTests.qll new file mode 100644 index 000000000000..fbc407c67f05 --- /dev/null +++ b/java/ql/automodel/test/AutomodelExtractionTests.qll @@ -0,0 +1,77 @@ +import java +import TestUtilities.InlineExpectationsTest +import AutomodelSharedCharacteristics + +signature module TestHelperSig { + Location getEndpointLocation(Candidate::Endpoint e); + + predicate isCandidate( + Candidate::Endpoint e, string name, string signature, string input, string output, + string extensibleType + ); + + predicate isPositiveExample( + Candidate::Endpoint e, string endpointType, string name, string signature, string input, + string output, string extensibleType + ); + + predicate isNegativeExample( + Candidate::Endpoint e, string name, string signature, string input, string output, + string extensibleType + ); +} + +module Extraction TestHelper> implements TestSig { + string getARelevantTag() { + result in [ + "sourceModelCandidate", "sinkModelCandidate", // a candidate source/sink + "positiveSourceExample", "positiveSinkExample", // a known source/sink + "negativeSourceExample", "negativeSinkExample" // a known non-source/non-sink + ] + } + + /** + * If `extensibleType` is `sourceModel` then the result is `ifSource`, if it + * is `sinkModel` then the result is `ifSink`. + */ + bindingset[extensibleType, ifSource, ifSink] + private string ifSource(string extensibleType, string ifSource, string ifSink) { + extensibleType = "sourceModel" and result = ifSource + or + extensibleType = "sinkModel" and result = ifSink + } + + additional predicate selectEndpoint( + Candidate::Endpoint endpoint, string name, string signature, string input, string output, + string extensibleType, string tag, string suffix + ) { + TestHelper::isCandidate(endpoint, name, signature, input, output, extensibleType) and + tag = ifSource(extensibleType, "sourceModelCandidate", "sinkModelCandidate") and + suffix = "" + or + TestHelper::isNegativeExample(endpoint, name, signature, input, output, extensibleType) and + tag = "negative" + ifSource(extensibleType, "Source", "Sink") + "Example" and + suffix = "" + or + exists(string endpointType | + TestHelper::isPositiveExample(endpoint, endpointType, name, signature, input, output, + extensibleType) and + tag = "positive" + ifSource(extensibleType, "Source", "Sink") + "Example" and + suffix = "(" + endpointType + ")" + ) + } + + predicate hasActualResult(Location location, string element, string tag, string value) { + exists( + Candidate::Endpoint endpoint, string name, string signature, string input, string output, + string extensibleType, string suffix + | + selectEndpoint(endpoint, name, signature, input, output, extensibleType, tag, suffix) + | + TestHelper::getEndpointLocation(endpoint) = location and + endpoint.toString() = element and + // for source models only the output is relevant, and vice versa for sink models + value = name + signature + ":" + ifSource(extensibleType, output, input) + suffix + ) + } +} diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.expected b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.expected deleted file mode 100644 index 411f1c57b2ce..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.expected +++ /dev/null @@ -1,25 +0,0 @@ -| com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | Related 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://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | Related 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://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | Related 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://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | Related 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://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | Related 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://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | MethodDoc | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | 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://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | MethodDoc | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | 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://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:13:33:13:42 | 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://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:13:33:13:42 | 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://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | MethodDoc | com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | 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://PublicClass:1:1:1:1 | PublicClass | name | file://(Object):1:1:1:1 | (Object) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://:1:1:1:1 | | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| com/github/codeql/test/PublicClass.java:22:22:22:33 | input | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:22:22:22:33 | input | MethodDoc | com/github/codeql/test/PublicClass.java:22:22:22:33 | input | 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://PublicClass:1:1:1:1 | PublicClass | name | file://(Object):1:1:1:1 | (Object) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://input:1:1:1:1 | input | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| com/github/codeql/test/PublicClass.java:26:18:26:26 | isIgnored | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:26:18:26:26 | isIgnored | MethodDoc | com/github/codeql/test/PublicClass.java:26:18:26:26 | isIgnored | 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://isIgnored:1:1:1:1 | isIgnored | name | file://(Object):1:1:1:1 | (Object) | signature | file://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| com/github/codeql/test/PublicClass.java:26:28:26:39 | input | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:26:28:26:39 | input | MethodDoc | com/github/codeql/test/PublicClass.java:26:28:26:39 | input | 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://isIgnored:1:1:1:1 | isIgnored | name | file://(Object):1:1:1:1 | (Object) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://input:1:1:1:1 | input | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| com/github/codeql/test/PublicInterface.java:4:16:4:20 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:16:4:20 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:16:4:20 | 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://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| com/github/codeql/test/PublicInterface.java:4:16:4:20 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:16:4:20 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:16:4:20 | 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://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| com/github/codeql/test/PublicInterface.java:4:22:4:31 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:22:4:31 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:4:22:4:31 | 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://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| com/github/codeql/test/PublicInterface.java:4:22:4:31 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:22:4:31 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:4:22:4:31 | 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://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | Related 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://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| java/io/File.java:10:20:10:34 | setLastModified | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:10:20:10:34 | setLastModified | MethodDoc | java/io/File.java:10:20:10:34 | setLastModified | 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://setLastModified:1:1:1:1 | setLastModified | name | file://(long):1:1:1:1 | (long) | signature | file://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| java/io/File.java:10:20:10:34 | setLastModified | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:10:20:10:34 | setLastModified | MethodDoc | java/io/File.java:10:20:10:34 | setLastModified | 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://setLastModified:1:1:1:1 | setLastModified | name | file://(long):1:1:1:1 | (long) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| java/io/File.java:10:36:10:44 | time | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:10:36:10:44 | time | MethodDoc | java/io/File.java:10:36:10:44 | time | 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://setLastModified:1:1:1:1 | setLastModified | name | file://(long):1:1:1:1 | (long) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://time:1:1:1:1 | time | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| java/nio/file/Files.java:14:9:14:24 | out | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:14:9:14:24 | out | MethodDoc | java/nio/file/Files.java:14:9:14: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://:1:1:1:1 | | output | file://out:1:1:1:1 | out | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| java/nio/file/Files.java:24:31:24:44 | newInputStream | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:24:31:24:44 | newInputStream | MethodDoc | java/nio/file/Files.java:24:31:24:44 | newInputStream | 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://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://:1:1:1:1 | | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| java/nio/file/Files.java:25:9:25:21 | openPath | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:25:9:25:21 | openPath | MethodDoc | java/nio/file/Files.java:25:9:25:21 | 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://openPath:1:1:1:1 | openPath | parameterName | file://ai-manual:1:1:1:1 | ai-manual | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| java/nio/file/Files.java:26:9:26:29 | options | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:26:9:26:29 | options | MethodDoc | java/nio/file/Files.java:26:9:26:29 | options | 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[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://options:1:1:1:1 | options | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.qlref b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.qlref deleted file mode 100644 index e9b513032aaf..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractCandidates.qlref +++ /dev/null @@ -1 +0,0 @@ -AutomodelFrameworkModeExtractCandidates.ql diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.expected b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.expected deleted file mode 100644 index e1bcaca7ddde..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.expected +++ /dev/null @@ -1,7 +0,0 @@ -| com/github/codeql/test/PublicClass.java:26:18:26:26 | isIgnored | unexploitable (is-style boolean method)\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:26:18:26:26 | isIgnored | MethodDoc | com/github/codeql/test/PublicClass.java:26:18:26:26 | isIgnored | 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://isIgnored:1:1:1:1 | isIgnored | name | file://(Object):1:1:1:1 | (Object) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://:1:1:1:1 | | parameterName | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| com/github/codeql/test/PublicClass.java:26:18:26:26 | isIgnored | unexploitable (is-style boolean method)\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:26:18:26:26 | isIgnored | MethodDoc | com/github/codeql/test/PublicClass.java:26:18:26:26 | isIgnored | 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://isIgnored:1:1:1:1 | isIgnored | name | file://(Object):1:1:1:1 | (Object) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| com/github/codeql/test/PublicClass.java:26:28:26:39 | input | unexploitable (is-style boolean method)\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:26:28:26:39 | input | MethodDoc | com/github/codeql/test/PublicClass.java:26:28:26:39 | input | 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://isIgnored:1:1:1:1 | isIgnored | name | file://(Object):1:1:1:1 | (Object) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://input:1:1:1:1 | input | parameterName | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| java/io/File.java:4:16:4:24 | compareTo | known non-sink\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:4:16:4:24 | compareTo | MethodDoc | java/io/File.java:4:16:4:24 | 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://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| java/io/File.java:4:16:4:24 | compareTo | known non-sink\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:4:16:4:24 | compareTo | MethodDoc | java/io/File.java:4:16:4:24 | 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://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| 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://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://pathname:1:1:1:1 | pathname | parameterName | file://sourceModel:1:1:1:1 | sourceModel | extensibleType | -| 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://:1:1:1:1 | | output | file://pathname:1:1:1:1 | pathname | parameterName | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.qlref b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.qlref deleted file mode 100644 index 69498caf8998..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractNegativeExamples.qlref +++ /dev/null @@ -1 +0,0 @@ -AutomodelFrameworkModeExtractNegativeExamples.ql diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.expected b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.expected deleted file mode 100644 index dcef63fd4bf8..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.expected +++ /dev/null @@ -1,2 +0,0 @@ -| java/nio/file/Files.java:13:9:13:19 | source | path-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:13:9:13:19 | source | MethodDoc | java/nio/file/Files.java:13:9:13: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://:1:1:1:1 | | output | file://source:1:1:1:1 | source | parameterName | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | -| java/nio/file/Files.java:25:9:25:21 | openPath | path-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:25:9:25:21 | openPath | MethodDoc | java/nio/file/Files.java:25:9:25:21 | 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://openPath:1:1:1:1 | openPath | parameterName | file://sinkModel:1:1:1:1 | sinkModel | extensibleType | diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.qlref b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.qlref deleted file mode 100644 index fbda3f3dd376..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractPositiveExamples.qlref +++ /dev/null @@ -1 +0,0 @@ -AutomodelFrameworkModeExtractPositiveExamples.ql diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.expected b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.expected new file mode 100644 index 000000000000..8ec8033d086e --- /dev/null +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.expected @@ -0,0 +1,2 @@ +testFailures +failures diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.ql b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.ql new file mode 100644 index 000000000000..0d5e86118705 --- /dev/null +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.ql @@ -0,0 +1,35 @@ +import java +import AutomodelFrameworkModeCharacteristics as Characteristics +import AutomodelExtractionTests + +module TestHelper implements TestHelperSig { + Location getEndpointLocation(Characteristics::Endpoint endpoint) { + result = endpoint.asTop().getLocation() + } + + predicate isCandidate( + Characteristics::Endpoint endpoint, string name, string signature, string input, string output, + string extensibleType + ) { + Characteristics::isCandidate(endpoint, _, _, _, name, signature, input, output, _, + extensibleType, _) + } + + predicate isPositiveExample( + Characteristics::Endpoint endpoint, string endpointType, string name, string signature, + string input, string output, string extensibleType + ) { + Characteristics::isPositiveExample(endpoint, endpointType, _, _, _, name, signature, input, + output, _, extensibleType) + } + + predicate isNegativeExample( + Characteristics::Endpoint endpoint, string name, string signature, string input, string output, + string extensibleType + ) { + Characteristics::isNegativeExample(endpoint, _, _, _, _, _, name, signature, input, output, _, + extensibleType) + } +} + +import MakeTest> diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java index e0915ac628ff..79fabff0664b 100644 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java @@ -1,29 +1,27 @@ package com.github.codeql.test; public class PublicClass { - public void stuff(String arg) { // `arg` is a sink candidate, `this` is a candidate, `arg` is a source candidate (overrideable method) + public void stuff(String arg) { // $ sinkModelCandidate=stuff(String):Argument[this] sourceModelCandidate=stuff(String):Parameter[this] sinkModelCandidate=stuff(String):Argument[0] sourceModelCandidate=stuff(String):Parameter[0] // source candidates because it is an overrideable method System.out.println(arg); } - public static void staticStuff(String arg) { // `arg` is a sink candidate, but not a source candidate (not overrideabe); `this` is not a candidate (static method) + public static void staticStuff(String arg) { // $ sinkModelCandidate=staticStuff(String):Argument[0] // `arg` is not a source candidate (not overrideabe); `this` is not a candidate (static method) System.out.println(arg); } - // `arg` and `this` are candidates because the method is protected (may be called from downstream repositories). The return value is a candidate source for the same reason. - protected void nonPublicStuff(String arg) { + protected void nonPublicStuff(String arg) { // $ sinkModelCandidate=nonPublicStuff(String):Argument[this] sourceModelCandidate=nonPublicStuff(String):Parameter[this] sinkModelCandidate=nonPublicStuff(String):Argument[0] sourceModelCandidate=nonPublicStuff(String):Parameter[0] System.out.println(arg); } - // `arg` and `this are not candidates because the method is not public: - void packagePrivateStuff(String arg) { + void packagePrivateStuff(String arg) { // no candidates because the method is not public System.out.println(arg); } - public PublicClass(Object input) { - // the `this` qualifier is not a candidate + public PublicClass(Object input) { // $ sourceModelCandidate=PublicClass(Object):ReturnValue sinkModelCandidate=PublicClass(Object):Argument[0] // `this` is not a candidate because it is a constructor } - public Boolean isIgnored(Object input) { // `input` is a source candidate, but not a sink candidate (is-style method); `this` is not a candidate + // `input` and `input` are source candidates, but not sink candidates (is-style method) + public Boolean isIgnored(Object input) { // $ negativeSinkExample=isIgnored(Object):Argument[this] sourceModelCandidate=isIgnored(Object):Parameter[this] negativeSinkExample=isIgnored(Object):Argument[0] sourceModelCandidate=isIgnored(Object):Parameter[0] return false; } } diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java index 5ee8cb095115..d4f80b3c6988 100644 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java @@ -1,9 +1,9 @@ package com.github.codeql.test; public interface PublicInterface { - public int stuff(String arg); // `arg` is a candidate, `this` is a candidate, method stuff is _not_ a candidate source (primitive return type), `arg` is a source candidate (overridable method) + public int stuff(String arg); // $ sinkModelCandidate=stuff(String):Argument[this] sourceModelCandidate=stuff(String):Parameter[this] sinkModelCandidate=stuff(String):Argument[0] sourceModelCandidate=stuff(String):Parameter[0] // result is _not_ a source candidate source (primitive return type) - public static void staticStuff(String arg) { // `arg` is a candidate, `this` is not a candidate (static method) + public static void staticStuff(String arg) { // $ sinkModelCandidate=staticStuff(String):Argument[0] // not a source candidate (static method) System.out.println(arg); } } diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/io/File.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/io/File.java index 7abf501d905e..c23b6165c648 100644 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/io/File.java +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/io/File.java @@ -1,13 +1,13 @@ package java.io; public class File { - public 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 + public int compareTo( // $ negativeSinkExample=compareTo(File):Argument[this] negativeSourceExample=compareTo(File):Parameter[this] // modeled as neutral + File pathname // $ negativeSinkExample=compareTo(File):Argument[0] negativeSourceExample=compareTo(File):Parameter[0] // modeled as neutral ) { return 0; } - public boolean setLastModified(long time) { + public boolean setLastModified(long time) { // $ sinkModelCandidate=setLastModified(long):Argument[this] sourceModelCandidate=setLastModified(long):Parameter[this] // time is not a candidate (primitive type) return false; } // return value is not a source candidate because it's a primitive } diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/nio/file/Files.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/nio/file/Files.java index 6374d8ee8a4c..a833ba5f6e20 100644 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/nio/file/Files.java +++ b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/nio/file/Files.java @@ -9,9 +9,10 @@ import java.nio.file.OpenOption; 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 + public static void copy( // method result is not a candidate source (void) + Path source, // $ positiveSinkExample=copy(Path,OutputStream):Argument[0](path-injection) // manual model exists + OutputStream out // $ sinkModelCandidate=copy(Path,OutputStream):Argument[1] + /* 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 @@ -19,12 +20,12 @@ public static void copy( */ ) throws IOException { // ... - } // method copy is a candidate source + } - public static InputStream newInputStream( - Path openPath ,// positive example (known sink), candidate (ai-modeled, and useful as a candidate in regression testing) - OpenOption... options + public static InputStream newInputStream( // $ sourceModelCandidate=newInputStream(Path,OpenOption[]):ReturnValue + Path openPath, // $ positiveSinkExample=newInputStream(Path,OpenOption[]):Argument[0](path-injection) sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[0] // known sink, but still a candidate (ai-modeled, and useful as a candidate in regression testing) + OpenOption... options // $ sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[1] ) throws IOException { return new FileInputStream(openPath.toFile()); - } // method newInputStream is a candidate source + } } diff --git a/java/ql/automodel/test/qlpack.yml b/java/ql/automodel/test/qlpack.yml index 11f5ec8c1926..633e848ccc8a 100644 --- a/java/ql/automodel/test/qlpack.yml +++ b/java/ql/automodel/test/qlpack.yml @@ -7,6 +7,7 @@ groups: dependencies: codeql/java-all: ${workspace} codeql/java-automodel-queries: ${workspace} + codeql/java-tests: ${workspace} extractor: java tests: . warnOnImplicitThis: true \ No newline at end of file