Writing log to /Users/yuntsy/My/Projects/Java/WebAnalyzer/output/tai-e.log
java.version: 17.0.11
java.version.date: 2024-04-16
java.runtime.version: 17.0.11+7-LTS-207
java.vendor: Oracle Corporation
java.vendor.version: null
os.name: Mac OS X
os.version: 26.1
os.arch: aarch64
Tai-e Version: 0.5.2-SNAPSHOT
Tai-e Commit: 3f3b802611bf6b8187abc1785e6c5d08a4cf5a4a
Writing analysis plan to /Users/yuntsy/My/Projects/Java/WebAnalyzer/output/tai-e-plan.yml
WorldBuilder starts ...
Warning: main class was not given!
10231 classes with 100939 methods in the world
WorldBuilder finishes, elapsed time: 1.93s
ir-dumper starts ...
Dumping IR in /Users/yuntsy/My/Projects/Java/WebAnalyzer/output/tir
28 classes in scope (APP) of class analyses
ir-dumper finishes, elapsed time: 0.03s
routerAnalysis starts ...
Router analysis started at: 2025-11-11 20:03:31
Router analysis completed at: 2025-11-11 20:03:31 (Duration: 4ms)
routerAnalysis finishes, elapsed time: 0.00s
beanAnalysis starts ...
beanAnalysis finishes, elapsed time: 0.00s
injectPointsAnalysis starts ...
injectPointsAnalysis finishes, elapsed time: 0.00s
aspectAnalysis starts ...
Starting AOP aspect analysis...
aspectAnalysis finishes, elapsed time: 0.00s
pta starts ...
Loading taint config from /Users/yuntsy/My/Projects/Java/WebAnalyzer/configs/taint-config.yml
Cannot find source method '<javax.servlet.ServletRequestWrapper: java.lang.String getParameter(java.lang.String)>'
Cannot find source method '<org.example.springtest.CommandExecClass: java.lang.String index(jakarta.servlet.http.HttpServletRequest)>'
Cannot find sink method '<org.springframework.web.client.RestTemplate: org.springframework.http.ResponseEntity exchange(java.lang.String,org.springframework.http.HttpMethod,org.springframework.http.HttpEntity,java.lang.Class,java.lang.Object[])>'
Cannot find sink method '<org.example.springtest.FieldInjection: java.lang.String sayInjection()>'
TaintConfig:
sinks:
- { method: "<java.sql.Statement: java.sql.ResultSet executeQuery(java.lang.String)>", index: "0" }
- { method: "<java.sql.Connection: java.sql.PreparedStatement prepareStatement(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.String: void getChars(int,int,char[],int)>", from: "base", to: "2", type: "char[]" }
- { method: "<java.lang.String: java.lang.String format(java.lang.String,java.lang.Object[])>", from: "1[*]", to: "result", type: "java.lang.String" }
- { method: "<java.lang.StringBuffer: void <init>(java.lang.String)>", from: "0", to: "base", type: "java.lang.StringBuffer" }
- { 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.String)>", from: "0", to: "result", type: "java.lang.StringBuffer" }
- { method: "<java.lang.StringBuffer: java.lang.StringBuffer append(java.lang.String)>", from: "base", to: "result", type: "java.lang.StringBuffer" }
- { method: "<java.lang.StringBuffer: java.lang.String toString()>", from: "base", to: "result", type: "java.lang.String" }
- { method: "<java.lang.StringBuilder: void <init>(java.lang.String)>", from: "0", to: "base", type: "java.lang.StringBuilder" }
- { 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.String)>", from: "0", to: "result", type: "java.lang.StringBuilder" }
- { method: "<java.lang.StringBuilder: java.lang.StringBuilder append(java.lang.String)>", from: "base", to: "result", type: "java.lang.StringBuilder" }
- { method: "<java.lang.StringBuilder: java.lang.String toString()>", from: "base", to: "result", type: "java.lang.String" }
callSiteMode: true
Add entry point (empty params): <org.example.springtarget.di.entry.controller.RestControllerEntry: java.lang.String requestMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.RestControllerEntry: java.lang.String defaultMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.RestControllerEntry: java.lang.String getMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.RestControllerEntry: java.lang.String postMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.RestControllerEntry: java.lang.String putMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.RestControllerEntry: java.lang.String deleteMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.RestControllerEntry: java.lang.String patchMapping()>
Added entry point (with params): <org.example.springtarget.di.entry.controller.RestControllerEntry: java.lang.String pathVariable(java.lang.Long)>
Added entry point (with params): <org.example.springtarget.di.entry.controller.RestControllerEntry: java.lang.String requestParameter(java.lang.String)>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.ControllerEntry: java.lang.String requestMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.ControllerEntry: java.lang.String getMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.ControllerEntry: java.lang.String postMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.ControllerEntry: java.lang.String putMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.ControllerEntry: java.lang.String deleteMapping()>
Add entry point (empty params): <org.example.springtarget.di.entry.controller.ControllerEntry: java.lang.String patchMapping()>
Added entry point (with params): <org.example.springtarget.di.entry.controller.ControllerEntry: java.lang.String pathVariable(java.lang.Long)>
Added entry point (with params): <org.example.springtarget.di.entry.controller.ControllerEntry: java.lang.String requestParameter(java.lang.String)>
Add entry point (empty params): <org.example.springtarget.example.UserController: void createOrder()>
Added entry point (with params): <org.example.springtarget.example.UserController: void getUser(jakarta.servlet.http.HttpServletRequest)>
Add entry point (empty params): <org.example.springtarget.example.UserController: void getUserAndId()>
Add entry point (empty params): <org.example.springtarget.example.UserController: void getServiceBeanMessage()>
ๆนๆณ <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)> ๅน้
ๅ็น: bean(orderService)
็ปๅ
ฅๅ้ข: org.example.springtarget.example.LogAspect -> ้็ฅ็ฑปๅ: AROUND -> ็ฎๆ ๆนๆณ: <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)>
ๆนๆณ <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)> ๅน้
ๅ็น: @within(org.springframework.stereotype.Service)
็ปๅ
ฅๅ้ข: org.example.springtarget.example.LogAspect -> ้็ฅ็ฑปๅ: AFTER -> ็ฎๆ ๆนๆณ: <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)>
ๆนๆณ <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)> ๅน้
ๅ็น: execution(* org.example.springtarget.example.OrderService.createOrder(..))
็ปๅ
ฅๅ้ข: org.example.springtarget.example.LogAspect -> ้็ฅ็ฑปๅ: BEFORE -> ็ฎๆ ๆนๆณ: <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)>
็ปๅ
ฅๅ้ข: org.example.springtarget.example.LogAspect -> ้็ฅ็ฑปๅ: AFTER_RETURNING -> ็ฎๆ ๆนๆณ: <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)>
็ปๅ
ฅๅ้ข: org.example.springtarget.example.LogAspect -> ้็ฅ็ฑปๅ: AFTER_THROWING -> ็ฎๆ ๆนๆณ: <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)>
โ ๅค็ AOP ่ฐ็จ่พน: <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)> -> <org.example.springtarget.example.LogAspect: java.lang.Object aroundAdvice(org.aspectj.lang.ProceedingJoinPoint)>, ้็ฅ็ฑปๅ: AROUND
โ ๅค็ AOP ่ฐ็จ่พน: <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)> -> <org.example.springtarget.example.LogAspect: void afterAdvice(org.aspectj.lang.JoinPoint)>, ้็ฅ็ฑปๅ: AFTER
โ ๅค็ AOP ่ฐ็จ่พน: <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)> -> <org.example.springtarget.example.LogAspect: void beforeAdvice(org.aspectj.lang.JoinPoint)>, ้็ฅ็ฑปๅ: BEFORE
โ ๅค็ AOP ่ฐ็จ่พน: <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)> -> <org.example.springtarget.example.LogAspect: void afterReturningAdvice(java.lang.Object)>, ้็ฅ็ฑปๅ: AFTER_RETURNING
โ ๅค็ AOP ่ฐ็จ่พน: <org.example.springtarget.example.OrderService: void createOrder(java.lang.String)> -> <org.example.springtarget.example.LogAspect: void afterThrowingAdvice(java.lang.Exception)>, ้็ฅ็ฑปๅ: AFTER_THROWING
ๆนๆณ <org.example.springtarget.example.UserServiceImpl: java.lang.String getUser()> ๅน้
ๅ็น: @within(org.springframework.stereotype.Service)
็ปๅ
ฅๅ้ข: org.example.springtarget.example.LogAspect -> ้็ฅ็ฑปๅ: AFTER -> ็ฎๆ ๆนๆณ: <org.example.springtarget.example.UserServiceImpl: java.lang.String getUser()>
โ ๅค็ AOP ่ฐ็จ่พน: <org.example.springtarget.example.UserServiceImpl: java.lang.String getUser()> -> <org.example.springtarget.example.LogAspect: void afterAdvice(org.aspectj.lang.JoinPoint)>, ้็ฅ็ฑปๅ: AFTER
ๆนๆณ <org.example.springtarget.example.UserServiceAbstractImpl: java.lang.String getUser()> ๅน้
ๅ็น: @within(org.springframework.stereotype.Service)
็ปๅ
ฅๅ้ข: org.example.springtarget.example.LogAspect -> ้็ฅ็ฑปๅ: AFTER -> ็ฎๆ ๆนๆณ: <org.example.springtarget.example.UserServiceAbstractImpl: java.lang.String getUser()>
โ ๅค็ AOP ่ฐ็จ่พน: <org.example.springtarget.example.UserServiceAbstractImpl: java.lang.String getUser()> -> <org.example.springtarget.example.LogAspect: void afterAdvice(org.aspectj.lang.JoinPoint)>, ้็ฅ็ฑปๅ: AFTER
ๆนๆณ <org.example.springtarget.example.UserServiceImpl: java.lang.String getId()> ๅน้
ๅ็น: @within(org.springframework.stereotype.Service)
็ปๅ
ฅๅ้ข: org.example.springtarget.example.LogAspect -> ้็ฅ็ฑปๅ: AFTER -> ็ฎๆ ๆนๆณ: <org.example.springtarget.example.UserServiceImpl: java.lang.String getId()>
โ ๅค็ AOP ่ฐ็จ่พน: <org.example.springtarget.example.UserServiceImpl: java.lang.String getId()> -> <org.example.springtarget.example.LogAspect: void afterAdvice(org.aspectj.lang.JoinPoint)>, ้็ฅ็ฑปๅ: AFTER
ๆนๆณ <org.example.springtarget.di.beans.ServiceBeanImpl2: java.lang.String getMessage()> ๅน้
ๅ็น: @within(org.springframework.stereotype.Service)
็ปๅ
ฅๅ้ข: org.example.springtarget.example.LogAspect -> ้็ฅ็ฑปๅ: AFTER -> ็ฎๆ ๆนๆณ: <org.example.springtarget.di.beans.ServiceBeanImpl2: java.lang.String getMessage()>
โ ๅค็ AOP ่ฐ็จ่พน: <org.example.springtarget.di.beans.ServiceBeanImpl2: java.lang.String getMessage()> -> <org.example.springtarget.example.LogAspect: void afterAdvice(org.aspectj.lang.JoinPoint)>, ้็ฅ็ฑปๅ: AFTER
[Pointer analysis] elapsed time: 0.02s
Detected 0 taint flow(s):
TFGDumper starts ...
Source nodes:
Sink nodes:
Dumping /Users/yuntsy/My/Projects/Java/WebAnalyzer/output/taint-flow-graph.dot
TFGDumper finishes, elapsed time: 0.00s
-------------- Pointer analysis statistics: --------------
#var pointers: 71 (insens) / 91 (sens)
#objects: 27 (insens) / 27 (sens)
#var points-to: 54 (insens) / 60 (sens)
#static field points-to: 0 (sens)
#instance field points-to: 8 (sens)
#array points-to: 0 (sens)
#reachable methods: 39 (insens) / 45 (sens)
#call graph edges: 11 (insens) / 11 (sens)
----------------------------------------
1
pta finishes, elapsed time: 0.13s
cg starts ...
Call graph has 39 reachable methods and 11 edges
Dumping call graph to /Users/yuntsy/My/Projects/Java/WebAnalyzer/output/call-graph.dot
Dumping reachable methods to /Users/yuntsy/My/Projects/Java/WebAnalyzer/output/reachable-methods.txt
Dumping call edges to /Users/yuntsy/My/Projects/Java/WebAnalyzer/output/call-edges.txt
cg finishes, elapsed time: 0.01s
Tai-e finishes, elapsed time: 2.19s
๐ Overall Description
I'm using Tai-e to analyze Spring AOP functionality.
Spring dynamically creates proxy classes at runtime to intercept the createOrder()method, resulting in the actual call sequence:
beforeAdvice()->createOrder()->afterAdvice().I've implemented a plugin to analyze this call sequence:
In the weaveAdvice()method, I create
AOPEdgeand add it usingsolver.addCallEdge().The analysis successfully enters
DefaultSolverand inprocessCallEdge,callGraph.addEdge(edge)returnstrueHowever, in the final call graph output, only the calls inside
beforeAdvice():But the expected AOP edges like:
are not present in the output. It seems like
callGraph.addEdge(edge)is not working properly forAOPEdges?๐ฏ Expected Behavior
Edges like these should be included in the call graph.
๐ Current Behavior
Edges like these are not included in the call graph.
๐ Reproducible Example
No response
โ๏ธ Tai-e Arguments
๐ Click here to see Tai-e Options
๐ Click here to see Tai-e Analysis Plan
๐ Tai-e Log
๐ Click here to see Tai-e Log
โน๏ธ Additional Information
No response