All Downloads are FREE. Search and download functionalities are using the official Maven repository.

crypto.extractparameter.ExtractParameterAnalysis Maven / Gradle / Ivy

package crypto.extractparameter;

import boomerang.ForwardQuery;
import boomerang.scene.AllocVal;
import boomerang.scene.ControlFlowGraph;
import boomerang.scene.DeclaredMethod;
import boomerang.scene.Statement;
import boomerang.scene.Type;
import boomerang.scene.Val;
import crypto.extractparameter.transformation.TransformedAllocVal;
import crypto.utils.MatcherUtils;
import crysl.rule.CrySLMethod;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;

public class ExtractParameterAnalysis {

    private final Collection queries;
    private final Collection collectedValues;
    private final ExtractParameterDefinition definition;

    public ExtractParameterAnalysis(ExtractParameterDefinition definition) {
        this.definition = definition;

        queries = new HashSet<>();
        collectedValues = new HashSet<>();
    }

    public void run() {
        for (Statement statement : definition.getCollectedCalls()) {
            if (!statement.containsInvokeExpr()) {
                continue;
            }

            DeclaredMethod declaredMethod = statement.getInvokeExpr().getMethod();
            Collection methods =
                    MatcherUtils.getMatchingCryslMethodsToDeclaredMethod(
                            definition.getRule(), declaredMethod);

            for (CrySLMethod method : methods) {
                injectQueryAtCallSite(statement, method);
            }
        }

        for (ExtractParameterQuery query : queries) {
            definition.getAnalysisReporter().beforeTriggeringBoomerangQuery(query);
            query.solve();
            definition.getAnalysisReporter().afterTriggeringBoomerangQuery(query);
        }
    }

    private void injectQueryAtCallSite(Statement statement, CrySLMethod method) {
        for (int i = 0; i < method.getParameters().size(); i++) {
            String parameter = method.getParameters().get(i).getKey();

            addQueryAtCallSite(statement, parameter, i);
        }
    }

    private void addQueryAtCallSite(Statement statement, String varNameInSpec, int index) {
        Val parameter = statement.getInvokeExpr().getArg(index);

        Collection predecessors =
                statement.getMethod().getControlFlowGraph().getPredsOf(statement);
        for (Statement pred : predecessors) {
            ControlFlowGraph.Edge edge = new ControlFlowGraph.Edge(pred, statement);

            ExtractParameterQuery query =
                    new ExtractParameterQuery(definition, edge, parameter, index);
            query.addListener(
                    results -> {
                        Collection> extractedParameters = new HashSet<>();

                        Collection filteredQueries =
                                filterBoomerangResults(results.getAllocationSites().keySet());
                        for (ForwardQuery paramQuery : filteredQueries) {
                            Val val = paramQuery.var();

                            if (val instanceof AllocVal allocVal) {
                                Map.Entry entry =
                                        new AbstractMap.SimpleEntry<>(
                                                allocVal.getAllocVal(),
                                                paramQuery.cfgEdge().getStart());
                                extractedParameters.add(entry);
                            } else {
                                Map.Entry entry =
                                        new AbstractMap.SimpleEntry<>(
                                                val, paramQuery.cfgEdge().getStart());
                                extractedParameters.add(entry);
                            }
                        }

                        CallSiteWithParamIndex callSiteWithParam =
                                new CallSiteWithParamIndex(statement, index, varNameInSpec);
                        Collection types = results.getPropagationType();

                        // If no value could be extracted, add the zero value to indicate it
                        if (extractedParameters.isEmpty()) {
                            ExtractedValue zeroVal =
                                    new ExtractedValue(Val.zero(), statement, types);

                            CallSiteWithExtractedValue callSite =
                                    new CallSiteWithExtractedValue(callSiteWithParam, zeroVal);
                            collectedValues.add(callSite);
                            return;
                        }

                        for (Map.Entry entry : extractedParameters) {
                            // The extracted value may be transformed, i.e. not the propagated type
                            types.add(entry.getKey().getType());

                            ExtractedValue extractedValue =
                                    new ExtractedValue(entry.getKey(), entry.getValue(), types);

                            CallSiteWithExtractedValue callSite =
                                    new CallSiteWithExtractedValue(
                                            callSiteWithParam, extractedValue);
                            collectedValues.add(callSite);
                        }
                    });
            queries.add(query);
        }
    }

    private Collection filterBoomerangResults(
            Collection resultQueries) {
        Collection transformedQueries = new HashSet<>();

        for (ForwardQuery query : resultQueries) {
            Val val = query.var();

            if (val instanceof TransformedAllocVal) {
                transformedQueries.add(query);
            }
        }

        if (transformedQueries.isEmpty()) {
            return resultQueries;
        }

        return transformedQueries;
    }

    public Collection getExtractedValues() {
        return collectedValues;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy