Skip to content
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

How to share context with follow up queries? #9

Open
martinschaef opened this issue Sep 14, 2020 · 3 comments
Open

How to share context with follow up queries? #9

martinschaef opened this issue Sep 14, 2020 · 3 comments

Comments

@martinschaef
Copy link

I have the following test program and want to perform a BackwardQuery for variable bar in line

ConstantPropagationTest.assertReachesSources(bar, "java.util.Scanner:");

The query gives me the AllocVal

        return new StringBuilder(s).toString();

and from there, I want to start a follow up query for s.

import java.util.Scanner;
import ConstantPropagationTest;

public class Test1 {

    /**
     * Our constant propagation finds the definition of the return value here
     * and knows (by looking up a list of builtin summaries) that it needs to
     * perform a follow-up {@link boomerang.BackwardQuery} for s.
     * However, this follow-up query does not share the {@link boomerang.Context} of the original
     * query, so when it steps out of {@link #loosingTrackOfThings(String)}, it does not remember
     * that it came from {@link #entryPoint()} and explores all possible call sites instead.
     *
     * @param s Some string that's being passed through.
     * @return The same string that was passed as an argument.
     */
    public static String loosingTrackOfThings(String s) {
        return new StringBuilder(s).toString();
    }


    public void entryPoint() {
        Scanner scanner = new Scanner(System.in);
        String fooTest1 = scanner.next();
        final String bar = loosingTrackOfThings(fooTest1);
        ConstantPropagationTest.assertReachesSources(bar, "java.util.Scanner:");
    }

    public void unreleatedMethod1() {
        Scanner scanner = new Scanner(System.in);
        String fooTest1 = scanner.nextLine();
        final String bar = loosingTrackOfThings(fooTest1);

    }

    public void unreleatedMethod2() {
        Scanner scanner = new Scanner(System.in);
        String fooTest1 = scanner.toString();
        final String bar = loosingTrackOfThings(fooTest1);
    }
}

Currently, the second backward query finds reaching definitions in entryPoint, unreleatedMethod1, and unreleatedMethod2 because the second query doesn't get the call stack from the first.

Is there a way to share information between queries in Boomerang?

@johspaeth
Copy link
Member

The query graph can be used to tell a query which paths to follow. I pointed out details here:

CROSSINGTUD#92

@martinschaef
Copy link
Author

martinschaef commented Sep 15, 2020

Hmm ... looks like I'm doing it wrong. Here a sketch of my setup (not syntactically correct):

    private void runBoomerangQueries(JimpleVal jimpleVal, Unit stmt
                                     final Set<Node<Statement, Val>> parentBoomerangTrace)
        BackwardQuery query = BackwardQuery.make(stmt, jimpleVal);
     ...
          SootCallGraph sootGraph = new SootCallGraph();
            // here I'm trying to add the results from the previous query ------------
            if (parentBoomerangTrace != null) {
                parentBoomerangTrace.stream().forEach(node -> {
                    val method = interproceduralCFG.getMethodOf(getJimpleStatementFromStatement(node.stmt())
                                                                    .getDelegate());
                    CallSiteStatement callSiteStatement;
                    if (node.stmt() instanceof ReturnSiteStatement) {
                        callSiteStatement = ((ReturnSiteStatement) node.stmt()).getCallSiteStatement();
                    } else if (node.stmt() instanceof CallSiteStatement) {
                        callSiteStatement = ((CallSiteStatement) node.stmt());
                    } else {
                        callSiteStatement = new CallSiteStatement(node.stmt());
                    }
                    sootGraph.addEdge(new CallGraph.Edge(callSiteStatement, JimpleMethod.of(method)));
                });
            }

            BoomerangOptions boomerangOptions = new BoomerangOptions(config);
            Boomerang solver = new Boomerang(sootGraph, SootDataFlowScope.make(Scene.v()), boomerangOptions);
            BackwardBoomerangResults<Weight.NoWeight> backwardResults = solver.solve(query);

        for (ForwardQuery forwardQuery : backwardResults.getAllocationSites().keySet()) {
            if (forwardQuery.var() instanceof AllocVal) {
                val allocVal = (AllocVal) forwardQuery.var();
                if ( ... if the alloc val contains a summary ...) {
                    val dataFlowPath = backwardResults.getDataFlowPath(forwardQuery);
                    val value = ((JimpleVal) allocVal.getAllocVal()).getDelegate();
                    // recursive call with new trace ------------------
                    runBoomerangQueries(val, allocVal.stmt(), dataFlowPath);

But the statement sootGraph.addEdge(new CallGraph.Edge(callSiteStatement, JimpleMethod.of(method))); doesn't seem to have an effect on the recursive query.

@martinschaef
Copy link
Author

Also, I noticed that the CallSiteStatement and ReturnSiteStatement classes disappeared in 3.1.1; is there an immediate need to update to that version is it ok to stay on an older release?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants