Java: add new endpoint class for source candidates in application mode

This commit is contained in:
Stephan Brandauer 2023-09-05 15:51:08 +02:00
Родитель 7cfcbf6b71
Коммит eb1e29d284
3 изменённых файлов: 42 добавлений и 6 удалений

Просмотреть файл

@ -35,7 +35,8 @@ newtype TApplicationModeEndpoint =
argExpr.isVararg() and
not exists(int i | i < idx and call.getArgument(i).(Argument).isVararg())
)
}
} or
TMethodCall(Call call) { not call instanceof ConstructorCall }
/**
* An endpoint is a node that is a candidate for modeling.
@ -122,6 +123,25 @@ class ImplicitVarargsArray extends ApplicationModeEndpoint, TImplicitVarargsArra
override string toString() { result = vararg.toString() }
}
/**
* An endpoint that represents a method call.
*/
class MethodCall extends ApplicationModeEndpoint, TMethodCall {
Call call;
MethodCall() { this = TMethodCall(call) }
override predicate isArgOf(Call c, int idx) { c = call and idx = -1 }
override Top asTop() { result = call }
override DataFlow::Node asNode() { result.asExpr() = call }
override string getExtensibleType() { result = "sourceModel" }
override string toString() { result = call.toString() }
}
/**
* A candidates implementation.
*
@ -275,6 +295,7 @@ private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NotASin
UnexploitableIsCharacteristic() { this = "unexploitable (is-style boolean method)" }
override predicate appliesToEndpoint(Endpoint e) {
e.getExtensibleType() = "sinkModel" and
not ApplicationCandidatesImpl::isSink(e, _, _) and
ApplicationModeGetCallable::getCallable(e).getName().matches("is%") and
ApplicationModeGetCallable::getCallable(e).getReturnType() instanceof BooleanType
@ -293,6 +314,7 @@ private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::Not
UnexploitableExistsCharacteristic() { this = "unexploitable (existence-checking boolean method)" }
override predicate appliesToEndpoint(Endpoint e) {
e.getExtensibleType() = "sinkModel" and
not ApplicationCandidatesImpl::isSink(e, _, _) and
exists(Callable callable |
callable = ApplicationModeGetCallable::getCallable(e) and
@ -309,6 +331,7 @@ private class ExceptionCharacteristic extends CharacteristicsImpl::NotASinkChara
ExceptionCharacteristic() { this = "exception" }
override predicate appliesToEndpoint(Endpoint e) {
e.getExtensibleType() = "sinkModel" and
ApplicationModeGetCallable::getCallable(e).getDeclaringType().getASupertype*() instanceof
TypeThrowable
}
@ -323,9 +346,13 @@ private class IsMaDTaintStepCharacteristic extends CharacteristicsImpl::NotASink
IsMaDTaintStepCharacteristic() { this = "taint step" }
override predicate appliesToEndpoint(Endpoint e) {
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(e.asNode(), _, _) or
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(e.asNode(), _, _) or
FlowSummaryImpl::Private::Steps::summaryGetterStep(e.asNode(), _, _, _) or
e.getExtensibleType() = "sinkModel" and
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(e.asNode(), _, _)
or
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(e.asNode(), _, _)
or
FlowSummaryImpl::Private::Steps::summaryGetterStep(e.asNode(), _, _, _)
or
FlowSummaryImpl::Private::Steps::summarySetterStep(e.asNode(), _, _, _)
}
}
@ -340,6 +367,7 @@ private class ArgumentToLocalCall extends CharacteristicsImpl::UninterestingToMo
ArgumentToLocalCall() { this = "argument to local call" }
override predicate appliesToEndpoint(Endpoint e) {
e.getExtensibleType() = "sinkModel" and
ApplicationModeGetCallable::getCallable(e).fromSource()
}
}
@ -351,6 +379,7 @@ private class ExcludedFromModeling extends CharacteristicsImpl::UninterestingToM
ExcludedFromModeling() { this = "excluded from modeling" }
override predicate appliesToEndpoint(Endpoint e) {
e.getExtensibleType() = "sinkModel" and
ModelExclusions::isUninterestingForModels(ApplicationModeGetCallable::getCallable(e))
}
}
@ -364,6 +393,7 @@ private class NonPublicMethodCharacteristic extends CharacteristicsImpl::Uninter
NonPublicMethodCharacteristic() { this = "non-public method" }
override predicate appliesToEndpoint(Endpoint e) {
e.getExtensibleType() = "sinkModel" and
not ApplicationModeGetCallable::getCallable(e).isPublic()
}
}
@ -386,6 +416,7 @@ private class OtherArgumentToModeledMethodCharacteristic extends Characteristics
}
override predicate appliesToEndpoint(Endpoint e) {
e.getExtensibleType() = "sinkModel" and
not ApplicationCandidatesImpl::isSink(e, _, _) and
exists(Endpoint otherSink |
ApplicationCandidatesImpl::isSink(otherSink, _, "manual") and
@ -403,7 +434,10 @@ private class OtherArgumentToModeledMethodCharacteristic extends Characteristics
private class FunctionValueCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic {
FunctionValueCharacteristic() { this = "function value" }
override predicate appliesToEndpoint(Endpoint e) { e.asNode().asExpr() instanceof FunctionalExpr }
override predicate appliesToEndpoint(Endpoint e) {
e.getExtensibleType() = "sinkModel" and
e.asNode().asExpr() instanceof FunctionalExpr
}
}
/**
@ -419,6 +453,7 @@ private class CannotBeTaintedCharacteristic extends CharacteristicsImpl::LikelyN
override predicate appliesToEndpoint(Endpoint e) {
// XXX consider source candidate endpoints
e.getExtensibleType() = "sinkModel" and
not this.isKnownOutNodeForStep(e)
}

Просмотреть файл

@ -1,2 +1,3 @@
| Test.java:45:10:47:3 | compareTo(...) | known sanitizer\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | Test.java:45:10:47:3 | compareTo(...) | CallContext | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://false:1:1:1:1 | false | isVarargsArray |
| Test.java:46:4:46:5 | f2 | known non-sink\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | Test.java:45:10:47:3 | compareTo(...) | CallContext | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://false:1:1:1:1 | false | isVarargsArray |
| Test.java:52:4:52:4 | p | taint step\nrelated locations: $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@. | Test.java:51:3:56:3 | walk(...) | CallContext | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://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://false:1:1:1:1 | false | isVarargsArray |

Просмотреть файл

@ -42,7 +42,7 @@ class Test {
}
public static int compareFiles(File f1, File f2) {
return f1.compareTo(
return f1.compareTo( // compareTo call is a known sanitizer
f2 // negative example (modeled as not a sink)
);
}