This repository has been archived by the owner on Nov 3, 2023. It is now read-only.
/
ExecutionPathFactory.cs
99 lines (89 loc) · 2.47 KB
/
ExecutionPathFactory.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace Gendarme.Rules.Exceptions.Impl {
internal sealed class ExecutionPathFactory {
const int MaxLimit = 1000;
public ExecutionPathFactory ()
{
}
public IList<ExecutionPathCollection> CreatePaths (Instruction start, Instruction end)
{
if (start == null)
throw new ArgumentNullException ("start");
List<ExecutionPathCollection> paths = new List<ExecutionPathCollection> ();
CreatePathHelper (start, end, new ExecutionPathCollection (), paths);
// we were not able to build all code paths within a reasonable amount of memory
if (paths.Count >= MaxLimit)
paths.Clear ();
return paths;
}
private void CreatePathHelper (Instruction start, Instruction end,
ExecutionPathCollection path, List<ExecutionPathCollection> completedPaths)
{
if (completedPaths.Count >= MaxLimit)
return;
ExecutionBlock curBlock = new ExecutionBlock ();
curBlock.First = start;
Instruction cur = start;
bool stop = false;
do {
switch (cur.OpCode.FlowControl) {
case FlowControl.Branch:
case FlowControl.Cond_Branch:
if (cur.OpCode == OpCodes.Switch) {
Instruction[] targetOffsets = (Instruction[])cur.Operand;
foreach (Instruction target in targetOffsets) {
if (!path.Contains (target)) {
curBlock.Last = cur;
path.Add (curBlock);
CreatePathHelper (target,
end,
path.Clone (),
completedPaths);
}
}
stop = true;
} else if (cur.OpCode == OpCodes.Leave ||
cur.OpCode == OpCodes.Leave_S) {
curBlock.Last = cur;
path.Add (curBlock);
completedPaths.Add (path);
stop = true;
break;
} else {
Instruction target = (Instruction)cur.Operand;
if (!path.Contains (target)) {
curBlock.Last = cur;
path.Add (curBlock);
CreatePathHelper (target,
end,
path.Clone (),
completedPaths);
}
if (!path.Contains (cur.Next)) {
curBlock = new ExecutionBlock ();
curBlock.First = cur.Next;
} else {
stop = true;
}
}
break;
case FlowControl.Throw:
case FlowControl.Return:
curBlock.Last = cur;
path.Add (curBlock);
completedPaths.Add (path);
stop = true;
break;
}
if (cur.Next != null && cur != end && !stop)
cur = cur.Next;
else
stop = true;
}
while (!stop);
}
}
}