.dex
檔案是 Dalvik 位元碼的傳輸格式。檔案必須符合特定的語法和語義限制,才能成為有效的 .dex
檔案,而執行階段則必須只支援有效的 .dex 檔案。
一般 .dex 完整性限制
一般完整性限制與 .dex
檔案的較大結構有關,詳情請參閱 .dex
格式。
ID | 說明 |
---|---|
G1 |
.dex 檔案的 magic 編號必須是 dex\n035\0 (適用於 35 以上版本),或類似的編號 (適用於較新版本)。 |
G2 |
總和檢查碼必須是整個檔案內容的 Adler-32 總和檢查碼,但 magic 和 checksum 欄位除外。 |
G3 |
簽章必須是整個檔案內容的 SHA-1 雜湊,但 magic 、checksum 和 signature 除外。 |
G4 |
|
G5 |
|
G6 |
endian_tag 必須具有以下值:
ENDIAN_CONSTANT 或 REVERSE_ENDIAN_CONSTANT
|
G7 |
對於每個
|
G8 |
標頭中所有偏移欄位 (map_off 除外) 都必須四個位元組對齊。 |
G9 |
map_off 欄位必須為零或指向資料區段。在後一種情況下,data 部分必須存在。 |
G10 |
link 、string_ids 、type_ids 、proto_ids 、field_ids 、method_ids 、class_defs 和 data 區段不得彼此重疊或重疊至標題。 |
G11 | 如果有地圖,則每個地圖項目都必須具有有效的類型。每個類型最多只能出現一次。 |
G12 |
如果有對應圖,則每個對應圖項目都必須有非零的偏移量和大小。偏移值必須指向檔案的對應部分 (也就是 string_id_item 必須指向 string_ids 部分),且項目的明確或隱含大小必須與該部分的實際內容和大小相符。 |
G13 |
如果地圖存在,地圖項目 n+1 的偏移量必須大於或等於地圖項目 n plus than size of map entry n 的偏移量。這表示不重疊的項目和由低至高的排序。 |
G14 |
下列類型的項目必須有四個位元組對齊的偏移量:string_id_item 、type_id_item 、proto_id_item 、field_id_item 、method_id_item 、class_def_item 、type_list 、code_item 、annotations_directory_item 。 |
G15 |
對於每個 對於每個 對於參照的 |
G16 |
對於每個 type_id_item ,descriptor_idx 欄位都必須包含有效的 string_ids 清單參照。參照的字串必須是有效的類型描述符。 |
G17 |
對於每個 proto_id_item ,shorty_idx 欄位都必須包含有效的 string_ids 清單參照。參照的字串必須是有效的短代碼描述元。此外,return_type_idx 欄位必須是 type_ids 區段的有效索引,而 parameters_off 欄位必須是零,或是指向 data 區段的有效偏移量。如果不為零,參數清單不得包含任何無效項目。 |
G18 |
對於每個 field_id_item ,class_idx 和 type_idx 欄位都必須是 type_ids 清單中的有效索引。class_idx 參照的項目必須是非陣列參照類型。此外,name_idx 欄位必須是 string_ids 區段的有效參照,且參照項目的內容必須符合 MemberName 規格。 |
G19 |
對於每個 method_id_item ,class_idx 欄位必須是 type_ids 區段中的有效索引,且參照的項目必須是陣列以外的參照類型。proto_id 欄位必須是 proto_ids 清單中的有效參照。name_idx 欄位必須是 string_ids 部分的有效參照,且參照項目的內容必須符合 MemberName 規格。 |
G20 |
對於每個 field_id_item ,class_idx 欄位必須是 type_ids 清單中的有效索引。參照的項目必須是非陣列參照類型。 |
靜態位元碼限制
靜態限制是對位元碼個別元素的限制。通常不需要採用控制或資料流分析技術,即可檢查這些項目。
ID | 說明 |
---|---|
A1 |
insns 陣列不得為空白。 |
A2 |
insns 陣列中的第一個 Opcode 必須有索引 0。 |
A3 |
insns 陣列只能包含有效的 Dalvik 指令碼。 |
A4 |
指令 n+1 的索引必須等於指令 n 的索引加上指令 n 的長度,並考量可能的運算元。 |
A5 |
insns 陣列中的最後一個指令必須在索引 insns_size-1 結束。 |
A6 |
所有 goto 和 if-<kind> 目標都必須是同一個方法中的運算碼。 |
A7 |
packed-switch 指令的所有目標都必須是同一個方法中的運算碼。目標的大小和清單必須一致。 |
A8 |
sparse-switch 指令的所有目標都必須是同一個方法中的運算碼。對應的資料表必須一致,且以低至高的順序排序。 |
A9 |
const-string 和 const-string/jumbo 指令的 B 運算元必須是字串常數集合的有效索引。 |
A10 |
iget<kind> 和 iput<kind> 指令的 C 運算元必須是欄位常數集區的有效索引。參照的項目必須代表例項欄位。 |
A11 |
sget<kind> 和 sput<kind> 指令的 C 運算元必須是欄位常數集區的有效索引。參照的項目必須代表靜態欄位。 |
A12 |
invoke-virtual 、invoke-super 、invoke-direct 和 invoke-static 指令的 C 運算元必須是方法常數集區的有效索引。 |
A13 |
invoke-virtual/range 、invoke-super/range 、invoke-direct/range 和 invoke-static/range 指令的 B 運算元必須是方法常數集區的有效索引。 |
A14 |
名稱開頭為 '<' 的方法只能由 VM 隱含叫用,而非由來自 .dex 檔案的程式碼叫用。唯一例外狀況是執行個體初始化器,可能會由 invoke-direct 叫用。 |
A15 |
invoke-interface 指令的 C 運算元必須是方法常數集區中的有效索引。所參照的 method_id 必須屬於介面 (而非類別)。 |
A16 |
invoke-interface/range 指令的 B 運算元必須是方法常數集區中的有效索引。所參照的 method_id 必須屬於介面 (而非類別)。 |
A17 |
const-class 、check-cast 、new-instance 和 filled-new-array/range 指令的 B 運算元必須是類型常數集區的有效索引。 |
A18 |
instance-of 、new-array 和 filled-new-array 指令的 C 運算元必須是類型常數集區的有效索引。 |
A19 |
由 new-array 指令建立的陣列維度必須小於 256 。 |
A20 |
new 指令不得參照陣列類別、介面或抽象類別。 |
A21 |
new-array 指令所參照的類型必須是有效的非參照類型。 |
A22 |
以單一寬度 (非成對) 方式由指令參照的所有暫存器,必須對目前方法有效。也就是說,其索引必須是非負值,且小於 registers_size 。 |
A23 |
以雙寬度 (成對) 方式由指令參照的所有暫存器,必須對目前方法有效。也就是說,這些索引必須是非負值,且小於 registers_size-1 。 |
A24 |
invoke-virtual 和 invoke-direct 指令的 method_id 運算元必須屬於類別 (而非介面)。在 037 之前的 Dex 檔案中,invoke-super 和 invoke-static 指令也必須符合相同的條件。 |
A25 |
invoke-virtual/range 和 invoke-direct/range 指令的 method_id 運算元必須屬於類別 (而非介面)。在 037 之前的 Dex 檔案中,invoke-super/range 和 invoke-static/range 指令也必須符合相同的條件。 |
結構化位元碼限制
結構限制是指對位元碼的幾個元素之間關係的限制。通常必須採用控制或資料流分析技術,才能檢查這些問題。
ID | 說明 |
---|---|
B1 | 引數 (暫存器和立即值) 的數量和類型必須一律與指令相符。 |
B2 | 註冊組合不得分開。 |
B3 | 您必須先指派註冊 (或組合),才能讀取。 |
B4 |
invoke-direct 指令必須在目前類別或其中一個超類別中,呼叫例項初始化器或方法。 |
B5 | 例項初始化器只能在未初始化的例項上叫用。 |
B6 | 您只能在已初始化的例項上叫用例項方法,也只能在已初始化的例項上存取例項欄位。 |
B7 |
如果在執行個體初始化前再次執行相同的 new-instance 指令,則不得使用儲存 new-instance 指令結果的暫存器。 |
B8 |
在存取任何例項成員之前,例項初始化器必須呼叫另一個例項初始化器 (相同的類別或超類別)。例外狀況是未繼承的例項欄位,可在呼叫其他初始化器之前指派,以及一般 Object 類別。 |
B9 | 所有實際方法引數都必須與其對應的形式引數相容。 |
B10 | 針對每個例項方法叫用作業,實際例項必須與指令中指定的類別或介面相容。 |
B11 |
return<kind> 指令必須與其方法的傳回類型相符。 |
B12 | 存取父類別的受保護成員時,所存取的例項實際類型必須是目前類別或其子類別之一。 |
B13 | 儲存至靜態欄位的值類型,必須與欄位類型相容或可轉換為該類型。 |
B14 | 儲存至欄位的值類型必須與欄位類型相容,或可轉換為欄位類型。 |
B15 | 儲存至陣列的每個值的類型,必須與陣列的元件類型相容。 |
B16 |
throw 指令的 A 運算元必須與 java.lang.Throwable 相容。 |
B17 |
方法可到達的最後一個指令必須是回溯 goto 或分支、return 或 throw 指令。insns 陣列不得留在底部。 |
B18 | 在未重新指派其他指令之前,先前註冊組未指派的一半可能無法讀取 (視為無效)。 |
B19 |
move-result<kind> 指令必須在 insns 陣列中,緊接著 invoke-<kind> 指令。唯一例外的是 move-result-object 指令,其前方也可能有 filled-new-array 指令。 |
B20 |
move-result<kind> 指令必須在實際控制流程中,立即接在相符的 return-<kind> 指令之前 (不得跳轉至該指令)。唯一例外的是 move-result-object 指令,其前方也可能有 filled-new-array 指令。 |
B21 |
move-exception 指令只能出現在例外狀況處理程序的第一個指令中。 |
B22 |
控制流程不得存取 packed-switch-data 、sparse-switch-data 和 fill-array-data 擬似指令。 |