Skip to content

Dataflow gap with static setter/getter + alias #28

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());
            }
          });
        }
      }
    };
  }

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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