Contraintes

Un fichier .dex est le format de transport du bytecode Dalvik. Il existe certaines contraintes syntaxiques et sémantiques pour qu'un fichier soit un fichier .dex valide, et un environnement d'exécution est requis pour prendre en charge uniquement les fichiers .dex valides.

Contraintes générales d’intégrité .dex

Les contraintes générales d'intégrité concernent la structure plus large d'un fichier .dex , comme décrit en détail dans le format .dex .

Identifiant Description
G1 Le nombre magic du fichier .dex doit être dex\n035\0 ou dex\n037\0 .
G2 La somme de contrôle doit être une somme de contrôle Adler-32 de tout le contenu du fichier, à l'exception des champs magic et checksum .
G3 La signature doit être un hachage SHA-1 de tout le contenu du fichier à l'exception magic , checksum et signature .
G4 Le file_size doit correspondre à la taille réelle du fichier en octets.
G5 Le header_size doit avoir la valeur : 0x70
G6 Le endian_tag doit avoir soit la valeur : ENDIAN_CONSTANT ou REVERSE_ENDIAN_CONSTANT
G7 Pour chacune des link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs et data , les champs offset et size doivent être tous deux nuls ou non nuls. Dans ce dernier cas, le décalage doit être aligné sur quatre octets.
G8 Tous les champs de décalage dans l'en-tête, à l'exception map_off doivent être alignés sur quatre octets.
G9 Le champ map_off doit être soit zéro, soit pointer vers la section de données. Dans ce dernier cas, la section data doit exister.
G10 Aucun des éléments link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs et data sections ne doit se chevaucher ni se chevaucher dans l'en-tête.
G11 Si une carte existe, chaque entrée de carte doit avoir un type valide. Chaque type peut apparaître au maximum une fois.
G12 Si une carte existe, chaque entrée de carte doit avoir un décalage et une taille non nuls. Le décalage doit pointer vers la section correspondante du fichier (c'est-à-dire qu'un string_id_item doit pointer vers la section string_ids ) et la taille explicite ou implicite de l'élément doit correspondre au contenu et à la taille réels de la section.
G13 Si une carte existe, alors le décalage de l'entrée de carte n+1 doit être supérieur ou égal au décalage de l'entrée de carte n plus than size of map entry n . Cela implique des entrées qui ne se chevauchent pas et un ordre croissant.
G14 Les types d'entrées suivants doivent avoir un décalage aligné sur quatre octets : 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 Pour chaque string_id_item , le champ string_data_off doit contenir une référence valide dans la section data . Pour le string_data_item référencé, le champ data doit contenir une chaîne MUTF-8 valide et le utf16_size doit correspondre à la longueur décodée de la chaîne.
G16 Pour chaque type_id_item , le champ descriptor_idx doit contenir une référence valide dans la liste string_ids . La chaîne référencée doit être un descripteur de type valide.
G17 Pour chaque proto_id_item , le champ shorty_idx doit contenir une référence valide dans la liste string_ids . La chaîne référencée doit être un descripteur shorty valide. De plus, le champ return_type_idx doit être un index valide dans la section type_ids , et le champ parameters_off doit être soit zéro, soit un décalage valide pointant vers la section data . Si elle est différente de zéro, la liste de paramètres ne doit contenir aucune entrée vide.
G18 Pour chaque field_id_item , les champs class_idx et type_idx doivent être des indices valides dans la liste type_ids . L'entrée référencée par class_idx doit être un type de référence non-tableau. De plus, le champ name_idx doit être une référence valide dans la section string_ids et le contenu de l'entrée référencée doit être conforme à la spécification MemberName .
G19 Pour chaque method_id_item , le champ class_idx doit être un index valide dans la section type_ids et l'entrée référencée doit être un type de référence non-tableau. Le champ proto_id doit être une référence valide dans la liste proto_ids . Le champ name_idx doit être une référence valide dans la section string_ids et le contenu de l'entrée référencée doit être conforme à la spécification MemberName .
G20 Pour chaque field_id_item , le champ class_idx doit être un index valide dans la liste type_ids . L’entrée référencée doit être un type de référence non-tableau.

Contraintes de bytecode statique

Les contraintes statiques sont des contraintes sur des éléments individuels du bytecode. Ils peuvent généralement être vérifiés sans recourir à des techniques de contrôle ou d’analyse des flux de données.

Identifiant Description
A1 Le tableau insns ne doit pas être vide.
A2 Le premier opcode du tableau insns doit avoir l'index zéro.
A3 Le tableau insns doit contenir uniquement des opcodes Dalvik valides.
A4 L'indice de l'instruction n+1 doit être égal à l'indice de l'instruction n plus la longueur de l'instruction n , en tenant compte des opérandes possibles.
A5 La dernière instruction du tableau insns doit se terminer à l'index insns_size-1 .
A6 Toutes les cibles goto et if-<kind> doivent être des opcodes au sein de la même méthode.
A7 Toutes les cibles d'une instruction packed-switch doivent être des opcodes au sein de la même méthode. La taille et la liste des cibles doivent être cohérentes.
A8 Toutes les cibles d’une instruction sparse-switch doivent être des opcodes au sein de la même méthode. Le tableau correspondant doit être cohérent et trié de bas en haut.
A9 L'opérande B des instructions const-string et const-string/jumbo doit être un index valide dans le pool de constantes de chaîne.
A10 L'opérande C des instructions iget<kind> et iput<kind> doit être un index valide dans le pool de constantes de champ. L'entrée référencée doit représenter un champ d'instance.
A11 L'opérande C des instructions sget<kind> et sput<kind> doit être un index valide dans le pool de constantes de champ. L'entrée référencée doit représenter un champ statique.
A12 L'opérande C des instructions invoke-virtual , invoke-super , invoke-direct et invoke-static doit être un index valide dans le pool de constantes de méthode.
A13 L'opérande B des instructions invoke-virtual/range , invoke-super/range , invoke-direct/range et invoke-static/range doit être un index valide dans le pool de constantes de méthode.
A14 Une méthode dont le nom commence par un '<' ne doit être invoquée qu'implicitement par la VM, et non par du code provenant d'un fichier .dex . La seule exception est l'initialiseur d'instance, qui peut être invoqué par invoke-direct .
A15 L'opérande C de l'instruction invoke-interface doit être un index valide dans le pool de constantes de méthode. Le method_id référencé doit appartenir à une interface (pas à une classe).
A16 L’opérande B de l’instruction invoke-interface/range doit être un index valide dans le pool de constantes de méthode. Le method_id référencé doit appartenir à une interface (pas à une classe).
A17 L'opérande B des instructions const-class , check-cast , new-instance et filled-new-array/range doit être un index valide dans le pool de constantes de type.
A18 L'opérande C des instructions instance-of , new-array et filled-new-array doit être un index valide dans le pool de constantes de type.
A19 Les dimensions d'un tableau créé par une instruction new-array doivent être inférieures à 256 .
A20 La new instruction ne doit pas faire référence à des classes de tableau, des interfaces ou des classes abstraites.
A21 Le type auquel fait référence une instruction new-array doit être un type valide et sans référence.
A22 Tous les registres référencés par une instruction de manière simple largeur (sans paire) doivent être valides pour la méthode actuelle. Autrement dit, leurs indices doivent être non négatifs et plus petits que registers_size .
A23 Tous les registres référencés par une instruction en double largeur (paire) doivent être valides pour la méthode actuelle. Autrement dit, leurs indices doivent être non négatifs et plus petits que registers_size-1 .
A24 L’opérande method_id des instructions invoke-virtual et invoke-direct doit appartenir à une classe (pas à une interface). Dans les fichiers Dex antérieurs à la version 037 , il doit en être de même pour les instructions invoke-super et invoke-static .
A25 L’opérande method_id des instructions invoke-virtual/range et invoke-direct/range doit appartenir à une classe (pas à une interface). Dans les fichiers Dex antérieurs à la version 037 , il doit en être de même pour les instructions invoke-super/range et invoke-static/range .

Contraintes structurelles du bytecode

Les contraintes structurelles sont des contraintes sur les relations entre plusieurs éléments du bytecode. Ils ne peuvent généralement pas être vérifiés sans recourir à des techniques de contrôle ou d’analyse des flux de données.

Identifiant Description
B1 Le nombre et les types d'arguments (registres et valeurs immédiates) doivent toujours correspondre à l'instruction.
B2 Les paires de registres ne doivent jamais être divisées.
B3 Un registre (ou une paire) doit d'abord être attribué avant de pouvoir être lu.
B4 Une instruction invoke-direct doit appeler un initialiseur d'instance ou une méthode uniquement dans la classe actuelle ou l'une de ses superclasses.
B5 Un initialiseur d'instance doit être invoqué uniquement sur une instance non initialisée.
B6 Les méthodes d'instance ne peuvent être invoquées que sur et les champs d'instance ne sont accessibles que sur des instances déjà initialisées.
B7 Un registre contenant le résultat d'une instruction new-instance ne doit pas être utilisé si la même instruction new-instance est à nouveau exécutée avant l'initialisation de l'instance.
B8 Un initialiseur d'instance doit appeler un autre initialiseur d'instance (même classe ou superclasse) avant de pouvoir accéder aux membres de l'instance. Les exceptions sont les champs d'instance non hérités, qui peuvent être attribués avant d'appeler un autre initialiseur, et la classe Object en général.
B9 Tous les arguments de méthode réels doivent être compatibles avec leurs arguments formels respectifs.
B10 Pour chaque appel de méthode d'instance, l'instance réelle doit être compatible en termes d'affectation avec la classe ou l'interface spécifiée dans l'instruction.
B11 Une instruction return<kind> doit correspondre au type de retour de sa méthode.
B12 Lors de l'accès aux membres protégés d'une superclasse, le type réel de l'instance accessible doit être soit la classe actuelle, soit l'une de ses sous-classes.
B13 Le type d'une valeur stockée dans un champ statique doit être compatible avec l'affectation ou convertible en type du champ.
B14 Le type d'une valeur stockée dans un champ doit être compatible avec l'affectation ou convertible en type du champ.
B15 Le type de chaque valeur stockée dans un tableau doit être compatible en termes d'affectation avec le type de composant du tableau.
B16 L'opérande A d'une instruction throw doit être compatible avec l'affectation avec java.lang.Throwable .
B17 La dernière instruction accessible d'une méthode doit être soit une instruction goto ou branch arrière, soit une instruction return ou une instruction throw . Il ne doit pas être possible de laisser le tableau insns en bas.
B18 La moitié non attribuée d'une ancienne paire de registres ne peut pas être lue (elle est considérée comme invalide) jusqu'à ce qu'elle ait été réaffectée par une autre instruction.
B19 Une instruction move-result<kind> doit être immédiatement précédée (dans le tableau insns ) d'une instruction invoke-<kind> . La seule exception est l'instruction move-result-object , qui peut également être précédée d'une instruction filled-new-array .
B20 Une instruction move-result<kind> doit être immédiatement précédée (dans le flux de contrôle réel) par une instruction return-<kind> correspondante (elle ne doit pas être sautée). La seule exception est l'instruction move-result-object , qui peut également être précédée d'une instruction filled-new-array .
B21 Une instruction move-exception doit apparaître uniquement comme première instruction dans un gestionnaire d’exceptions.
B22 Les pseudo-instructions packed-switch-data , sparse-switch-data et fill-array-data ne doivent pas être accessibles par le flux de contrôle.