• 沒有找到結果。

goo foo

B 13 Start point

Exit point 1

B 2 C 3 B 4

S 5

B 6

S 7 9

B 10

11 S 14 8

12

Figure 4.8 The Simplified Control Flow Graph of Figure 4.6

首先找路徑的部分,為了實作上的方便,我們採用深度優先順序搜尋的演算 法(Depth-First Search Algorithm),依照程式執行的邏輯順序,將函式中所有的路 徑一條一條的搜尋出來。在搜尋的過程中,特別要提到的是,當遇到包含迴圈標 籤的語句 (Loop Statement),表示此路徑會經過迴圈,但根據程式的執行邏輯順 序向下搜尋路徑,會產生無窮迴圈路徑的情況,因此我們統一將迴圈分類成兩條

根據上述找路徑的描述,從這控制流程圖我們會找出 7 條路徑,我們將這 7 條搜尋到的路徑以圖的方式展開。Figure 4.9 中可以看到 Path-4 到 Path-7 為包含 迴圈語句所展開的路徑,其中因為迴圈之後又遇到一個編號 13 的分支語句所以 又會再各分成兩條路徑,Path-6 和 Path-7 為不經過迴圈的路徑,Path-4 和 Path-5 是迴圈執行一次的迴圈路徑。在這邊以 Path-4 為例,我們可以看到一條退回邊 (Back Edge),從語句 12 回到迴圈分支語句 10,所謂的迴圈執行一次的迴圈路徑 就是只有一個退回邊,而且回到迴圈分支語句之後即離開迴圈的路徑。

再找出所有函式的路徑之後,開始進行可能含有弱點的路徑的篩選,當路徑 上包含接收點語句或呼叫外部函式語句或回傳值語句,三個條件任何一個就是我 們要處理的情況。反過來說,當三個條件都不符合的時候此路徑就優先刪除掉。

其中包含接收點語句的路徑很明顯就是我們要處理的汙染路徑,所以 Path-1、3、

4、6 我們先保留下來,接著我們說明另外兩個條件考慮進去的原因,以跨程序 性的角度來看,當遇到呼叫外部函式的語句,因為外部函式可能含有其他接收點 的汙染路徑,所以很直觀的我們要將他考慮進來,所以 Path-2 也保留起來。至 於回傳值語句的部分,從 Figure 4.9 的 Path-1 舉例來說,此為一條汙染路徑,其 中包含一個呼叫外部函式語句 3,從前面函式排序的描述可知,此外部函式 idCheck 會比目前分析的函式 doGet 優先進行分析。因此我們從 Figure 4.10 看

1

Exit point B 2

R 3

4 R 5 Start point

1 B 2

R 3 Path-1

1 B 2

4 R 5 Path-2

Figure 4.10 The Simplified Control Flow Graph and all paths of Figure 4.7

到 idCheck 在路徑篩選的部分會搜尋到兩條有回傳值的路徑,回傳值會影響 doGet 函式的 Path-1 裡面的變數值,也會跟著影響路徑限制的蒐集,因此包含回 傳值語句的路徑也要考慮進來,所以 doGet 除了上述保留的路徑,其他 Path-5、

7 被刪除掉,而 idCheck 的 Path-1、2 因為有回傳值所以都會保留起來。所以這 兩個含是最後篩選完的路徑分別為 idCheck 的 Path-1、2,doGet 的 Path-1、2、3、

4、6。

4-1-2-2-2 路徑靜態單一賦值轉換(Path -Specific SSA Transformation)

SSA 為 Static Single-Assignment 的縮寫,是程式分析中很常拿來作編譯器優化的 技巧,屬於一種更方便作程式分析的中繼表示(Intermediate Representation),

當我們說一個函式符合 SSA 的形式,定義上表示此函式中的每個變數都只會被 賦予過一次的值,關於 SSA 的轉換演算法[11]參考文獻中有進一步的說明。

在此我們的目的是為了避免之後路徑限制蒐集發生變數命名衝突的問題,因 此我們利用此概念以路徑為單位作 SSA 轉換,將路徑上的變數都給予一個獨一 無二的名稱。原本正統的 SSA 是對整個函式作轉換,需要利用一個輔助函式 Φ (Phi)來處理路徑接合的地方,不同於原本的 SSA 轉換,我們是以路徑為轉換單 位,只要單純順著路徑從起始點開始順著找出變數定義與使用的關係即可。

Figure 4.11 為 SSA 轉換展示,其中我們舉 Figure 4.9 的 Path-4 為範例,可以 看到轉換過後的 SSA Path-4 這條路徑上的所有程式語句中的變數名稱都改變了。

實作上我們對每個變數新增一個 SSA 標籤,分別記錄變數是屬於那個函式以及 是哪一個編號的變數,因為不同的函式之間可能有相同的本地變數名稱,我們用 函式 ID 來作區別。至於當變數的值被定義過一次以上,像是此圖中左邊的 Path-4,

從上面數下來的第 4 個語句 sum = 2 和第 7 個語句 sum = sum + 1,我們依照變數 被定義的順序作編號的遞增來達成 SSA 的轉換。因此這兩個語句就轉換成 M0_sum_0 =2 和 M0_sum_1 = M0_sum_0 + 1,其中以底線’_’作為區分,M0 就 是函式 ID 後面的數字就代表變數被定義的順序,0 就代表第一次定義,以此類

有了此轉換我們可以很清楚每個語句使用到的變數是屬於哪一個變數定義,

由上面轉換的結果可以看到第 7 個語句中使用到的變數 sum 實際就是 M0_sum_0,

而第 10 語句中用到的變數 sum 就是 M0_sum_1,將所有的路徑都做完 SSA 轉換 之後就會產生 SSA 形式的路徑,開始作接下來路徑限制蒐集。

4-1-2-2-3 迴圈路徑處理(Loop Path Handling)

迴圈的處理在測試案例產生的相關研究中是一定會遇到的問題,迴圈的出現導致

req = @parameter0 resp = @parameter1

name = req.getParameter("name");

id = req.getParameter("id");

writer = resp.getWriter();

Path-4

! (name.length() >= 5)

B

B ! (name.equals("Admin"))

B ( i < id.length())

(M0_sum_1 > 15)

B

M0_req_0 = @parameter0 M0_resp_0 = @parameter1

M0_name_0 =M0_ req_0.getParameter("name");

M0_id_0 = M0_req_0.getParameter("id");

M0_writer_0 = M0_resp_0.getWriter();

B ! (M0_name_0.equals("Admin"))

B ! (M0_i_1 < M0_id_0.length())

M0_writer_0.println(M0_name_0 + M0_id_0);

S

! (M0_name_0.length() >= 5)

B

SSA Path-4

B ( M0_i_0 < M0_id_0.length() )

Figure 4.11 The Demonstration of Path-Specific SSA Transformation

迴圈類型並舉例說明。

在路徑分析中遇到迴圈,處理上最困難的地方是迴圈的存在會產生無限種可 能的迴圈路徑。以 Figure 4.8 為例,從右邊的控制流程圖中看到迴圈產生的可能 路徑有 1-6-7-8-6-9、 1-6-7-8-6-7-8-6-9、1-6-7-8-6-7-8-6-7-8-6-9…,在不知道此 迴圈實際執行的次數下,所有可能的迴圈路徑都需要考慮進去才能達成我們程式 路徑的涵蓋率。迴圈展開(Loop Unfolding)為上述的解決方法,但在實作上的困 難點在於我們至少要知道迴圈實際執行次數的上限,否則只能盲目地展開路徑我 們可能因為迴圈產生上千條的路徑,蒐集上千條的路徑限制,但實際上卻只有一 條是真正的可執行路徑,產生過多的路徑限制我們也很難去比對在迴圈執行到第 幾次的情況下產生了經過迴圈的可執行路徑。更大的問題是當遇到迴圈執行次數 是和使用者輸入有關,我們根本不知道迴圈實際執行次數,因此也不知道到底在 甚麼時間點要停止展開,因此計算迴圈執行次數的上限、或是自動化地找出迴圈 的固定點(Fixed point)才能找到迴圈的收斂點兒不會無窮的發散,但相對運算的 代價是很昂貴的。

回想我們要產生測試案例的重點,重點在於路徑限制蒐集的完整性,我們思 考要如何蒐集迴圈內部的路徑限制以及迴圈會影響路徑上其他路徑限制的變數 值,我們應該如何補足這些資訊以達到路徑限制蒐集的完整性。從這樣的角度來 解決迴圈造成的限制問題,因此我們希望以迴圈執行一次的概念來完成包含迴圈 的完整路徑限制蒐集。

因此本論文研究對於迴圈的路徑處理方法是當遇到迴圈時,將迴圈分成兩條 路徑,從 Figure 4.8 來說的話,就是分成 1-6-9 和 1-6-7-8-6-9 兩條路徑,1-6-9 為 不經過迴圈的路徑,1-6-7-8-6-9 就是迴圈執行一次產生的路徑,其中在對 1-6-7-8-6-9 此路徑進行迴圈的分析處理以及路徑限制的蒐集。

採用迴圈執行一次的概念主要是參考[15]和[9]此兩篇相關文獻,我們利用[15]

提出一個新的符號化迴圈變數(Symbolic Trip Count Variable)。 TC 來代表迴圈實

執行一次的路徑的概念是[9]中提出的 non-iterative static loop evaluation。概念是 利用一回合的迴圈執行就算出迴圈執行次數以及和迴圈次數相關的變數值。簡單 的來說,我們對於迴圈的處理有兩部分,首先是迴圈路徑的展開,只展開迴圈執 行一次的路徑,再引進代表迴圈次數的符號化迴圈變數 TC 來幫助路徑限制蒐集 的完整性。

但迴圈執行一次的路徑分析的限制在於只能處理屬於線性變化類型的迴圈,

我們以[15]其中以 Key rules of linear relationship analysis 如 Figure 4.12 作為判別 迴圈是否能夠處理的基礎,以下會以第三章的 doGet 程式範例 Figure 3.1 中第 15

~17 行的 for 迴圈如何套用此規則來做說明。

下面為我們抽取出來的 for 迴圈程式片段,首先給予此迴圈一個專屬的符號 化迴圈變數 TC0,接著套用 Figure 4.12 的規則來計算迴圈中變數的抽象值 (Abstract Value)。規則中的方括號[ ]代表變數的抽象值,方括號裡面小寫的英文 字代表常數值,TC 是迴圈執行次數的變數;角括號< >代表迴圈的 domain,總 共有四個 domains,<0>代表抽象值在進入迴圈之前的初始狀態、<1>代表迴圈執 行一次之後抽象值的狀態,<*>和<*+1>分別代表抽象值在迴圈全部執行完,前者

Figure 4.12 The Key Rules of Linear Relationship Analysis in [16].

14 sum = 2;

15 for (int i = 0; i < id.length(); i++) { 16 sum++;

17 }

是還沒出迴圈後者是出迴圈的狀態。而 raise 代表迴圈執行完後 domain 的改變,

U(Join)的動作是將迴圈前後的變化聯集起來並引入符號化迴圈變數 TC 連結變 數與迴圈執行次數的關係。E 代表抽象值的表達式(Expression),

T

代表非線性變

化,就是無法處理的情況。下面我們舉迴圈中的變數 i 作最後迴圈的抽象值推演,

(M0_sum_1 > 15)

B

B ! (M0_i_1 < M0_id_0.length())

M0_writer_0.println(M0_name_0 + M0_id_0);

S

B ( M0_i_0 < M0_id_0.length() )

M0_sum_1 = M0_sum_0 + 1*M0_TC0;

M0_sum_0 = 2;

M0_i_0 = 0;

M0_i_1 = M0_i_0 + 1*M0_TC0;

(M0_sum_1 > 15)

B

B ! (M0_i_1 < M0_id_0.length())

M0_writer_0.println(M0_name_0 + M0_id_0);

S

套用這樣的概念到我們實作上,Figure 4.13 為 Figure 4.11 SSA 轉換後的路徑 中包含迴圈的片段,對於符合線性變化的迴圈,我們從展開執行一次的迴圈路徑 去推論迴圈中的變數值與符號化迴圈變數的線性關係,以完成路徑資訊的完整。

從這裡可以看到原本迴圈語句中 M0_sum_1 = M0_sum_0 + 1 在分析之後會得到 關於此迴圈的資訊,我們在實作上會額外使用一個標籤去記錄分析後的迴圈資訊,

像是迴圈是否為巢狀迴圈、TC ID 則是符號化迴圈變數名稱為 M0_TC0,代表是 M0 函式中的第一個迴圈變數,如果是常數的迴圈的話,會多出 TC value 紀錄計 算出來的迴圈數,而 TC delta 代表符合線性關係每回合固定改變的常數值。因此 此語句會改變成為 M0_sum_1 = M0_sum_0 + 1*M0_TC0,以此類推我們可以得 到變數 M0_i_1 = M0_i_0 + 1*M0_TC0, 因此我們就完成了迴圈路徑的處理。接 著就可以將完整的路徑資訊進行下一步路徑限制的蒐集,在此我們以概觀的角度 說明我們想要達成目標,接下來會針對目前能夠處理的迴圈作正面的列舉與說明。

像是迴圈是否為巢狀迴圈、TC ID 則是符號化迴圈變數名稱為 M0_TC0,代表是 M0 函式中的第一個迴圈變數,如果是常數的迴圈的話,會多出 TC value 紀錄計 算出來的迴圈數,而 TC delta 代表符合線性關係每回合固定改變的常數值。因此 此語句會改變成為 M0_sum_1 = M0_sum_0 + 1*M0_TC0,以此類推我們可以得 到變數 M0_i_1 = M0_i_0 + 1*M0_TC0, 因此我們就完成了迴圈路徑的處理。接 著就可以將完整的路徑資訊進行下一步路徑限制的蒐集,在此我們以概觀的角度 說明我們想要達成目標,接下來會針對目前能夠處理的迴圈作正面的列舉與說明。

相關文件