From 37455ec29ee08ab7e8f78aad3137c2f4343e06cf Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Wed, 26 Jul 2023 15:19:50 +0200 Subject: [PATCH] Java: Replace ratpack test fix with general heuristic summary. --- java/ql/lib/ext/ratpack.exec.model.yml | 1 - .../semmle/code/java/dataflow/FlowSummary.qll | 3 ++ .../code/java/dispatch/WrappedInvocation.qll | 41 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/ext/ratpack.exec.model.yml b/java/ql/lib/ext/ratpack.exec.model.yml index cc8ec7a9894..44da63c29b7 100644 --- a/java/ql/lib/ext/ratpack.exec.model.yml +++ b/java/ql/lib/ext/ratpack.exec.model.yml @@ -3,7 +3,6 @@ extensions: pack: codeql/java-all extensible: summaryModel data: - - ["ratpack.exec", "Operation", True, "of", "(Block)", "", "Argument[0]", "Argument[0].Parameter[this]", "value", "manual"] - ["ratpack.exec", "Promise", True, "apply", "", "", "Argument[this].Element", "Argument[0].Parameter[0].Element", "value", "manual"] - ["ratpack.exec", "Promise", True, "apply", "", "", "Argument[0].ReturnValue.Element", "ReturnValue.Element", "value", "manual"] - ["ratpack.exec", "Promise", True, "blockingMap", "", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"] diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll index e45ba0be27e..b0e342ab320 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll @@ -101,6 +101,7 @@ abstract class SyntheticCallable extends string { * A module for importing frameworks that define synthetic callables. */ private module SyntheticCallables { + private import semmle.code.java.dispatch.WrappedInvocation private import semmle.code.java.frameworks.android.Intent private import semmle.code.java.frameworks.Stream } @@ -170,6 +171,8 @@ class SummarizedCallableBase extends TSummarizedCallableBase { } } +class Provenance = Impl::Public::Provenance; + class SummarizedCallable = Impl::Public::SummarizedCallable; class NeutralCallable = Impl::Public::NeutralCallable; diff --git a/java/ql/lib/semmle/code/java/dispatch/WrappedInvocation.qll b/java/ql/lib/semmle/code/java/dispatch/WrappedInvocation.qll index ec1eea5f93c..83bdaadfb7a 100644 --- a/java/ql/lib/semmle/code/java/dispatch/WrappedInvocation.qll +++ b/java/ql/lib/semmle/code/java/dispatch/WrappedInvocation.qll @@ -58,3 +58,44 @@ Method getRunnerTarget(MethodAccess ma) { result.overridesOrInstantiates*(runmethod) ) } + +import semmle.code.java.dataflow.FlowSummary +import semmle.code.java.dataflow.internal.FlowSummaryImplSpecific as ImplSpecific + +private predicate hasExternalSummary(Callable c) { + exists(SummarizedCallableBase scb | scb.asCallable() = c | + ImplSpecific::summaryElement(scb, _, _, _, _) + ) +} + +private predicate mayInvokeCallback(SrcMethod m, int n) { + m.getParameterType(n).(RefType).getSourceDeclaration() instanceof FunctionalInterface and + (not m.fromSource() or m.isNative() or m.getFile().getAbsolutePath().matches("%/test/stubs/%")) and + not hasExternalSummary(m) +} + +private class SummarizedCallableWithCallback extends SummarizedCallable { + private int pos; + + SummarizedCallableWithCallback() { mayInvokeCallback(this.asCallable(), pos) } + + override predicate propagatesFlow( + SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue + ) { + input = SummaryComponentStack::argument(pos) and + output = SummaryComponentStack::push(SummaryComponent::parameter(-1), input) and + preservesValue = true + } + + override predicate hasProvenance(Provenance provenance) { provenance = "hq-generated" } +} + +private class RequiredComponentStackForCallback extends RequiredSummaryComponentStack { + override predicate required(SummaryComponent head, SummaryComponentStack tail) { + exists(int pos | + mayInvokeCallback(_, pos) and + head = SummaryComponent::parameter(-1) and + tail = SummaryComponentStack::argument(pos) + ) + } +}