吉華斌,尚 穎,李 征
北京化工大學(xué) 信息科學(xué)與技術(shù)學(xué)院,北京 100029
Web應(yīng)用程序是指用戶可以通過(guò)Web瀏覽器訪問(wèn)的應(yīng)用程序,由完成特定任務(wù)的各種Web組件構(gòu)成,并通過(guò)Web頁(yè)面將結(jié)果展示給用戶[1]。隨著Web應(yīng)用程序的發(fā)展,異步請(qǐng)求過(guò)程在其中扮演越來(lái)越重要的角色。通過(guò)異步請(qǐng)求的工作方式,Web應(yīng)用程序結(jié)合JavaScript(JS)和對(duì)文檔對(duì)象模型(document object model,DOM)的操作,完成數(shù)據(jù)的修改與傳輸,實(shí)現(xiàn)高水平的用戶交互[2]。
DOM是處理可擴(kuò)展標(biāo)志語(yǔ)言的標(biāo)準(zhǔn)編程接口,它定義了HTML/XML的數(shù)據(jù)對(duì)象和屬性以及訪問(wèn)方法[3]。Web應(yīng)用程序的數(shù)據(jù)操作請(qǐng)求一般是通過(guò)JS對(duì)DOM的數(shù)據(jù)操作[4],包括添加、移除、改變或重排頁(yè)面上的DOM項(xiàng)目,重構(gòu)HTML文檔。
AJAX(asynchronous JavaScript and XML)技術(shù)是異步請(qǐng)求中最為常見(jiàn)的一種交互技術(shù)。AJAX是指異步的JavaScript和XML結(jié)合,在不重新加載整個(gè)網(wǎng)頁(yè)的情況下,對(duì)網(wǎng)頁(yè)的特定部分進(jìn)行更新[5]。AJAX通過(guò)在后臺(tái)與服務(wù)器進(jìn)行少量數(shù)據(jù)交換,使網(wǎng)頁(yè)實(shí)現(xiàn)異步更新,從而大大提高了與用戶之間的交互速度[6]。
AJAX技術(shù)在提高Web應(yīng)用程序與用戶交互水平的同時(shí),由于Web應(yīng)用程序設(shè)計(jì)不合理或網(wǎng)絡(luò)延遲等原因,可能導(dǎo)致服務(wù)端不能及時(shí)響應(yīng)客戶端請(qǐng)求,傳輸?shù)臄?shù)據(jù)發(fā)生錯(cuò)誤,影響用戶的使用[7]。這些錯(cuò)誤通常稱為異步請(qǐng)求錯(cuò)誤。
一些靜態(tài)分析方法被應(yīng)用于此類問(wèn)題的分析檢測(cè)。如Guha等人對(duì)JavaScript程序靜態(tài)控制流進(jìn)行分析,用于AJAX的錯(cuò)誤檢測(cè)[8];Marchetto等人使用基于狀態(tài)的測(cè)試事件序列,用于測(cè)試AJAX特定的錯(cuò)誤,并通過(guò)使用啟發(fā)式搜索算法優(yōu)化生成AJAX事件序列,有效檢出AJAX錯(cuò)誤[9];Zheng等人則通過(guò)使用邏輯數(shù)據(jù)語(yǔ)言實(shí)現(xiàn)對(duì)JavaScript進(jìn)行靜態(tài)分析,并實(shí)現(xiàn)從服務(wù)端抽取JavaScript并進(jìn)行重寫,用于檢測(cè)AJAX存在的原子沖突和數(shù)據(jù)不一致問(wèn)題[10]等。
當(dāng)異步請(qǐng)求的返回為靜態(tài)常量時(shí),上述方法能很好地檢測(cè)其中的問(wèn)題,但是當(dāng)異步請(qǐng)求的返回為非靜態(tài)常量時(shí),如對(duì)DOM的操作、變量操作、URL跳轉(zhuǎn)等,這些方法只能將其默認(rèn)為靜態(tài)常量[11]。這些返回?cái)?shù)據(jù)可以進(jìn)一步觸發(fā)事件,進(jìn)而引發(fā)異步請(qǐng)求錯(cuò)誤,但作為靜態(tài)常量處理后,這些錯(cuò)誤將不再可能被檢出。
為了模擬異步請(qǐng)求過(guò)程,測(cè)試AJAX執(zhí)行過(guò)程中可能發(fā)生的問(wèn)題,一些開(kāi)源的工具如WebCollector(https://github.com/CrawlScript/WebCollector/)、OWASP AJAX Crawling Tool(https://code.google.com/archive/p/fuzzops-ng/)、CRAWLJAX[12]可以通過(guò)獲取AJAX動(dòng)態(tài)執(zhí)行結(jié)果,對(duì)AJAX建立狀態(tài)模型進(jìn)行測(cè)試[13]。Dong等人通過(guò)建立模型抓取詳細(xì)而精確的用戶交互之間的關(guān)聯(lián)和依賴,判斷其調(diào)用的實(shí)際方法在AJAX調(diào)用時(shí)是否被改寫,由此判斷數(shù)據(jù)傳輸是否符合預(yù)期,實(shí)現(xiàn)對(duì)異步請(qǐng)求的錯(cuò)誤診斷[14]等。這些動(dòng)態(tài)分析方法通過(guò)動(dòng)態(tài)執(zhí)行能夠呈現(xiàn)異步請(qǐng)求返回為非靜態(tài)常量的各種情況,但分析的核心是傳輸數(shù)據(jù)結(jié)果的準(zhǔn)確性,對(duì)異步請(qǐng)求返回中存在的事件操作之間或與原有的異步操作之間可能引發(fā)的異步請(qǐng)求問(wèn)題檢測(cè)較少。
本文在動(dòng)態(tài)分析技術(shù)的基礎(chǔ)上,對(duì)返回值為非靜態(tài)常量的異步請(qǐng)求操作,通過(guò)URL參數(shù)從服務(wù)器端獲取完整的返回?cái)?shù)據(jù),并進(jìn)一步解析其中的事件操作,分析兩個(gè)事件操作之間或與原有的異步請(qǐng)求之間可能引發(fā)的問(wèn)題,將此類問(wèn)題定義為異步請(qǐng)求時(shí)序問(wèn)題,并將兩者一起構(gòu)成異步請(qǐng)求交錯(cuò)圖,通過(guò)圖的連通關(guān)系檢測(cè)可能發(fā)生的異步請(qǐng)求錯(cuò)誤。在實(shí)踐過(guò)程中,重點(diǎn)分析了異步請(qǐng)求可能發(fā)生的DOM未加載、DOM共用和變量沖突等錯(cuò)誤。最后通過(guò)動(dòng)態(tài)驗(yàn)證檢測(cè)結(jié)果的有效性。
本文的主要貢獻(xiàn)是:(1)提出了一種基于交錯(cuò)圖的異步請(qǐng)求時(shí)序問(wèn)題檢測(cè)方法,將能夠引發(fā)異步請(qǐng)求的事件和數(shù)據(jù)組成交錯(cuò)圖,對(duì)異步請(qǐng)求事件操作返回?cái)?shù)據(jù)為非靜態(tài)常量的可能引發(fā)的異步請(qǐng)求時(shí)序錯(cuò)誤進(jìn)行分析和檢測(cè)。(2)實(shí)現(xiàn)了一個(gè)完整的工具原型,用于自動(dòng)化檢測(cè)Web應(yīng)用程序中的異步請(qǐng)求時(shí)序問(wèn)題。(3)對(duì)現(xiàn)有5個(gè)開(kāi)源Web應(yīng)用程序和5個(gè)特定Web應(yīng)用程序,檢測(cè)其中的異步請(qǐng)求時(shí)序問(wèn)題,并通過(guò)控制網(wǎng)絡(luò)條件進(jìn)行驗(yàn)證,結(jié)果表明了本文提出的檢測(cè)方法的有效性。
首先介紹只有一個(gè)事件觸發(fā)的異步請(qǐng)求過(guò)程,其詳細(xì)過(guò)程如圖1所示,上面橢圓表示異步請(qǐng)求過(guò)程中的各個(gè)動(dòng)作,下面矩形表示頁(yè)面中的DOM元素跟隨動(dòng)作發(fā)生的變化。假定頁(yè)面包含DOM1、DOM2和DOM3共3組DOM元素,DOM1中包含一個(gè)能夠引發(fā)異步請(qǐng)求的事件A1。
步驟1用戶觸發(fā)了事件A1,異步請(qǐng)求的返回將會(huì)作用于DOM2,此時(shí)頁(yè)面中DOM2和DOM3保持不變。
步驟2瀏覽器發(fā)送請(qǐng)求給服務(wù)端,頁(yè)面中DOM2和DOM3保持不變。
步驟3服務(wù)端后端進(jìn)行處理,頁(yè)面中DOM2和DOM3保持不變。
步驟4瀏覽器獲取返回后開(kāi)始進(jìn)行加載,頁(yè)面中DOM2和DOM3保持不變。
步驟5瀏覽器加載完全,用戶看到DOM2更新為DOM2′,如圖1中的陰影部分,DOM3保持不變。
根據(jù)異步請(qǐng)求的異步特性,在異步請(qǐng)求進(jìn)行過(guò)程的5個(gè)步驟中,頁(yè)面中的DOM元素不會(huì)被鎖定,仍然可以繼續(xù)操作。下面考慮多個(gè)異步請(qǐng)求的情況。

Fig.1 Process of asynchronous request圖1 異步請(qǐng)求詳細(xì)過(guò)程
下面給出了一組返回值為非靜態(tài)常量的異步請(qǐng)求代碼示例(如圖2所示),詳細(xì)了解兩個(gè)異步請(qǐng)求進(jìn)行過(guò)程中的關(guān)系。圖2(a)表示ID為tip的DOM綁定了一個(gè)click事件,并由此事件引發(fā)了一個(gè)AJAX請(qǐng)求,包含url、data、type等參數(shù),成功后返回參數(shù)xhr,并操作了ID為content的DOM元素,將返回值嵌入到其中。此時(shí)的返回值xhr.data即為非靜態(tài)常量,具體體現(xiàn)在content中是一個(gè)標(biāo)簽,但是在異步請(qǐng)求執(zhí)行之前并不知道其具體的值。圖2(b)表示ID為choose的DOM綁定了一個(gè)click事件,返回值也是一個(gè)非靜態(tài)常量,最終也操作了ID為content的DOM元素,并將返回值嵌入到其中。圖2(c)表示content對(duì)應(yīng)的HTML代碼。
根據(jù)一個(gè)異步請(qǐng)求的過(guò)程圖(圖1),將tip綁定的Ajax事件記為tip.click,choose.click表示choose綁定的Ajax事件。如果連續(xù)觸發(fā)事件tip.click和choose.click,可以得到兩個(gè)異步請(qǐng)求的過(guò)程圖如圖3。
圖3表示tip.click和choose.click都會(huì)操作ID為content的DOM元素。由于在一個(gè)異步請(qǐng)求過(guò)程中,頁(yè)面不會(huì)被鎖定,即在圖3中choose.click可能發(fā)生在tip.click完成之前的任何一個(gè)過(guò)程中。tip.click觸發(fā)的異步請(qǐng)求返回將更新content,當(dāng)在tip.click觸發(fā)的請(qǐng)求沒(méi)有完成對(duì)content更新之前(即content更新為content′之前),用戶觸發(fā)了choose.click,choose.click觸發(fā)的請(qǐng)求也將更新content,即對(duì)于content的最終更新結(jié)果content″,不確定是tip.click觸發(fā)的異步請(qǐng)求更新的結(jié)果,還是choose.click觸發(fā)的異步請(qǐng)求更新的結(jié)果,進(jìn)而引發(fā)后續(xù)的操作錯(cuò)誤。
為了具體分析描述引例中的問(wèn)題以及相關(guān)的問(wèn)題,根據(jù)異步請(qǐng)求的過(guò)程,本文將兩個(gè)能夠引發(fā)異步請(qǐng)求的事件組合,引入異步請(qǐng)求時(shí)序的概念,具體定義如下。
定義1(異步請(qǐng)求時(shí)序)一個(gè)引起異步請(qǐng)求的事件發(fā)生后,立即觸發(fā)另外一個(gè)事件處理時(shí),頁(yè)面加載和參數(shù)傳遞的執(zhí)行順序。

Fig.2 Example code圖2 引例代碼

Fig.3 Process of two asynchronous requests圖3 兩個(gè)異步請(qǐng)求的過(guò)程
在一個(gè)異步請(qǐng)求時(shí)序中,假如依次發(fā)生的兩個(gè)事件分別為A1和A2,當(dāng)A1發(fā)生在A2引發(fā)的異步請(qǐng)求整個(gè)過(guò)程完成之后,即瀏覽器返回的數(shù)據(jù)已經(jīng)在客戶端完全展示出來(lái)之后,此異步請(qǐng)求時(shí)序不會(huì)引發(fā)錯(cuò)誤;而當(dāng)A1觸發(fā)的異步請(qǐng)求事件還未進(jìn)行完全,觸發(fā)A2,即A2發(fā)生在A1引發(fā)的異步請(qǐng)求過(guò)程中,頁(yè)面元素可能還未完全加載,參數(shù)變量也有可能還在傳遞過(guò)程中,可能會(huì)引發(fā)錯(cuò)誤,此類問(wèn)題稱為異步請(qǐng)求時(shí)序問(wèn)題。
異步請(qǐng)求過(guò)程的事件和數(shù)據(jù)操作存在明顯的因果依賴關(guān)系,如果異步請(qǐng)求事件和數(shù)據(jù)元素過(guò)多,問(wèn)題會(huì)變得非常復(fù)雜,為了高效地分析異步請(qǐng)求過(guò)程中因事件請(qǐng)求和數(shù)據(jù)操作引發(fā)的錯(cuò)誤,對(duì)異步請(qǐng)求事件和數(shù)據(jù)操作進(jìn)行有效建模,下面借助交錯(cuò)圖對(duì)異步請(qǐng)求的事件和數(shù)據(jù)進(jìn)行表示。首先給出異步請(qǐng)求時(shí)序的交錯(cuò)圖的定義,如圖4所示,左邊分別表示DOM元素、事件操作和參數(shù)變量的節(jié)點(diǎn)表示,右邊為三者之間關(guān)系的箭頭表示。

Fig.4 Definition of asynchronous request sequence interleaving graph圖4 異步請(qǐng)求時(shí)序的交錯(cuò)圖定義
根據(jù)交錯(cuò)圖的定義,可以得到示例中兩個(gè)事件tip.click和choose.click的交錯(cuò)圖,如圖5所示,通過(guò)有向圖的連通性[15],根據(jù)交錯(cuò)圖可以看出兩個(gè)能夠引發(fā)異步請(qǐng)求的事件tip.click到choose.click存在弱連通。

Fig.5 Interleaving graph presentation of example圖5 引例的交錯(cuò)圖表示
兩個(gè)異步請(qǐng)求事件A1和A2連續(xù)被觸發(fā)時(shí),其可能出錯(cuò)的原因是事件A2發(fā)生在A1引發(fā)的異步請(qǐng)求過(guò)程中。如果事件A1和A2分別作用于頁(yè)面的不同DOM元素中,且參數(shù)沒(méi)有任何關(guān)聯(lián)性,在兩個(gè)異步請(qǐng)求依次觸發(fā)的過(guò)程中,即使事件A2發(fā)生在A1引發(fā)的異步請(qǐng)求過(guò)程中,并不會(huì)影響A1觸發(fā)的異步請(qǐng)求,兩者互相不會(huì)有交集,也不會(huì)引發(fā)由于數(shù)據(jù)依賴關(guān)系發(fā)生的錯(cuò)誤。因此根據(jù)兩個(gè)異步請(qǐng)求事件與數(shù)據(jù)操作之間的關(guān)系以及實(shí)際應(yīng)用程序中可能出現(xiàn)的情況,將可能引發(fā)異步請(qǐng)求時(shí)序錯(cuò)誤的問(wèn)題歸納為三類:
(1)DOM未加載錯(cuò)誤:存在一個(gè)DOM1包含將要觸發(fā)的異步請(qǐng)求事件A1,A1將會(huì)更新DOM2為DOM2′。如果DOM2′直接包含另一個(gè)異步請(qǐng)求事件,或者DOM2包含的DOM中存在另一個(gè)異步請(qǐng)求事件,那么在DOM2′還沒(méi)有加載完成時(shí),觸發(fā)其中的另一個(gè)異步請(qǐng)求事件,這時(shí)觸發(fā)的事件會(huì)和想要觸發(fā)的事件不一致。
(2)DOM共用錯(cuò)誤:存在兩個(gè)異步請(qǐng)求事件A1和A2,事件A1將會(huì)更新DOM2,事件A2也會(huì)更新DOM2或者更新DOM2中包含的DOM。由于兩個(gè)事件操作了同一個(gè)DOM,不能確定兩個(gè)事件對(duì)于DOM2操作的先后執(zhí)行順序,也就不確定最終執(zhí)行完成后頁(yè)面加載的結(jié)果是否正確。
(3)變量沖突錯(cuò)誤:一個(gè)異步請(qǐng)求事件觸發(fā)也會(huì)使用參數(shù)變量,返回也會(huì)更改某些參數(shù)變量。存在兩個(gè)異步請(qǐng)求事件A1和A2,當(dāng)A2操作的變量參數(shù)為事件A1返回的變量參數(shù)時(shí),當(dāng)兩個(gè)事件連續(xù)發(fā)生時(shí),A2操作的參數(shù)也不確定是由A1更新之前的還是更新之后的。
引例所示即為DOM共用錯(cuò)誤。下面使用交錯(cuò)圖表示其他兩類錯(cuò)誤:圖6表示DOM未加載錯(cuò)誤,D1包含的事件A1觸發(fā)的異步請(qǐng)求將會(huì)操作D2,而D2又包含一個(gè)新的異步請(qǐng)求事件A2,矩形虛線框中表示D2包含子DOM元素D3,D3中包含A2。A1將會(huì)更新D2,D2又包含A2,當(dāng)D2還未加載完成時(shí),觸發(fā)其中的事件A2,這時(shí)會(huì)引發(fā)異步請(qǐng)求時(shí)序錯(cuò)誤,可以看出A1和A2通過(guò)D2或者D2和D3連通。

Fig.6 Interleaving graph presentation of DOM not loaded圖6 DOM未加載問(wèn)題交錯(cuò)圖表示
圖7表示變量沖突錯(cuò)誤,D1包含的事件A1觸發(fā)的異步請(qǐng)求將會(huì)操作P1,而D2包含的事件A2觸發(fā)的異步請(qǐng)求也會(huì)操作P1。當(dāng)A1在對(duì)P1參數(shù)的更新過(guò)程中觸發(fā)A2,這時(shí)會(huì)引發(fā)異步請(qǐng)求時(shí)序錯(cuò)誤。可以看出A1和A2通過(guò)P1連通。

Fig.7 Interleaving graph presentation of variables conflict圖7 變量沖突問(wèn)題的交錯(cuò)圖表示
在一個(gè)Web應(yīng)用程序中,可能有很多引發(fā)異步請(qǐng)求的事件,以一個(gè)頁(yè)面為例,將其包含的所有異步請(qǐng)求事件作為一個(gè)集合,那么集合中的任意兩個(gè)元素組合可能引發(fā)異步請(qǐng)求錯(cuò)誤,也可能不會(huì)引發(fā)異步請(qǐng)求錯(cuò)誤。假設(shè)頁(yè)面中有n個(gè)異步請(qǐng)求事件,考慮所有異步請(qǐng)求事件兩兩組合中的關(guān)聯(lián)關(guān)系,需要分析的事件組合數(shù)為:

因此異步請(qǐng)求時(shí)序問(wèn)題的交錯(cuò)圖分析流程如圖8所示。首先進(jìn)行頁(yè)面分析得到所有的包含異步請(qǐng)求事件的集合,然后兩兩組合分析。圖中表示為第k次連接,通過(guò)每次的組合連接,如果兩個(gè)異步請(qǐng)求事件能夠連通,表示一組可能出錯(cuò)的異步請(qǐng)求事件組合,通過(guò)連通的情況判斷為DOM未加載錯(cuò)誤、DOM共用錯(cuò)誤、變量沖突錯(cuò)誤,或者不連通即為不存在錯(cuò)誤,檢測(cè)算法將在下章詳細(xì)說(shuō)明。然后k=k+1,對(duì)下一個(gè)組合進(jìn)行判斷,循環(huán)直至n(n-1)/2個(gè)組合檢測(cè)完成,其時(shí)間復(fù)雜度為O(nlogn)。

Fig.8 Flow graph of interleaving graph method圖8 交錯(cuò)圖方法流程圖
在上述異步請(qǐng)求交錯(cuò)圖分析中,得到引起異步請(qǐng)求問(wèn)題的三類錯(cuò)誤:DOM未加載、DOM共用、變量沖突。根據(jù)上述產(chǎn)生異步請(qǐng)求問(wèn)題的原因,下面將詳細(xì)講述對(duì)上述三類問(wèn)題的檢測(cè)方法。
當(dāng)異步請(qǐng)求返回為靜態(tài)常量時(shí),即操作對(duì)象和數(shù)據(jù)是已知的,無(wú)需后臺(tái)數(shù)據(jù)獲取,此時(shí)僅僅需要前端代碼,即可以通過(guò)關(guān)聯(lián)性分析異步請(qǐng)求錯(cuò)誤。但是多數(shù)情況下,異步請(qǐng)求的返回涉及很多非靜態(tài)常量,例如圖2(b)中,這種情況下異步請(qǐng)求的返回變量xhr.data并不知道,需要從后臺(tái)獲取其對(duì)應(yīng)的數(shù)據(jù),因此需要知道后臺(tái)對(duì)應(yīng)的數(shù)據(jù)代碼,才能得到其對(duì)應(yīng)的交錯(cuò)圖關(guān)系。具體檢測(cè)方法如下:
由于異步請(qǐng)求的實(shí)現(xiàn)在JS文件中,其發(fā)起點(diǎn)為事件,事件綁定的是DOM,即綁定事件的DOM即為數(shù)據(jù)入口點(diǎn)。為了獲取含有異步請(qǐng)求的Web應(yīng)用程序的輸入值,本文采取逆向工程的過(guò)程[16],提取所有暴露的數(shù)據(jù)入口點(diǎn)。如算法1所示:輸入為JS文件,輸出為包含異步請(qǐng)求的事件集。dom1和dom2分別表示引發(fā)異步請(qǐng)求事件所在的DOM和異步請(qǐng)求返回操作的DOM。
在獲取異步請(qǐng)求事件時(shí),如果其返回值為靜態(tài)元素,直接可以得到其改變的DOM元素結(jié)構(gòu),否則需要根據(jù)異步請(qǐng)求的URL,通過(guò)后端程序獲取其返回值,賦予其對(duì)應(yīng)改變的DOM元素結(jié)構(gòu)。算法1中GetDOM2ByUrl表示當(dāng)異步請(qǐng)求返回值為動(dòng)態(tài)數(shù)據(jù)時(shí),需要通過(guò)URL從后端獲取返回?cái)?shù)據(jù)。
算法1GetEventDOM

通過(guò)算法1,可以獲取需要檢測(cè)的異步請(qǐng)求事件集,根據(jù)這些數(shù)據(jù)集,通過(guò)下面的方法,即可實(shí)現(xiàn)對(duì)以下三類錯(cuò)誤的檢測(cè)。
(1)DOM未加載錯(cuò)誤的檢測(cè)
如算法2所示,O為算法1獲取的事件集,新建一個(gè)空集合K用來(lái)存儲(chǔ)檢測(cè)后的事件集,初始i=0,將O中的元素依次加入到K中,并初始K[i].num為1,同時(shí)增加i值。如果新加入事件的觸發(fā)DOM元素(Triger-DOM)和K中某個(gè)事件的返回DOM(ReturnDOM)相同或包含(由于包含關(guān)系可能會(huì)很復(fù)雜,只考慮基礎(chǔ)的DOM樹(shù)的關(guān)系),即有可能引發(fā)異步請(qǐng)求問(wèn)題,則更新相應(yīng)K[i].num為K[i].num+1,并將O.event加入K[i].event,直至O中所有元素遍歷完全。此時(shí)K中的元素num值大于1的事件集合就是可能發(fā)生DOM未加載的事件集。
算法2GetUnreloadDOM

(2)DOM共用的檢測(cè)
如算法3所示,O為算法1獲取的事件集,新建一個(gè)空集合K用來(lái)存儲(chǔ)檢測(cè)后的事件集,初始i=0,將O中的元素依次加入到K中,并初始K[i].num為1,同時(shí)增加i值。如果新加入事件的返回DOM(Return-DOM)和K中某個(gè)事件的返回DOM(ReturnDOM)相同或包含,即會(huì)引發(fā)異步請(qǐng)求問(wèn)題,則更新相應(yīng)K[i].num為K[i].num+1,并將O.event加入K[i].event,直至O中所有元素遍歷完全。此時(shí)K中的元素num值大于1的事件集合就是可能發(fā)生DOM共用的事件集。
算法3GetReuseDOM


(3)變量沖突檢測(cè)
對(duì)于變量沖突的檢測(cè)方法和DOM共用類似,算法4同算法3,不再贅述。
本文實(shí)現(xiàn)了一個(gè)完整的工具原型,用于DOM未加載、DOM共用和變量沖突等情況導(dǎo)致的異步請(qǐng)求時(shí)序問(wèn)題的檢測(cè),如圖9所示。為了實(shí)現(xiàn)獲取檢測(cè)方法中使用的異步請(qǐng)求事件集,需要前端部分與后端部分的綜合分析。具體的實(shí)現(xiàn)流程如下。
(1)前端分析:通過(guò)使用Webkit的Webcore和Java-ScriptCore的API接口檢測(cè)所有JS文件,在異步請(qǐng)求的獲取中參考Jquery的Ajax,得到Ajax的url、發(fā)送的data以及success之后的返回值。
(2)后端分析:(以PHP語(yǔ)言為例)通過(guò)PHP compiler獲取上述url對(duì)應(yīng)的Ajax返回值,結(jié)合得到Ajax返回值以及對(duì)DOM的操作。
(3)綜合前端分析和后端分析結(jié)果,再通過(guò)上文描述的檢測(cè)算法,得到是否產(chǎn)生異步請(qǐng)求錯(cuò)誤以及引起異步請(qǐng)求錯(cuò)誤的問(wèn)題類型。

Fig.9 Tool prototype圖9 工具原型
文中提出的問(wèn)題主要針對(duì)Web應(yīng)用程序中異步請(qǐng)求過(guò)程中可能發(fā)生的錯(cuò)誤,因此在實(shí)驗(yàn)對(duì)象的選擇上,首先構(gòu)造了針對(duì)各個(gè)錯(cuò)誤的5個(gè)特定Web應(yīng)用程序,然后選取了異步請(qǐng)求較多的5個(gè)開(kāi)源Web應(yīng)用程序。并且本文對(duì)開(kāi)源Web應(yīng)用程序的檢測(cè)結(jié)果和之前靜態(tài)分析方法[10]的檢測(cè)結(jié)果進(jìn)行對(duì)比。
表1為5個(gè)針對(duì)特定問(wèn)題的特定Web應(yīng)用程序,以及總文件大小、JS文件大小和AJAX文件大小。它們分別包含示例或?qū)嶋HWeb應(yīng)用程序中的一類異步請(qǐng)求錯(cuò)誤,詳情如下:
Case 1兩個(gè)異步請(qǐng)求事件改變同一個(gè)DOM的display屬性,block或者none。
Case 2兩個(gè)異步請(qǐng)求事件改變同一個(gè)DOM元素的圖片內(nèi)容。
Case 3異步請(qǐng)求事件操作的DOM在更新前后都包含一個(gè)URL,分別指向不同的外部地址。
Case 4第一個(gè)異步請(qǐng)求事件操作的DOM內(nèi)包含和之前DOM內(nèi)相似的刪除事件,分別指向不同的文件。
Case 5兩個(gè)異步請(qǐng)求事件同時(shí)操作同一個(gè)變量。

Table 1 Web application cases表1 特定Web應(yīng)用程序
表2中包含了另外5個(gè)開(kāi)源的Web應(yīng)用程序Ajax File Browser(http://sourceforge.net/projects/ajaxfb/)、Photogallery(http://p.horm.org/er/)、Phormer(http://sourceforge.net/projects/rephormer/)、Quizzy(http://sourceforge.net/projects/quizzy/)、XHTML Chat(http://chat.plasticshore.com/)的詳細(xì)信息,分別為站點(diǎn)總文件大小、JS文件大小和AJAX文件大小。這里選用文件大小而不是文件個(gè)數(shù)的原因是現(xiàn)在許多應(yīng)用程序?qū)τ谏暇€應(yīng)用程序的JS文件會(huì)進(jìn)行壓縮處理,比如多個(gè)文件壓縮成一個(gè)文件,因此使用文件大小能較為準(zhǔn)確地衡量文件比例關(guān)系。另外,JS文件不包括外部的JS庫(kù)文件,因?yàn)槎鄶?shù)庫(kù)文件很大,統(tǒng)計(jì)難度較大,然而應(yīng)用程序?qū)ζ涞氖褂檬侵苯诱{(diào)用其函數(shù)接口,所以以實(shí)際使用為準(zhǔn)。

Table 2 Open source Web applications表2 開(kāi)源Web應(yīng)用程序
通過(guò)使用本文的方法對(duì)上述10個(gè)應(yīng)用程序進(jìn)行檢測(cè),得出可能出現(xiàn)錯(cuò)誤的個(gè)數(shù)如表3所示。由于此類問(wèn)題的發(fā)生具有不確定性,但都是引發(fā)異步請(qǐng)求錯(cuò)誤的潛在因素。為了增加驗(yàn)證中出現(xiàn)錯(cuò)誤的可能性,表4給出了通過(guò)控制網(wǎng)絡(luò)條件,即在不同的網(wǎng)速條件下,通過(guò)10次實(shí)際操作,出現(xiàn)異步請(qǐng)求錯(cuò)誤的次數(shù),對(duì)表3中的錯(cuò)誤進(jìn)行驗(yàn)證。從表4可以看到,如果網(wǎng)絡(luò)條件良好的情況下,大部分結(jié)構(gòu)簡(jiǎn)單的站點(diǎn)不容易引發(fā)錯(cuò)誤,但是對(duì)于結(jié)構(gòu)復(fù)雜或含有大文件的數(shù)據(jù)交互時(shí),還是有可能引發(fā)錯(cuò)誤,雖然出現(xiàn)的概率比較低,也正因此,錯(cuò)誤才不容易被發(fā)現(xiàn),然而這些錯(cuò)誤在實(shí)際中可能會(huì)對(duì)用戶產(chǎn)生困擾,對(duì)用戶使用產(chǎn)生較大的影響,因此對(duì)于此類錯(cuò)誤的檢測(cè)是有意義的。

Table 3 Detecting result of asynchronous request sequence表3 異步請(qǐng)求時(shí)序錯(cuò)誤檢測(cè)結(jié)果
用本文的檢測(cè)結(jié)果和之前已有的結(jié)果[10]進(jìn)行對(duì)比,這里只對(duì)實(shí)際的應(yīng)用程序進(jìn)行對(duì)比,如表5所示。之前的方法只能檢測(cè)出變量沖突問(wèn)題的個(gè)數(shù),因此其總個(gè)數(shù)就是其變量沖突問(wèn)題的個(gè)數(shù)。除了Photogallery之前方法沒(méi)有進(jìn)行實(shí)驗(yàn)無(wú)法對(duì)比外,對(duì)于其余4個(gè)Web應(yīng)用程序,本文方法不僅檢出了和之前方法一樣多的變量沖突錯(cuò)誤,而且還能檢測(cè)出文中提出的DOM未加載和DOM共用錯(cuò)誤。因此,本文方法比之前的方法在DOM未加載和DOM共用兩類錯(cuò)誤的檢測(cè)上具有明顯的優(yōu)勢(shì)。

Table 4 Experimental verification表4 實(shí)驗(yàn)驗(yàn)證

Table 5 Experimental result contrast表5 實(shí)驗(yàn)對(duì)比
針對(duì)Web應(yīng)用程序的異步請(qǐng)求中,由于程序代碼設(shè)計(jì)不合理或網(wǎng)絡(luò)延遲等原因?qū)е碌臄?shù)據(jù)傳輸錯(cuò)誤等問(wèn)題,本文對(duì)返回中存在事件操作的異步請(qǐng)求,通過(guò)URL參數(shù)從服務(wù)器端獲取完整的返回?cái)?shù)據(jù),分析兩個(gè)事件操作之間或與原有的異步請(qǐng)求之間可能引發(fā)的問(wèn)題,并構(gòu)成異步請(qǐng)求交錯(cuò)圖進(jìn)行分析檢測(cè)。在此基礎(chǔ)上提出了一個(gè)完整的技術(shù)實(shí)現(xiàn)框架,用于自動(dòng)化檢測(cè)Web應(yīng)用程序中的異步請(qǐng)求時(shí)序問(wèn)題。利用本文方法,針對(duì)5個(gè)特定Web應(yīng)用程序和5個(gè)現(xiàn)有開(kāi)源Web應(yīng)用程序,能夠檢測(cè)其中的異步請(qǐng)求問(wèn)題,并通過(guò)控制網(wǎng)絡(luò)條件進(jìn)行驗(yàn)證,結(jié)果表明了本文提出的檢測(cè)方法的有效性。與之前的方法相比,本文方法能夠?qū)崿F(xiàn)更多的Web應(yīng)用程序問(wèn)題檢測(cè)。
進(jìn)一步,對(duì)于本文檢測(cè)出的異步請(qǐng)求時(shí)序問(wèn)題,部分可以通過(guò)AJAX的控制機(jī)制避免,或者在HTML書(shū)寫過(guò)程中,盡量避免使用過(guò)多的DOM嵌套。另外本文只考慮了JS文件中標(biāo)準(zhǔn)格式綁定的事件,而對(duì)于結(jié)構(gòu)比較混亂的代碼結(jié)構(gòu)檢出率可能會(huì)降低,因此需要用更多的實(shí)際應(yīng)用程序進(jìn)行驗(yàn)證。
[1]Yang Jian,Papazoglou M P.Web component:a substrate for Web service reuse and composition[C]//LNCS 2348:Proceedings of the 14th International Conference on Advanced Information Systems Engineering,Toronto,May 27-31,2002.Berlin,Heidelberg:Springer,2002:21-36.
[2]Mesbah A,van Deursen A,Roest D.Invariant-based automatic testing of modern Web applications[J].IEEE Transactions on Software Engineering,2012,38(1):35-53.
[3]Jensen S H,Madsen M,M?llerA.Modeling the HTML DOM and browser API in static analysis of JavaScript Web applications[C]//Proceedings of the 19th ACM SIGSOFT Symposium on the Foundations of Software Engineering and 13th European Software Engineering Conference,Szeged,Sep 5-9,2011.New York:ACM,2011:59-69.
[4]Patil P,Lambhate P.Crawler based Ajax Web application testing[J].International Journal of Current Engineering and Technology,2015,5(4):2621-2624.
[5]Ocariza F,Bajaj K,Pattabiraman K,et al.An empirical study of client-side JavaScript bugs[C]//Proceedings of the 2013 International Symposium on Empirical Software Engineering and Measurement,Baltimore,Oct 10-11,2013.Washington:IEEE Computer Society,2013:55-64.
[6]Wenzel M,Meinel C.Parallel network data processing in client side JavaScript applications[C]//Proceedings of the 2015 International Conference on Collaboration Technologies and Systems,Atlanta,Jun 1-5,2015.Piscataway:IEEE,2015:140-147.
[7]Madsen M,Tip F,Lhoták O.Static analysis of event-driven Node.js JavaScript applications[C]//Proceedings of the 2015 International Conference on Object-Oriented Programming,Systems,Languages,and Applications,Pittsburgh,Oct 25-30,2015.New York:ACM,2015:505-519.
[8]Guha A,Krishnamurthi S,Jim T.Using static analysis for Ajax intrusion detection[C]//Proceedings of the 18th International Conference on World Wide Web,Madrid,Apr 20-24,2009.New York:ACM,2009:561-570.
[9]Marchetto A,Tonella P.Using search-based algorithms for Ajax event sequence generation during testing[J].Empirical Software Engineering,2011,16(1):103-140.
[10]Zheng Yunhui,Bao Tao,Zhang Xiangyu.Statically locating Web application bugs caused by asynchronous calls[C]//Proceedings of the 20th International Conference on World Wide Web,Hyderabad,Mar 28-Apr 1,2011.New York:ACM,2011:805-814.
[11]Alimadadi S,Mesbah A,Pattabiraman K.Understanding asynchronous interactions in full-stack JavaScript[C]//Proceedings of the 38th International Conference on Software Engineering,Austin,May 14-22,2016.New York:ACM,2016:1169-1180.
[12]Mesbah A,Bozdag E,van Deursen A.Crawling AJAX by inferring user interface state changes[C]//Proceedings of the 5th International Conference on Web Engineering,Yorktown Heights,Jul 14-18,2008.Washington:IEEE Computer Society,2008:122-134.
[13]Mesbah A,van Deursen A,Lenselink S.Crawling Ajaxbased Web applications through dynamic analysis of user interface state changes[J].ACM Transactions on the Web,2012,6(1):3.
[14]Dong Xinshu,Patil K,Mao Jian,et al.Acomprehensive clientside behavior model for diagnosing attacks in Ajax applications[C]//Proceedings of the 18th International Conference on Engineering of Complex Computer Systems,Singapore,Jul 17-19,2013.Washington:IEEE Computer Society,2013:177-187.
[15]West D B.Introduction to graph theory[M].Upper Saddle River:Prentice Hall,2001.
[16]Marchetto A,Tonella P,Ricca F.Reajax:a reverse engineering tool for Ajax Web applications[J].IET Software,2012,6(1):33-49.