18
18
19
19
package proguard .analysis .cpa .jvm .cfa .visitors ;
20
20
21
- import java .util .Arrays ;
22
- import java .util .LinkedHashSet ;
23
- import java .util .Optional ;
24
- import java .util .Set ;
25
- import java .util .stream .Collectors ;
26
21
import org .apache .logging .log4j .LogManager ;
27
22
import org .apache .logging .log4j .Logger ;
23
+ import proguard .analysis .cpa .jvm .cfa .JvmCfa ;
24
+ import proguard .analysis .cpa .jvm .cfa .edges .JvmAssumeCaseCfaEdge ;
25
+ import proguard .analysis .cpa .jvm .cfa .edges .JvmAssumeCfaEdge ;
26
+ import proguard .analysis .cpa .jvm .cfa .edges .JvmAssumeDefaultCfaEdge ;
27
+ import proguard .analysis .cpa .jvm .cfa .edges .JvmAssumeExceptionCfaEdge ;
28
+ import proguard .analysis .cpa .jvm .cfa .edges .JvmCfaEdge ;
29
+ import proguard .analysis .cpa .jvm .cfa .edges .JvmInstructionCfaEdge ;
30
+ import proguard .analysis .cpa .jvm .cfa .nodes .JvmCatchCfaNode ;
31
+ import proguard .analysis .cpa .jvm .cfa .nodes .JvmCfaNode ;
32
+ import proguard .analysis .cpa .jvm .cfa .nodes .JvmUnknownCfaNode ;
28
33
import proguard .classfile .Clazz ;
29
34
import proguard .classfile .Method ;
30
35
import proguard .classfile .MethodSignature ;
41
46
import proguard .classfile .instruction .TableSwitchInstruction ;
42
47
import proguard .classfile .instruction .VariableInstruction ;
43
48
import proguard .classfile .instruction .visitor .InstructionVisitor ;
44
- import proguard .analysis .cpa .defaults .Cfa ;
45
- import proguard .analysis .cpa .jvm .cfa .JvmCfa ;
46
- import proguard .analysis .cpa .jvm .cfa .edges .JvmAssumeCaseCfaEdge ;
47
- import proguard .analysis .cpa .jvm .cfa .edges .JvmAssumeCfaEdge ;
48
- import proguard .analysis .cpa .jvm .cfa .edges .JvmAssumeDefaultCfaEdge ;
49
- import proguard .analysis .cpa .jvm .cfa .edges .JvmAssumeExceptionCfaEdge ;
50
- import proguard .analysis .cpa .jvm .cfa .edges .JvmCfaEdge ;
51
- import proguard .analysis .cpa .jvm .cfa .edges .JvmInstructionCfaEdge ;
52
- import proguard .analysis .cpa .jvm .cfa .nodes .JvmCatchCfaNode ;
53
- import proguard .analysis .cpa .jvm .cfa .nodes .JvmCfaNode ;
54
- import proguard .analysis .cpa .jvm .cfa .nodes .JvmUnknownCfaNode ;
49
+
50
+ import java .util .Arrays ;
51
+ import java .util .LinkedHashSet ;
52
+ import java .util .Optional ;
53
+ import java .util .Set ;
54
+ import java .util .stream .Collectors ;
55
55
56
56
/**
57
57
* This {@link AttributeVisitor} visits the {@link CodeAttribute} of a {@link Method} and performs two different tasks:
@@ -72,30 +72,28 @@ public class JvmIntraproceduralCfaFillerAllInstructionVisitor
72
72
implements AttributeVisitor
73
73
{
74
74
75
- private final Cfa < JvmCfaNode , JvmCfaEdge , MethodSignature > cfa ;
76
- private static final Logger log = LogManager .getLogger (JvmIntraproceduralCfaFillerAllInstructionVisitor .class );
75
+ private final JvmCfa cfa ;
76
+ private static final Logger log = LogManager .getLogger (JvmIntraproceduralCfaFillerAllInstructionVisitor .class );
77
77
78
78
public JvmIntraproceduralCfaFillerAllInstructionVisitor (JvmCfa cfa )
79
79
{
80
80
this .cfa = cfa ;
81
81
}
82
82
83
+ @ Override
83
84
public void visitAnyAttribute (Clazz clazz , Attribute attribute )
84
85
{
85
86
}
86
87
88
+ @ Override
87
89
public void visitCodeAttribute (Clazz clazz , Method method , CodeAttribute codeAttribute )
88
90
{
89
91
MethodSignature signature = MethodSignature .computeIfAbsent (clazz , method );
90
92
91
93
generateCatchNodes (signature , codeAttribute , clazz );
92
94
93
- JvmIntraproceduralCfaFillerVisitor instructionVisitor = new JvmIntraproceduralCfaFillerVisitor ((JvmCfa ) cfa );
94
-
95
- instructionVisitor .setSignature (signature );
96
-
97
95
// visit all the instructions of the current method
98
- codeAttribute .instructionsAccept (clazz , method , instructionVisitor );
96
+ codeAttribute .instructionsAccept (clazz , method , new JvmIntraproceduralCfaFillerVisitor ( signature , cfa ) );
99
97
}
100
98
101
99
private void generateCatchNodes (MethodSignature signature , CodeAttribute codeAttribute , Clazz clazz )
@@ -105,9 +103,10 @@ private void generateCatchNodes(MethodSignature signature, CodeAttribute codeAtt
105
103
if (codeAttribute .exceptionTable != null )
106
104
{
107
105
// get the position of all handlers, use a LinkedHashSet to remove duplicates and keep order
108
- Set <Integer > handlersOffset = new LinkedHashSet <>(Arrays .stream (codeAttribute .exceptionTable )
109
- .map (x -> x .u2handlerPC )
110
- .collect (Collectors .toList ()));
106
+ Set <Integer > handlersOffset =
107
+ Arrays .stream (codeAttribute .exceptionTable )
108
+ .map (x -> x .u2handlerPC )
109
+ .collect (Collectors .toCollection (LinkedHashSet ::new ));
111
110
112
111
// create the nodes for code locations at beginning of catch/finally statement
113
112
for (int handlerOffset : handlersOffset )
@@ -119,11 +118,11 @@ private void generateCatchNodes(MethodSignature signature, CodeAttribute codeAtt
119
118
.findFirst ()
120
119
.get ().u2catchType ,
121
120
clazz );
122
- (( JvmCfa ) cfa ) .addFunctionCatchNode (signature , catchNode , handlerOffset );
121
+ cfa .addFunctionCatchNode (signature , catchNode , handlerOffset );
123
122
124
123
// link the catch node to the starting node of the handler block with a true exception assumption
125
124
new JvmAssumeExceptionCfaEdge (catchNode ,
126
- (( JvmCfa ) cfa ) .addNodeIfAbsent (signature , handlerOffset , clazz ),
125
+ cfa .addNodeIfAbsent (signature , handlerOffset , clazz ),
127
126
true ,
128
127
catchNode .getCatchType ());
129
128
}
@@ -150,8 +149,8 @@ private void generateCatchNodes(MethodSignature signature, CodeAttribute codeAtt
150
149
{
151
150
// if there is a following catch block we link it with a false assume exception edge with the previous catch node type
152
151
// i.e. the following catch block is considered only if the exception is not caught by the block before
153
- JvmCatchCfaNode currNode = (( JvmCfa ) cfa ) .getFunctionCatchNode (signature , currHandlerOffset );
154
- JvmCatchCfaNode nextNode = (( JvmCfa ) cfa ) .getFunctionCatchNode (signature , followingCatch .get ().u2handlerPC );
152
+ JvmCatchCfaNode currNode = cfa .getFunctionCatchNode (signature , currHandlerOffset );
153
+ JvmCatchCfaNode nextNode = cfa .getFunctionCatchNode (signature , followingCatch .get ().u2handlerPC );
155
154
156
155
new JvmAssumeExceptionCfaEdge (currNode ,
157
156
nextNode ,
@@ -165,11 +164,11 @@ private void generateCatchNodes(MethodSignature signature, CodeAttribute codeAtt
165
164
166
165
// if the last node of a catch chain (i.e. linked only to the beginning of the corresponding catch block and not to other catch nodes)is not a `finally` (catch type == 0) which always throws
167
166
// an exception in the end, add an edge to the exception exit block, since this is an intra-procedural implementation
168
- for (JvmCatchCfaNode node : (( JvmCfa ) cfa ) .getFunctionCatchNodes (signature ))
167
+ for (JvmCatchCfaNode node : cfa .getFunctionCatchNodes (signature ))
169
168
{
170
169
if (node .getLeavingEdges ().size () == 1 && node .getCatchType () != 0 )
171
170
{
172
- JvmCfaNode exitNode = (( JvmCfa ) cfa ) .getFunctionExceptionExitNode (signature , clazz );
171
+ JvmCfaNode exitNode = cfa .getFunctionExceptionExitNode (signature , clazz );
173
172
174
173
// add edge for exception not caught
175
174
new JvmAssumeExceptionCfaEdge (node , exitNode , false , node .getCatchType ());
@@ -182,21 +181,22 @@ private void generateCatchNodes(MethodSignature signature, CodeAttribute codeAtt
182
181
* plus eventual additional nodes (i.e. in case of a branch instruction a node for the code location of the jump is added).
183
182
*
184
183
* <p>The edge from the previously visited instruction is linked to the current instruction if the control flows from one to the other (e.g. the previous edge is linked if it represents an iadd
185
- * instruction but it's not if it represents a goto instruction).
184
+ * instruction but not if it represents a goto instruction).
186
185
*
187
186
* @author Carlo Alberto Pozzoli
188
187
*/
189
- private class JvmIntraproceduralCfaFillerVisitor
188
+ private static class JvmIntraproceduralCfaFillerVisitor
190
189
implements InstructionVisitor
191
190
{
192
191
193
- private final Cfa < JvmCfaNode , JvmCfaEdge , MethodSignature > cfa ;
194
- private MethodSignature signature ;
195
- private JvmCfaEdge previousEdge ;
192
+ private final JvmCfa cfa ;
193
+ private final MethodSignature signature ;
194
+ private JvmCfaEdge previousEdge ;
196
195
197
- public JvmIntraproceduralCfaFillerVisitor (JvmCfa cfa )
196
+ public JvmIntraproceduralCfaFillerVisitor (MethodSignature methodSignature , JvmCfa cfa )
198
197
{
199
- this .cfa = cfa ;
198
+ this .signature = methodSignature ;
199
+ this .cfa = cfa ;
200
200
}
201
201
202
202
@ Override
@@ -275,11 +275,6 @@ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute
275
275
}
276
276
}
277
277
278
- public void setSignature (MethodSignature signature )
279
- {
280
- this .signature = signature ;
281
- }
282
-
283
278
/**
284
279
* Performs the default operations needed for each instruction, must be called by all the other specific addNode methods:
285
280
*
@@ -289,7 +284,7 @@ public void setSignature(MethodSignature signature)
289
284
*/
290
285
private JvmCfaNode connect (int offset , Clazz clazz )
291
286
{
292
- JvmCfaNode currentNode = (( JvmCfa ) cfa ) .addNodeIfAbsent (signature , offset , clazz );
287
+ JvmCfaNode currentNode = cfa .addNodeIfAbsent (signature , offset , clazz );
293
288
294
289
if (previousEdge != null )
295
290
{
@@ -322,7 +317,7 @@ private void connectReturn(int offset, Clazz clazz, CodeAttribute methodCode)
322
317
// next instruction will not continue the control flow
323
318
previousEdge = null ;
324
319
325
- JvmCfaNode exitNode = (( JvmCfa ) cfa ) .getFunctionReturnExitNode (signature , clazz );
320
+ JvmCfaNode exitNode = cfa .getFunctionReturnExitNode (signature , clazz );
326
321
327
322
// create and add edge to nodes
328
323
new JvmInstructionCfaEdge (currentNode , exitNode , methodCode , offset );
@@ -356,7 +351,7 @@ private void connectGoto(int offset, Clazz clazz, CodeAttribute methodCode, Bran
356
351
int branchTarget = offset + instruction .branchOffset ;
357
352
358
353
// get the goto location node
359
- JvmCfaNode jumpNode = (( JvmCfa ) cfa ) .addNodeIfAbsent (signature , branchTarget , clazz );
354
+ JvmCfaNode jumpNode = cfa .addNodeIfAbsent (signature , branchTarget , clazz );
360
355
361
356
// create and add edge to nodes
362
357
new JvmInstructionCfaEdge (currentNode , jumpNode , methodCode , offset );
@@ -376,7 +371,7 @@ private void connectBranch(int offset, Clazz clazz, CodeAttribute methodCode, Br
376
371
// create the branch taken edge with the corresponding node
377
372
int branchTarget = offset + instruction .branchOffset ;
378
373
379
- JvmCfaNode jumpNode = (( JvmCfa ) cfa ) .addNodeIfAbsent (signature , branchTarget , clazz );
374
+ JvmCfaNode jumpNode = cfa .addNodeIfAbsent (signature , branchTarget , clazz );
380
375
381
376
new JvmAssumeCfaEdge (currentNode , jumpNode , methodCode , offset , true );
382
377
}
@@ -400,7 +395,7 @@ private void connectSwitch(int offset, Clazz clazz, CodeAttribute methodCode, Sw
400
395
// add the default node/edge pair
401
396
int branchTarget = offset + instruction .defaultOffset ;
402
397
403
- JvmCfaNode jumpNode = (( JvmCfa ) cfa ) .addNodeIfAbsent (signature , branchTarget , clazz );
398
+ JvmCfaNode jumpNode = cfa .addNodeIfAbsent (signature , branchTarget , clazz );
404
399
405
400
new JvmAssumeDefaultCfaEdge (currentNode , jumpNode , methodCode , offset );
406
401
@@ -410,7 +405,7 @@ private void connectSwitch(int offset, Clazz clazz, CodeAttribute methodCode, Sw
410
405
branchTarget = offset + instruction .jumpOffsets [index ];
411
406
int caseAssumption = instruction instanceof TableSwitchInstruction ? ((TableSwitchInstruction ) instruction ).lowCase + index : ((LookUpSwitchInstruction ) instruction ).cases [index ];
412
407
413
- jumpNode = (( JvmCfa ) cfa ) .addNodeIfAbsent (signature , branchTarget , clazz );
408
+ jumpNode = cfa .addNodeIfAbsent (signature , branchTarget , clazz );
414
409
415
410
new JvmAssumeCaseCfaEdge (currentNode , jumpNode , methodCode , offset , caseAssumption );
416
411
}
@@ -443,12 +438,12 @@ private void connectThrow(int offset, Clazz clazz, CodeAttribute methodCode)
443
438
// link edge to the first catch block
444
439
if (firstCatch .isPresent ())
445
440
{
446
- new JvmInstructionCfaEdge (currentNode , (( JvmCfa ) cfa ) .getFunctionCatchNode (signature , firstCatch .get ().u2handlerPC ), methodCode , offset );
441
+ new JvmInstructionCfaEdge (currentNode , cfa .getFunctionCatchNode (signature , firstCatch .get ().u2handlerPC ), methodCode , offset );
447
442
}
448
443
// since this is an intra-procedural implementation if the thrown exception is not caught just add an edge to the exception exit node
449
444
else
450
445
{
451
- JvmCfaNode exitNode = (( JvmCfa ) cfa ) .getFunctionExceptionExitNode (signature , clazz );
446
+ JvmCfaNode exitNode = cfa .getFunctionExceptionExitNode (signature , clazz );
452
447
453
448
// add edge for the throw instruction
454
449
new JvmInstructionCfaEdge (currentNode , exitNode , methodCode , offset );
0 commit comments