Package dk.brics.xact.analysis.soot

Source Code of dk.brics.xact.analysis.soot.PutStringSources

package dk.brics.xact.analysis.soot;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import soot.ArrayType;
import soot.NullType;
import soot.RefType;
import soot.SootClass;
import soot.SootMethod;
import soot.Type;
import soot.ValueBox;
import soot.jimple.FieldRef;
import soot.jimple.InvokeExpr;
import dk.brics.automaton.Automaton;
import dk.brics.automaton.Datatypes;
import dk.brics.misc.Origin;
import dk.brics.string.StringAnalysis;
import dk.brics.string.external.FieldResolution;
import dk.brics.string.external.MethodResolution;
import dk.brics.string.external.Resolver;
import dk.brics.xact.XMLValidationException;
import dk.brics.xact.analysis.Debug;
import dk.brics.xact.analysis.config.Configuration;
import dk.brics.xact.analysis.flowgraph.FlowGraph;
import dk.brics.xact.analysis.flowgraph.Statement;
import dk.brics.xact.analysis.flowgraph.statements.ArrayWriteStringStm;
import dk.brics.xact.analysis.flowgraph.statements.BasicStatementVisitor;
import dk.brics.xact.analysis.flowgraph.statements.InsertStm;
import dk.brics.xact.analysis.flowgraph.statements.NodeStm;
import dk.brics.xact.analysis.flowgraph.statements.PlugStm;
import dk.brics.xact.analysis.flowgraph.statements.SetStm;

/**
* Runs the string analysis and replaces the string sources of certain statements.
*/
public class PutStringSources {
 
  private StringAnalysis sa;
  private TranslatorContext context;
  private FlowGraph graph;
  private Configuration config;
 
  public PutStringSources(FlowGraph g, TranslatorContext context, Configuration config) {
    this.graph = g;
    this.context = context;
    this.config = config;
  }
 
  /**
   * Runs string analysis with hotspots that are relevant for XACT operations.
   * This method is <i>not</i> thread-safe (because of Soot).
   */
  public void analyzeStrings() {
    dk.brics.string.Debug.init();
    Debug.println(1, true, "Running string analysis...");
    StringAnalysis.clearResolvers();
    StringAnalysis.addResolver(new Resolver() {
      public MethodResolution resolveMethod(InvokeExpr e, SootMethod m) {
        String sig = m.getSignature();
        if (sig.equals("<dk.brics.xact.XML: java.lang.String getString(java.lang.String)>") ||
            sig.equals("<dk.brics.xact.XML: java.lang.String getString()>")) {
          Automaton a = Datatypes.get("string"); // TODO: should use the XML graph (run twice!?)
          return new MethodResolution(e.getArgCount(), a);
        }
        // TODO methods taking an Iterable or array should not corrupt the argument
        if (sig.equals("<dk.brics.xact.XML: dk.brics.xact.XML concat(java.lang.Object[])>")) {
          MethodResolution r = new MethodResolution(1, Automaton.makeAnyString());
          r.setArgumentCorrupted(0, false);
          return r;
        }
        return null;
      }
      public FieldResolution resolveField(FieldRef f) {
        return null;
      }
      public Automaton resolveToString(SootClass clazz) {
        return config.resolveToString(clazz);
      }
    });
    Set<ValueBox> hots = new HashSet<ValueBox>();
    for (Statement stm : graph.getNodes()) {
      if (context.getStringHotspot1(stm) != null)
        hots.add(context.getStringHotspot1(stm));
      if (context.getStringHotspot2(stm) != null)
        hots.add(context.getStringHotspot2(stm));
    }
    sa = new StringAnalysis(
        hots,
        null,
        null,
        null,
        null,
        false); // <-- this argument means "do not unload soot"
    Debug.println(1, true, "Extracting strings...");
    for (Statement xstm : new ArrayList<Statement>(graph.getNodes())) {
      xstm.visitBy(new BasicStatementVisitor() {
        @Override
        public void visitArrayWriteStringStm(ArrayWriteStringStm s) {
          s.setStringsrc(getAutomatonFromObjectExp(context.getStringHotspot1(s)));
        }
//        @Override // set in ArrayTransformer
//        public void visitConcatStm(ConcatStm s) {
//          s.setStringSource(getAutomatonFromObjectExp(context.getHotspot1(s)));
//        }
        @Override
        public void visitInsertStm(InsertStm s) {
          if (context.getStringHotspot1(s) != null)
            s.setStringSource(getAutomatonFromObjectExp(context.getStringHotspot1(s)));
        }
        @Override
        public void visitNodeStm(NodeStm s) {
          if (context.getStringHotspot1(s) != null)
            s.setName(getAutomatonFromStringExp(context.getStringHotspot1(s), s.getOrigin()));
          if (context.getStringHotspot2(s) != null)
            s.setValue(getAutomatonFromStringExp(context.getStringHotspot2(s), s.getOrigin()));
          if (s.getName() != null && context.getNamespace(s) != null)
            s.setName(Automaton.makeString('{' + context.getNamespace(s) + '}').concatenate(s.getName()));
        }
        @Override
        public void visitPlugStm(PlugStm s) {
          if (context.getStringHotspot1(s) != null)
            s.setStringSource(getAutomatonFromObjectExp(context.getStringHotspot1(s)));
        }
        @Override
        public void visitSetStm(SetStm s) {
          if (context.getStringHotspot1(s) != null)
            s.setStringSource(getAutomatonFromObjectExp(context.getStringHotspot1(s)));
        }
      });
    }
    Debug.println(1, true, "String analysis completed.");
  }
 
  public Automaton getAutomatonFromStringExp(ValueBox b, Origin origin) {
    if (b.getValue().getType() instanceof NullType)
      return Automaton.makeString("null");
    if (!TranslatorContext.isStringType(b))
      throw new XMLValidationException("String expression expected " + b, origin);
    return sa.getAutomaton(b);
  }
  public Automaton getAutomatonFromObjectExp(ValueBox b) { // TODO: cache results of getAutomatonFromObjectExp?
    Type t = b.getValue().getType();
    if (t instanceof NullType)
      return Automaton.makeString("null");
    while (t instanceof ArrayType)
      t = ((ArrayType) t).getElementType();
    if (t instanceof RefType) {
      if (t.equals(RefType.v("java.lang.String")) || t.equals(RefType.v("java.lang.Object"))) { // for (arrays of) String, ask the string analyzer
        return sa.getAutomaton(b);
      } else { // for other reference types, take the union of the type automata for the possible types
        List<Automaton> auts = new ArrayList<Automaton>();
        for (SootClass sc : context.getSubclassesOfIncluding((RefType)t))
          if (!context.implementsToXMLable(sc))
            auts.add(sa.getTypeAutomaton(sc.getType()));
        return Automaton.union(auts); // TODO: minimize?
      }
    } else {
      throw new RuntimeException("RefType expected. Instead got " + t); // unreachable
    }
  }
}
TOP

Related Classes of dk.brics.xact.analysis.soot.PutStringSources

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.