Ograniczenia

Plik .dex to format transportowy kodu bajtowego Dalvik. Istnieją pewne ograniczenia składniowe i semantyczne, aby plik był prawidłowym plikiem .dex , a do obsługi tylko prawidłowych plików .dex wymagane jest środowisko wykonawcze.

Ogólne ograniczenia integralności .dex

Ogólne ograniczenia integralności dotyczą większej struktury pliku .dex , jak opisano szczegółowo w formacie .dex .

Identyfikator Opis
G1 magic liczba pliku .dex musi być dex\n035\0 lub dex\n037\0 .
G2 Suma kontrolna musi być sumą kontrolną Adler-32 całej zawartości pliku z wyjątkiem pola magic i checksum .
G3 Podpis musi być skrótem SHA-1 całej zawartości pliku z wyjątkiem magic , checksum i signature .
G4 file_size musi odpowiadać rzeczywistemu rozmiarowi pliku w bajtach.
G5 header_size musi mieć wartość: 0x70
G6 endian_tag musi mieć wartość: ENDIAN_CONSTANT lub REVERSE_ENDIAN_CONSTANT
G7 Dla każdego link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs i sekcji data pola offset i size muszą mieć wartość zerową lub różną od zera. W tym drugim przypadku przesunięcie musi być wyrównane do czterech bajtów.
G8 Wszystkie pola przesunięcia w nagłówku, z wyjątkiem map_off muszą być wyrównane do czterech bajtów.
G9 Pole map_off musi mieć wartość zero lub wskazywać sekcję danych. W tym drugim przypadku sekcja data musi istnieć.
G10 Żaden z link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs i sekcji data nie może nakładać się na siebie ani na nagłówek.
G11 Jeśli mapa istnieje, każdy wpis mapy musi mieć prawidłowy typ. Każdy typ może wystąpić najwyżej raz.
G12 Jeśli mapa istnieje, każdy wpis mapy musi mieć niezerowe przesunięcie i rozmiar. Przesunięcie musi wskazywać odpowiednią sekcję pliku (tzn. string_id_item musi wskazywać sekcję string_ids ), a jawny lub ukryty rozmiar elementu musi odpowiadać rzeczywistej zawartości i rozmiarowi sekcji.
G13 Jeżeli mapa istnieje, to przesunięcie wpisu mapy n+1 musi być większe lub równe przesunięciu wpisu mapy n plus than size of map entry n . Oznacza to, że wpisy nie nakładają się na siebie i są uporządkowane od najniższego do najwyższego.
G14 Następujące typy wpisów muszą mieć offset wyrównany do czterech bajtów: 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 Dla każdego string_id_item pole string_data_off musi zawierać prawidłowe odwołanie do sekcji data . W przypadku przywoływanego string_data_item pole data musi zawierać prawidłowy ciąg MUTF-8, a utf16_size musi odpowiadać zdekodowanej długości ciągu.
G16 Dla każdego type_id_item pole descriptor_idx musi zawierać prawidłowe odwołanie do listy string_ids . Ciąg, do którego następuje odwołanie, musi być prawidłowym deskryptorem typu.
G17 Dla każdego proto_id_item pole shorty_idx musi zawierać prawidłowe odwołanie do listy string_ids . Ciąg, do którego następuje odwołanie, musi być prawidłowym krótkim deskryptorem. Ponadto pole return_type_idx musi być prawidłowym indeksem sekcji type_ids , a pole parameters_off musi mieć wartość zero lub prawidłowe przesunięcie wskazujące sekcję data . Jeśli jest różna od zera, lista parametrów nie może zawierać żadnych pustych wpisów.
G18 Dla każdego field_id_item oba pola class_idx i type_idx muszą być prawidłowymi indeksami na liście type_ids . Wpis, do którego odwołuje się class_idx musi być typem odwołania innym niż tablica. Ponadto pole name_idx musi stanowić prawidłowe odwołanie do sekcji string_ids , a zawartość wpisu, do którego się odwołuje, musi być zgodna ze specyfikacją MemberName .
G19 Dla każdego method_id_item pole class_idx musi być prawidłowym indeksem w sekcji type_ids , a wpis, do którego się odwołuje, musi być typem referencyjnym innym niż tablicowy. Pole proto_id musi być prawidłowym odniesieniem do listy proto_ids . Pole name_idx musi być prawidłowym odniesieniem do sekcji string_ids , a zawartość wpisu, do którego się odwołuje, musi być zgodna ze specyfikacją MemberName .
G20 Dla każdego field_id_item pole class_idx musi być prawidłowym indeksem na liście type_ids . Wpis, do którego następuje odwołanie, musi być typem odniesienia innym niż tablicowy.

Statyczne ograniczenia kodu bajtowego

Ograniczenia statyczne to ograniczenia nałożone na poszczególne elementy kodu bajtowego. Zwykle można je sprawdzić bez stosowania technik kontroli lub analizy przepływu danych.

Identyfikator Opis
A1 Tablica insns nie może być pusta.
A2 Pierwszy kod operacji w tablicy insns musi mieć indeks zero.
A3 Tablica insns musi zawierać tylko prawidłowe kody operacji Dalvik.
A4 Indeks instrukcji n+1 musi być równy indeksowi instrukcji n plus długość instrukcji n , biorąc pod uwagę możliwe argumenty.
A5 Ostatnia instrukcja w tablicy insns musi kończyć się indeksem insns_size-1 .
A6 Wszystkie cele goto i if-<kind> muszą być kodami operacji w ramach tej samej metody.
A7 Wszystkie cele instrukcji packed-switch muszą być kodami operacji w ramach tej samej metody. Rozmiar i lista celów muszą być spójne.
A8 Wszystkie cele instrukcji sparse-switch muszą być kodami operacji w ramach tej samej metody. Odpowiednia tabela musi być spójna i posortowana od najniższej do najwyższej.
A9 Operand B instrukcji const-string i const-string/jumbo musi być prawidłowym indeksem puli stałych łańcuchowych.
A10 Operand C instrukcji iget<kind> i iput<kind> musi być poprawnym indeksem puli stałych pola. Wpis, do którego następuje odwołanie, musi reprezentować pole instancji.
A11 Operand C instrukcji sget<kind> i sput<kind> musi być poprawnym indeksem puli stałych pola. Wpis, do którego następuje odwołanie, musi reprezentować pole statyczne.
A12 Operand C instrukcji invoke-virtual , invoke-super , invoke-direct i invoke-static musi być prawidłowym indeksem w puli stałych metod.
A13 Operand B instrukcji invoke-virtual/range , invoke-super/range , invoke-direct/range i invoke-static/range musi być prawidłowym indeksem w puli stałych metod.
A14 Metoda, której nazwa zaczyna się od znaku „<”, może zostać wywołana tylko pośrednio przez maszynę wirtualną, a nie przez kod pochodzący z pliku .dex . Jedynym wyjątkiem jest inicjator instancji, który może zostać wywołany przez invoke-direct .
A15 Operand C instrukcji invoke-interface musi być prawidłowym indeksem w puli stałych metod. Odwoływany method_id musi należeć do interfejsu (nie do klasy).
A16 Operand B instrukcji invoke-interface/range musi być prawidłowym indeksem w puli stałych metody. Odwoływany method_id musi należeć do interfejsu (nie do klasy).
A17 Operand B instrukcji const-class , check-cast , new-instance i filled-new-array/range musi być prawidłowym indeksem puli stałych typów.
A18 Operand C instrukcji instance-of , new-array i filled-new-array musi być prawidłowym indeksem puli stałych typów.
A19 Wymiary tablicy utworzonej za pomocą instrukcji new-array muszą być mniejsze niż 256 .
A20 new instrukcja nie może odnosić się do klas tablicowych, interfejsów ani klas abstrakcyjnych.
A21 Typ, do którego odwołuje się instrukcja new-array musi być prawidłowym typem, który nie jest typem referencyjnym.
A22 Wszystkie rejestry, do których odwołuje się instrukcja w trybie o pojedynczej szerokości (nieparowej), muszą być ważne dla bieżącej metody. Oznacza to, że ich indeksy muszą być nieujemne i mniejsze niż registers_size .
A23 Wszystkie rejestry, do których odnosi się instrukcja w trybie podwójnej szerokości (pary), muszą być ważne dla bieżącej metody. Oznacza to, że ich indeksy muszą być nieujemne i mniejsze niż registers_size-1 .
A24 Operand method_id instrukcji invoke-virtual i invoke-direct musi należeć do klasy (nie do interfejsu). W plikach Dex wcześniejszych niż wersja 037 to samo musi dotyczyć instrukcji invoke-super i invoke-static .
A25 Operand method_id instrukcji invoke-virtual/range i invoke-direct/range musi należeć do klasy (nie do interfejsu). W plikach Dex wcześniejszych niż wersja 037 to samo musi dotyczyć instrukcji invoke-super/range i invoke-static/range .

Strukturalne ograniczenia kodu bajtowego

Ograniczenia strukturalne to ograniczenia relacji między kilkoma elementami kodu bajtowego. Zwykle nie można ich sprawdzić bez zastosowania technik kontroli lub analizy przepływu danych.

Identyfikator Opis
B1 Liczba i typy argumentów (rejestry i wartości bezpośrednie) muszą zawsze odpowiadać instrukcji.
B2 Pary rejestrów nie mogą być nigdy rozdzielane.
B3 Rejestr (lub para) musi zostać najpierw przypisany, zanim będzie można go odczytać.
B4 Instrukcja invoke-direct musi wywołać inicjator instancji lub metodę tylko w bieżącej klasie lub jednej z jej nadklas.
B5 Inicjator instancji musi być wywoływany tylko w przypadku niezainicjowanej instancji.
B6 Metody instancji można wywoływać tylko na instancjach, a dostęp do pól instancji można uzyskać tylko na instancjach już zainicjowanych.
B7 Rejestru przechowującego wynik instrukcji new-instance nie można używać, jeśli ta sama instrukcja new-instance zostanie wykonana ponownie przed inicjalizacją instancji.
B8 Inicjator instancji musi wywołać inny inicjator instancji (ta sama klasa lub nadklasa), zanim będzie można uzyskać dostęp do elementów członkowskich instancji. Wyjątkami są niedziedziczone pola instancji, które można przypisać przed wywołaniem innego inicjatora, oraz ogólnie klasa Object .
B9 Wszystkie rzeczywiste argumenty metod muszą być zgodne z przypisaniem z ich odpowiednimi argumentami formalnymi.
B10 Dla każdego wywołania metody instancji rzeczywista instancja musi być zgodna z przypisaniem z klasą lub interfejsem określonym w instrukcji.
B11 Instrukcja return<kind> musi odpowiadać typowi zwracanemu przez jej metodę.
B12 Podczas uzyskiwania dostępu do chronionych elementów nadklasy rzeczywistym typem instancji, do której uzyskuje się dostęp, musi być albo bieżąca klasa, albo jedna z jej podklas.
B13 Typ wartości przechowywanej w polu statycznym musi być zgodny z przypisaniem lub konwertowalny na typ pola.
B14 Typ wartości przechowywanej w polu musi być zgodny z przypisaniem lub konwertowalny na typ pola.
B15 Typ każdej wartości przechowywanej w tablicy musi być zgodny z przypisaniem z typem komponentu tablicy.
B16 Operand A instrukcji throw musi być kompatybilny z java.lang.Throwable .
B17 Ostatnią osiągalną instrukcją metody musi być instrukcja goto lub rozgałęzienia wstecz, instrukcja return lub instrukcja throw . Nie może być możliwe pozostawienie tablicy insns na dole.
B18 Nieprzypisana połowa poprzedniej pary rejestrów nie może zostać odczytana (jest uważana za nieważną), dopóki nie zostanie ponownie przypisana przez jakąś inną instrukcję.
B19 Instrukcja move-result<kind> musi być bezpośrednio poprzedzona (w tablicy insns ) instrukcją invoke-<kind> . Jedynym wyjątkiem jest instrukcja move-result-object , która może być również poprzedzona instrukcją filled-new-array .
B20 Instrukcja move-result<kind> musi być bezpośrednio poprzedzona (w rzeczywistym przepływie sterowania) pasującą instrukcją return-<kind> (nie wolno do niej przechodzić). Jedynym wyjątkiem jest instrukcja move-result-object , która może być również poprzedzona instrukcją filled-new-array .
B21 Instrukcja move-exception musi pojawić się tylko jako pierwsza instrukcja w procedurze obsługi wyjątku.
B22 Pseudoinstrukcje packed-switch-data , sparse-switch-data i fill-array-data nie mogą być osiągalne przez przepływ sterowania.