Skip to content

Dataflow gap with static setter/getter + alias #28

Open
@tiganov

Description

@tiganov

I think I've found a case where Boomerang misses some dataflow (3.1.2).

The reproducer below is based on FlowDroid Listing 2 (PLDI '14), but uses a static setter/getter instead of direct field writes.

boomerangPDS/src/main/java/boomerang/example/BoomerangExampleTarget1.java

public class BoomerangExampleTarget1 {
  public static void main(String... args) {
    Data p = new Data();
    taintIt(customSource(), p);
  }

  private static String customSource() { return "I'm tainted"; }
  private static void customSink(String sunk) { System.out.println(sunk); }

  private static void taintIt(String in, Data out) {
    Data x = out;
    Data.setter(x, in);
    customSink(Data.getter(out));
  }

  static class Data {
    private String f;
    static void setter(Data self, String value) {
      self.f = value;
    }
    static String getter(Data self) {
      return self.f;
    }
  }
}

If I change Data.setter(x, in); to Data.setter(out, in);, then I get a path from the source to the sink.

boomerangPDS/src/main/java/boomerang/example/ExampleMain1.java: createAnalysisTransformer()

 private static Transformer createAnalysisTransformer() {
    return new SceneTransformer() {
      protected void internalTransform(
          String phaseName, @SuppressWarnings("rawtypes") Map options) {
        SootCallGraph sootCallGraph = new SootCallGraph();
        AnalysisScope scope =
            new AnalysisScope(sootCallGraph) {
              @Override
              protected Collection<? extends Query> generate(Edge cfgEdge) {
                Statement statement = cfgEdge.getStart();
                if (statement.toString().contains("customSource") && statement.containsInvokeExpr()) {
                  Val arg = statement.getLeftOp();
                  return Collections.singleton(new ForwardQuery(cfgEdge,
                          new AllocVal(arg, statement, arg)));
                }
                return Collections.emptySet();
              }
            };

        Boomerang solver =
            new Boomerang(
                sootCallGraph, SootDataFlowScope.make(Scene.v()), new DefaultBoomerangOptions() {
              @Override
              public int analysisTimeoutMS() {
                return 10000;
              }
            });

        Collection<Query> seeds = scope.computeSeeds();
        for (Query query : seeds) {
          System.out.println("Solving query: " + query);

          ForwardBoomerangResults<Weight.NoWeight> res = solver.solve((ForwardQuery) query);

          if (res.isTimedout()) {
            throw new RuntimeException("Timed out");
          }

          res.asStatementValWeightTable().cellSet().forEach(cell -> {
            if (cell.getRowKey().getStart().containsInvokeExpr() &&
                    cell.getRowKey().getStart().getInvokeExpr().getMethod().getName().contains("customSink") &&
                    cell.getRowKey().getStart().uses(cell.getColumnKey())) {
              System.out.println("SOURCE: " + query.cfgEdge().getStart().toString());
              System.out.println("SINK: " + cell.getRowKey().getStart().toString());
            }
          });
        }
      }
    };
  }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions