2
2
3
3
require_once './vendor/autoload.php ' ;
4
4
ini_set ('xdebug.max_nesting_level ' , 2000 );
5
+ require_once './BasicBlock.php ' ;
5
6
6
- @define ("JUMP_STATEMENT " , array ('Stmt_If ' ,'Stmt_Switch ' ,'Stmt_TryCatch ' ,'Expr_Ternary ' ,'Expr_BinaryOp_LogicalOr ' )) ;
7
- @define ("LOOP_STATEMENT " ,array ('Stmt_For ' ,'Stmt_While ' ,'Stmt_Foreach ' ,'Stmt_Do ' )) ;
8
- @define ("STOP_STATEMENT " ,array ('Stmt_Throw ' ,'Stmt_Break ' ,'Stmt_Continue ' )) ;
9
- @define ("RETURN_STATEMENT " ,array ('Stmt_Return ' )) ;
7
+
8
+ $ JUMP_STATEMENT = array ('Stmt_If ' ,'Stmt_Switch ' ,'Stmt_TryCatch ' ,'Expr_Ternary ' ,'Expr_BinaryOp_LogicalOr ' ) ;
9
+ $ LOOP_STATEMENT = array ('Stmt_For ' ,'Stmt_While ' ,'Stmt_Foreach ' ,'Stmt_Do ' ) ;
10
+ $ STOP_STATEMENT = array ('Stmt_Throw ' ,'Stmt_Break ' ,'Stmt_Continue ' ) ;
11
+ $ RETURN_STATEMENT = array ('Stmt_Return ' ) ;
10
12
11
13
use PhpParser \Node ;
12
14
@@ -35,15 +37,18 @@ public function getBranches($node){
35
37
36
38
//处理elseifs,elseifs为索引数组,由cond和stmts构成
37
39
$ elseifs = $ node ->elseifs ;
38
- foreach ($ elseifs as $ if ){
39
- $ if_branch = new Branch ($ if ->cond , $ if ->stmts ) ;
40
- array_push ($ branches ,$ if_branch ) ;
40
+ if ($ elseifs ){
41
+ foreach ($ elseifs as $ if ){
42
+ $ if_branch = new Branch ($ if ->cond , $ if ->stmts ) ;
43
+ array_push ($ branches ,$ if_branch ) ;
44
+ }
41
45
}
42
46
43
47
//处理else分支,由stmts组成,没有cond,这里的cond填为"else"
44
- $ if_branch = new Branch ('else ' , $ node ->stmts ) ;
45
- array_push ($ branches ,$ if_branch ) ;
46
-
48
+ if ($ node ->else ){
49
+ $ if_branch = new Branch ('else ' , $ node ->else ) ;
50
+ array_push ($ branches ,$ if_branch ) ;
51
+ }
47
52
break ;
48
53
49
54
case 'Stmt_Switch ' :
@@ -95,54 +100,139 @@ public function getBranches($node){
95
100
return $ branches ;
96
101
}
97
102
103
+ /**
104
+ * 处理循环结构,将循环变量添加到基本块
105
+ * @param unknown $node AST Node
106
+ * @param unknown $block BasicBlock
107
+ */
108
+ public function addLoopVariable ($ node ,$ block ){
109
+ switch ($ node ->getType ()){
110
+ case 'Stmt_For ' : //for(i=0;i<3;i++) ===> extract var i
111
+ $ block ->loop_var = $ node ->init [0 ] ;
112
+ break ;
113
+ case 'Stmt_While ' : //while(cond) ====> extract cond
114
+ $ block ->loop_var = $ node ->cond ;
115
+ break ;
116
+ case 'Stmt_Foreach ' : //foreach($nodes as $node) ======> extract $nodes
117
+ $ block ->loop_var = $ node ->expr ;
118
+ break ;
119
+ case 'Stmt_Do ' : //do{}while(cond); =====> extract cond
120
+ $ block ->loop_var = $ node ->cond ;
121
+ break ;
122
+ }
123
+ }
124
+
125
+ /**
126
+ * 给定AST Nodes集合,返回结束的行号
127
+ * @param unknown $nodes
128
+ */
129
+ public function getEndLine ($ nodes ){
130
+ return end ($ nodes )->getAttribute ('endLine ' ) ;
131
+ }
132
+
133
+
98
134
99
135
/**
100
136
* 由AST节点创建相应的CFG,用于后续分析
101
137
*
102
- * @param unknown $nodes 传入的PHP file的所有nodes
103
- * @param unknown $condition 构建CFGNode时的跳转信息
104
- * @param unknown $pEntryBlock 入口基本块
105
- * @param unknown $pNextBlock 下一个基本块
138
+ * @param $nodes 传入的PHP file的所有nodes
139
+ * @param $condition 构建CFGNode时的跳转信息
140
+ * @param $pEntryBlock 入口基本块
141
+ * @param $pNextBlock 下一个基本块
106
142
*/
107
- public function CFGBuilder ($ nodes ,$ condition ,$ pEntryBlock ,$ pNextBlock ){
143
+ public function CFGBuilder ($ nodes ,$ condition ,$ pEntryBlock ,$ pNextBlock ,$ endLine =0 ){
144
+ echo "<pre> " ;
145
+ global $ JUMP_STATEMENT ,$ LOOP_STATEMENT ,$ STOP_STATEMENT ,$ RETURN_STATEMENT ;
108
146
$ currBlock = new BasicBlock () ;
109
147
110
148
//创建一个CFG节点的边
111
149
if ($ pEntryBlock ){
112
- $ block_edge = new CFGEdge ($ pEntryBlock , $ pNextBlock ,$ condition ) ;
150
+ $ block_edge = new CFGEdge ($ pEntryBlock , $ currBlock ,$ condition ) ;
151
+ $ pEntryBlock ->addOutEdge ($ block_edge ) ;
152
+ $ currBlock ->addInEdge ($ block_edge ) ;
113
153
}
114
-
154
+
115
155
//迭代每个AST node
116
156
foreach ($ nodes as $ node ){
117
- if (in_array ($ node ->getType (), JUMP_STATEMENT )){
157
+ if (!is_object ($ node ))continue ;
158
+ //判断node是否是结束node
159
+ if ($ node ->getAttribute ('endLine ' ) == 9 ){
160
+ $ currBlock ->is_exit = true ;
161
+ }
162
+
163
+ //如果节点是跳转类型的语句
164
+ if (in_array ($ node ->getType (), $ JUMP_STATEMENT )){
165
+ //生成基本块的摘要
166
+ //simulate(currBlock) ;
118
167
$ nextBlock = new BasicBlock () ;
119
168
//对每个分支,建立相应的基本块
169
+ $ branches = $ this ->getBranches ($ node ) ;
170
+ foreach ($ branches as $ b ){
171
+ $ this ->CFGBuilder ($ b ->nodes , $ b ->condition , $ currBlock , $ nextBlock ) ;
172
+ }
173
+ //var_dump($nextBlock) ;
174
+ $ currBlock = $ nextBlock ;
175
+
176
+ }elseif (in_array ($ node ->getType (), $ LOOP_STATEMENT )){ //如果节点是循环语句
177
+ $ this ->addLoopVariable ($ node , $ currBlock ) ; //加入循环条件
178
+ //simulate($currBlock) ;
179
+ $ currBlock ->nodes = $ node ->stmts ;
180
+ $ nextBlock = new BasicBlock () ;
181
+ $ this ->CFGBuilder ($ node ->stmts , NULL , $ currBlock , $ nextBlock ) ;
182
+ $ currBlock = $ nextBlock ;
120
183
184
+ }elseif (in_array ($ node ->getType (), $ STOP_STATEMENT )){
185
+ $ currBlock ->is_exit = true ;
186
+ break ;
187
+ }elseif (in_array ($ node ->getType (),$ RETURN_STATEMENT )){
188
+ $ currBlock ->addNode ($ node ) ;
189
+ //simulate($currBlock) ;
190
+ return ;
191
+ }else {
192
+ $ currBlock ->addNode ($ node );
121
193
}
122
194
}
123
195
196
+
197
+
198
+ //simulate(currBlock) ;
199
+ print_r ($ currBlock ) ;
200
+ if ($ pNextBlock && !$ currBlock ->is_exit ){
201
+ $ block_edge = new CFGEdge ($ currBlock , $ pNextBlock ) ;
202
+ $ currBlock ->addOutEdge ($ block_edge ) ;
203
+ $ pNextBlock ->addInEdge ($ block_edge ) ;
204
+ }
205
+
206
+ //print_r($currBlock) ;
207
+
124
208
}
125
209
126
210
}
127
211
128
212
213
+
129
214
/**
130
215
* 跳转语句的分支结构类
131
216
* @author Administrator
132
217
*
133
218
*/
134
219
class Branch{
135
- private $ condition ;
136
- private $ nodes = array () ;
220
+ public $ condition ;
221
+ public $ nodes ;
137
222
138
223
/**
139
224
* 构造函数
140
225
* @param $cond 跳转的条件
141
226
* @param $nodes 分支中携带的所有nodes
142
227
*/
143
228
public function __construct ($ cond ,$ nodes ){
144
- $ this ->condition = $ cond ;
145
- $ this ->nodes = $ nodes ;
229
+ $ this ->condition = array ($ cond ) ;
230
+ if (is_array ($ nodes )){
231
+ $ this ->nodes = $ nodes ;
232
+ }else {
233
+ $ this ->nodes = array ($ nodes ) ;
234
+ }
235
+
146
236
147
237
//将跳转的条件也加入至nodes中
148
238
if (is_array ($ this ->condition )){
@@ -154,34 +244,18 @@ public function __construct($cond,$nodes){
154
244
}
155
245
}
156
246
157
- /**
158
- * getter for $condition
159
- */
160
- public function getCondition (){
161
- return $ this ->condition ;
162
- }
163
-
164
- /**
165
- * getter for $nodes
166
- * @return multitype:
167
- */
168
- public function getNodes (){
169
- return $ this ->nodes ;
170
- }
171
-
172
-
173
247
}
174
248
175
-
249
+ /**
250
+ * 获取PHP File中所有的AST节点的访问者
251
+ * @author Administrator
252
+ *
253
+ */
176
254
class MyVisitor extends PhpParser \NodeVisitorAbstract{
177
255
private $ nodes = array ();
178
256
179
- public function leaveNode (Node $ node ) {
180
- $ this ->addNode ($ node ) ;
181
- }
182
-
183
- public function addNode ($ node ){
184
- array_push ($ this ->nodes , $ node ) ;
257
+ public function beforeTraverse (array $ nodes ){
258
+ $ this ->nodes = $ nodes ;
185
259
}
186
260
187
261
public function getNodes (){
@@ -229,19 +303,25 @@ public function leaveNode(Node $node) {
229
303
$ traverser ->addVisitor ($ visitor ) ;
230
304
$ traverser ->traverse ($ stmts ) ;
231
305
$ nodes = $ visitor ->getNodes () ;
232
- $ branches = NULL ;
233
- foreach ($ nodes as $ node ){
234
- if ($ node instanceof PhpParser \Node \Stmt \If_ ){
235
- $ branches = $ cfg ->getBranches ($ node ) ;
236
- }elseif ($ node instanceof PhpParser \Node \Stmt \Switch_ ){
237
- $ branches = $ cfg ->getBranches ($ node ) ;
238
- }else {
239
- $ branches = $ cfg ->getBranches ($ node ) ;
240
- }
241
- }
306
+ // $branches = NULL ;
307
+ // foreach ($nodes as $node){
308
+ // if($node instanceof PhpParser\Node\Stmt\If_ ){
309
+ // $branches = $cfg->getBranches($node) ;
310
+ // }elseif($node instanceof PhpParser\Node\Stmt\Switch_ ){
311
+ // $branches = $cfg->getBranches($node) ;
312
+ // }else{
313
+ // $branches = $cfg->getBranches($node) ;
314
+ // }
315
+ // }
316
+ // echo "<pre>" ;
317
+ // print_r($branches) ;
318
+
319
+ $ pEntryBlock = new BasicBlock () ;
320
+ $ pEntryBlock ->is_entry = true ;
321
+ $ endLine = $ cfg ->getEndLine ($ nodes );
322
+ $ ret = $ cfg ->CFGBuilder ($ nodes , NULL , NULL , NULL ,$ endLine ) ;
242
323
echo "<pre> " ;
243
- print_r ($ branches ) ;
244
-
324
+ //print_r($pEntryBlock) ;
245
325
?>
246
326
247
327
0 commit comments