Skip to content

Java: Support Argument[this] and parameters of bodiless interface methods in framework mode metadata extraction #13823

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 69 additions & 16 deletions java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,64 @@ newtype JavaRelatedLocationType =
MethodDoc() or
ClassDoc()

newtype TFrameworkModeEndpoint =
TExplicitParameter(Parameter p) or
TQualifier(Callable c)

/**
* A framework mode endpoint.
*/
abstract class FrameworkModeEndpoint extends TFrameworkModeEndpoint {
/**
* Returns the parameter index of the endpoint.
*/
abstract int getIndex();

/**
* Returns the name of the parameter of the endpoint.
*/
abstract string getParamName();

/**
* Returns the callable that contains the endpoint.
*/
abstract Callable getEnclosingCallable();

abstract Top asTop();

string toString() { result = this.asTop().toString() }

Location getLocation() { result = this.asTop().getLocation() }
}

class ExplicitParameterEndpoint extends FrameworkModeEndpoint, TExplicitParameter {
Parameter param;

ExplicitParameterEndpoint() { this = TExplicitParameter(param) }

override int getIndex() { result = param.getPosition() }

override string getParamName() { result = param.getName() }

override Callable getEnclosingCallable() { result = param.getCallable() }

override Top asTop() { result = param }
}

class QualifierEndpoint extends FrameworkModeEndpoint, TQualifier {
Callable callable;

QualifierEndpoint() { this = TQualifier(callable) }

override int getIndex() { result = -1 }

override string getParamName() { result = "this" }

override Callable getEnclosingCallable() { result = callable }

override Top asTop() { result = callable }
}

/**
* A candidates implementation for framework mode.
*
Expand All @@ -33,7 +91,7 @@ newtype JavaRelatedLocationType =
*/
module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
// for documentation of the implementations here, see the QLDoc in the CandidateSig signature module.
class Endpoint = DataFlow::ParameterNode;
class Endpoint = FrameworkModeEndpoint;

class EndpointType = AutomodelEndpointTypes::EndpointType;

Expand All @@ -46,7 +104,7 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
// Sanitizers are currently not modeled in MaD. TODO: check if this has large negative impact.
predicate isSanitizer(Endpoint e, EndpointType t) { none() }

RelatedLocation asLocation(Endpoint e) { result = e.asParameter() }
RelatedLocation asLocation(Endpoint e) { result = e.asTop() }

predicate isKnownKind = AutomodelJavaUtil::isKnownKind/2;

Expand All @@ -70,9 +128,7 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
FrameworkModeGetCallable::getCallable(e).hasQualifiedName(package, type, name) and
signature = ExternalFlow::paramsString(FrameworkModeGetCallable::getCallable(e)) and
ext = "" and
exists(int paramIdx | e.isParameterOf(_, paramIdx) |
input = AutomodelJavaUtil::getArgumentForIndex(paramIdx)
)
input = AutomodelJavaUtil::getArgumentForIndex(e.getIndex())
}

/**
Expand Down Expand Up @@ -124,16 +180,13 @@ class FrameworkModeMetadataExtractor extends string {
Endpoint e, string package, string type, string subtypes, string name, string signature,
string input, string parameterName
) {
exists(Callable callable, int paramIdx |
e.asParameter() = callable.getParameter(paramIdx) and
input = AutomodelJavaUtil::getArgumentForIndex(paramIdx) and
package = callable.getDeclaringType().getPackage().getName() and
type = callable.getDeclaringType().getErasure().(RefType).nestedName() and
subtypes = AutomodelJavaUtil::considerSubtypes(callable).toString() and
name = callable.getName() and
parameterName = e.asParameter().getName() and
signature = ExternalFlow::paramsString(callable)
)
parameterName = e.getParamName() and
name = e.getEnclosingCallable().getName() and
input = AutomodelJavaUtil::getArgumentForIndex(e.getIndex()) and
package = e.getEnclosingCallable().getDeclaringType().getPackage().getName() and
type = e.getEnclosingCallable().getDeclaringType().getErasure().(RefType).nestedName() and
subtypes = AutomodelJavaUtil::considerSubtypes(e.getEnclosingCallable()).toString() and
signature = ExternalFlow::paramsString(e.getEnclosingCallable())
}
}

Expand Down Expand Up @@ -201,7 +254,7 @@ private class NotAModelApiParameter extends CharacteristicsImpl::UninterestingTo
NotAModelApiParameter() { this = "not a model API parameter" }

override predicate appliesToEndpoint(Endpoint e) {
not exists(ModelExclusions::ModelApi api | api.getAParameter() = e.asParameter())
not e.getEnclosingCallable() instanceof ModelExclusions::ModelApi
}
}

Expand Down