Vincoli

Un file .dex è il formato di trasporto per il bytecode Dalvik. Esistono alcuni vincoli sintattici e semantici affinché un file sia un file .dex valido ed è necessario un runtime per supportare solo file .dex validi.

Vincoli generali di integrità del file .dex

I vincoli generali di integrità riguardano la struttura più ampia di un file .dex , come descritto in dettaglio nel formato .dex .

Identificatore Descrizione
G1 Il numero magic del file .dex deve essere dex\n035\0 o dex\n037\0 .
G2 Il checksum deve essere un checksum Adler-32 dell'intero contenuto del file eccetto magic e il campo checksum .
G3 La firma deve essere un hash SHA-1 dell'intero contenuto del file tranne magic , checksum e signature .
G4 file_size deve corrispondere alla dimensione effettiva del file in byte.
G5 header_size deve avere il valore: 0x70
G6 L' endian_tag deve avere il valore: ENDIAN_CONSTANT o REVERSE_ENDIAN_CONSTANT
G7 Per ciascuna delle link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs e data , i campi offset e size devono essere entrambi zero o entrambi diversi da zero. In quest'ultimo caso, l'offset deve essere allineato a quattro byte.
G8 Tutti i campi offset nell'intestazione tranne map_off devono essere allineati a quattro byte.
G9 Il campo map_off deve essere zero o puntare nella sezione dati. In quest'ultimo caso la sezione data deve esistere.
G10 Nessuno dei link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs e le sezioni data devono sovrapporsi tra loro o con l'intestazione.
G11 Se esiste una mappa, ciascuna voce della mappa deve avere un tipo valido. Ciascun tipo può apparire al massimo una volta.
G12 Se esiste una mappa, ciascuna voce della mappa deve avere un offset e una dimensione diversi da zero. L'offset deve puntare alla sezione corrispondente del file (cioè string_id_item deve puntare alla sezione string_ids ) e la dimensione esplicita o implicita dell'elemento deve corrispondere al contenuto effettivo e alla dimensione della sezione.
G13 Se esiste una mappa, l'offset della voce della mappa n+1 deve essere maggiore o uguale all'offset della voce della mappa n plus than size of map entry n . Ciò implica voci non sovrapposte e un ordinamento dal basso all'alto.
G14 I seguenti tipi di voci devono avere un offset allineato a quattro byte: 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 Per ogni string_id_item , il campo string_data_off deve contenere un riferimento valido nella sezione data . Per string_data_item di riferimento, il campo data deve contenere una stringa MUTF-8 valida e utf16_size deve corrispondere alla lunghezza decodificata della stringa.
G16 Per ogni type_id_item , il campo descriptor_idx deve contenere un riferimento valido nell'elenco string_ids . La stringa di riferimento deve essere un descrittore di tipo valido.
G17 Per ogni proto_id_item , il campo shorty_idx deve contenere un riferimento valido nell'elenco string_ids . La stringa di riferimento deve essere un descrittore breve valido. Inoltre, il campo return_type_idx deve essere un indice valido nella sezione type_ids e il campo parameters_off deve essere zero o un offset valido che punta alla sezione data . Se diverso da zero, l'elenco dei parametri non deve contenere voci nulle.
G18 Per ogni field_id_item , entrambi i campi class_idx e type_idx devono essere indici validi nell'elenco type_ids . La voce a cui fa riferimento class_idx deve essere un tipo di riferimento non array. Inoltre, il campo name_idx deve essere un riferimento valido nella sezione string_ids e il contenuto della voce di riferimento deve essere conforme alla specifica MemberName .
G19 Per ogni method_id_item , il campo class_idx deve essere un indice valido nella sezione type_ids e la voce a cui si fa riferimento deve essere un tipo di riferimento non array. Il campo proto_id deve essere un riferimento valido nell'elenco proto_ids . Il campo name_idx deve essere un riferimento valido nella sezione string_ids e il contenuto della voce di riferimento deve essere conforme alla specifica MemberName .
G20 Per ogni field_id_item , il campo class_idx deve essere un indice valido nell'elenco type_ids . La voce a cui si fa riferimento deve essere un tipo di riferimento non array.

Vincoli statici del bytecode

I vincoli statici sono vincoli sui singoli elementi del bytecode. Di solito possono essere controllati senza impiegare tecniche di controllo o di analisi del flusso di dati.

Identificatore Descrizione
A1 L'array insns non deve essere vuoto.
A2 Il primo codice operativo nell'array insns deve avere indice zero.
A3 L'array insns deve contenere solo codici operativi Dalvik validi.
A4 L'indice dell'istruzione n+1 deve essere uguale all'indice dell'istruzione n più la lunghezza dell'istruzione n , tenendo conto dei possibili operandi.
A5 L'ultima istruzione nell'array insns deve terminare con l'indice insns_size-1 .
A6 Tutti i target goto e if-<kind> devono essere codici operativi all'interno dello stesso metodo.
A7 Tutti i target di un'istruzione packed-switch devono essere codici operativi all'interno dello stesso metodo. La dimensione e l'elenco degli obiettivi devono essere coerenti.
A8 Tutti i target di un'istruzione sparse-switch devono essere codici operativi all'interno dello stesso metodo. La tabella corrispondente deve essere coerente e ordinata dal basso verso l'alto.
A9 L'operando B delle istruzioni const-string e const-string/jumbo deve essere un indice valido nel pool di costanti di stringa.
A10 L'operando C delle istruzioni iget<kind> e iput<kind> deve essere un indice valido nel pool di costanti di campo. La voce a cui si fa riferimento deve rappresentare un campo di istanza.
A11 L'operando C delle istruzioni sget<kind> e sput<kind> deve essere un indice valido nel pool di costanti di campo. La voce a cui si fa riferimento deve rappresentare un campo statico.
A12 L'operando C delle istruzioni invoke-virtual , invoke-super , invoke-direct e invoke-static deve essere un indice valido nel pool di costanti del metodo.
A13 L'operando B delle istruzioni invoke-virtual/range , invoke-super/range , invoke-direct/range e invoke-static/range deve essere un indice valido nel pool di costanti del metodo.
A14 Un metodo il cui nome inizia con "<" deve essere invocato solo implicitamente dalla VM, non dal codice proveniente da un file .dex . L'unica eccezione è l'inizializzatore dell'istanza, che può essere richiamato da invoke-direct .
A15 L'operando C dell'istruzione invoke-interface deve essere un indice valido nel pool di costanti del metodo. Il method_id a cui si fa riferimento deve appartenere a un'interfaccia (non a una classe).
A16 L'operando B dell'istruzione invoke-interface/range deve essere un indice valido nel pool di costanti del metodo. Il method_id a cui si fa riferimento deve appartenere a un'interfaccia (non a una classe).
A17 L'operando B delle istruzioni const-class , check-cast , new-instance filled-new-array/range deve essere un indice valido nel pool di costanti di tipo.
A18 L'operando C delle istruzioni instance-of , new-array filled-new-array deve essere un indice valido nel pool di costanti di tipo.
A19 Le dimensioni di un array creato da un'istruzione new-array devono essere inferiori a 256 .
A20 La new istruzione non deve fare riferimento a classi di array, interfacce o classi astratte.
A21 Il tipo a cui fa riferimento un'istruzione new-array deve essere un tipo valido, non di riferimento.
A22 Tutti i registri a cui fa riferimento un'istruzione in modalità a larghezza singola (non a coppia) devono essere validi per il metodo corrente. Cioè, i loro indici devono essere non negativi e inferiori a registers_size .
A23 Tutti i registri a cui fa riferimento un'istruzione in modo a doppia larghezza (coppia) devono essere validi per il metodo corrente. Cioè, i loro indici devono essere non negativi e più piccoli di registers_size-1 .
A24 L'operando method_id delle istruzioni invoke-virtual e invoke-direct deve appartenere a una classe (non a un'interfaccia). Nei file Dex precedenti alla versione 037 lo stesso deve valere per le istruzioni invoke-super e invoke-static .
A25 L'operando method_id delle istruzioni invoke-virtual/range e invoke-direct/range deve appartenere a una classe (non a un'interfaccia). Nei file Dex precedenti alla versione 037 lo stesso deve valere per le istruzioni invoke-super/range e invoke-static/range .

Vincoli strutturali del bytecode

I vincoli strutturali sono vincoli sulle relazioni tra diversi elementi del bytecode. Di solito non possono essere controllati senza impiegare tecniche di controllo o di analisi del flusso di dati.

Identificatore Descrizione
B1 Il numero e il tipo di argomenti (registri e valori immediati) devono sempre corrispondere all'istruzione.
B2 Le coppie di registri non devono mai essere scisse.
B3 Un registro (o una coppia) deve essere assegnato prima di poter essere letto.
B4 Un'istruzione invoke-direct deve invocare un inizializzatore di istanza o un metodo solo nella classe corrente o in una delle sue superclassi.
B5 Un inizializzatore di istanza deve essere richiamato solo su un'istanza non inizializzata.
B6 I metodi dell'istanza possono essere invocati solo su e i campi dell'istanza sono accessibili solo su istanze già inizializzate.
B7 Un registro che contiene il risultato di un'istruzione new-instance non deve essere utilizzato se la stessa istruzione new-instance viene nuovamente eseguita prima che l'istanza venga inizializzata.
B8 Un inizializzatore di istanza deve chiamare un altro inizializzatore di istanza (stessa classe o superclasse) prima che sia possibile accedere a qualsiasi membro dell'istanza. Le eccezioni sono i campi di istanza non ereditati, che possono essere assegnati prima di chiamare un altro inizializzatore, e la classe Object in generale.
B9 Tutti gli argomenti effettivi del metodo devono essere compatibili con l'assegnazione con i rispettivi argomenti formali.
B10 Per ogni chiamata al metodo di istanza, l'istanza effettiva deve essere compatibile con l'assegnazione della classe o dell'interfaccia specificata nell'istruzione.
B11 Un'istruzione return<kind> deve corrispondere al tipo restituito del relativo metodo.
B12 Quando si accede ai membri protetti di una superclasse, il tipo effettivo dell'istanza a cui si accede deve essere la classe corrente o una delle sue sottoclassi.
B13 Il tipo di un valore archiviato in un campo statico deve essere compatibile con l'assegnazione o convertibile nel tipo del campo.
B14 Il tipo di un valore archiviato in un campo deve essere compatibile con l'assegnazione o convertibile nel tipo del campo.
B15 Il tipo di ogni valore archiviato in un array deve essere compatibile con l'assegnazione del tipo di componente dell'array.
B16 L'operando A di un'istruzione throw deve essere compatibile con l'assegnazione con java.lang.Throwable .
B17 L'ultima istruzione raggiungibile di un metodo deve essere un goto o un branch all'indietro, un return o un'istruzione throw . Non deve essere possibile lasciare l'array insns in fondo.
B18 La metà non assegnata di una precedente coppia di registri non può essere letta (è considerata non valida) finché non viene riassegnata da qualche altra istruzione.
B19 Un'istruzione move-result<kind> deve essere immediatamente preceduta (nell'array insns ) da un'istruzione invoke-<kind> . L'unica eccezione è l'istruzione move-result-object , che può anche essere preceduta da un'istruzione filled-new-array .
B20 Un'istruzione move-result<kind> deve essere immediatamente preceduta (nel flusso di controllo effettivo) da un'istruzione return-<kind> corrispondente (non deve essere saltata a essa). L'unica eccezione è l'istruzione move-result-object , che può anche essere preceduta da un'istruzione filled-new-array .
B21 Un'istruzione move-exception deve apparire solo come prima istruzione in un gestore di eccezioni.
B22 Le pseudoistruzioni packed-switch-data , sparse-switch-data e fill-array-data non devono essere raggiungibili dal flusso di controllo.