Restricciones

Un archivo .dex es el formato de transporte para el código de bytes de Dalvik. Existen ciertas restricciones sintácticas y semánticas para que un archivo sea un archivo .dex válido, y se requiere un tiempo de ejecución para admitir solo archivos .dex válidos.

Restricciones generales de integridad de .dex

Las restricciones de integridad generales tienen que ver con la estructura más grande de un archivo .dex , como se describe en detalle en formato .dex .

Identificador Descripción
G1 El número magic del archivo .dex debe ser dex\n035\0 o dex\n037\0 .
G2 La suma de verificación debe ser una suma de verificación Adler-32 de todo el contenido del archivo excepto el campo magic y checksum .
G3 La firma debe ser un hash SHA-1 de todo el contenido del archivo, excepto magic , checksum y signature .
G4 file_size debe coincidir con el tamaño real del archivo en bytes.
G5 El header_size debe tener el valor: 0x70
G6 El endian_tag debe tener el valor: ENDIAN_CONSTANT o REVERSE_ENDIAN_CONSTANT
G7 Para cada una de las link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs y data , los campos offset y size deben ser cero o distintos de cero. En el último caso, el desplazamiento debe estar alineado con cuatro bytes.
G8 Todos los campos de desplazamiento en el encabezado, excepto map_off deben estar alineados con cuatro bytes.
G9 El campo map_off debe ser cero o apuntar a la sección de datos. En este último caso, la sección data debe existir.
G10 Ninguna de las link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs y data deben superponerse entre sí o con el encabezado.
G11 Si existe un mapa, cada entrada del mapa debe tener un tipo válido. Cada tipo puede aparecer como máximo una vez.
G12 Si existe un mapa, cada entrada del mapa debe tener un desplazamiento y un tamaño distintos de cero. El desplazamiento debe apuntar a la sección correspondiente del archivo (es decir, un string_id_item debe apuntar a la sección string_ids ) y el tamaño explícito o implícito del elemento debe coincidir con el contenido y el tamaño reales de la sección.
G13 Si existe un mapa, entonces el desplazamiento de la entrada del mapa n+1 debe ser mayor o igual al desplazamiento de la entrada del mapa n plus than size of map entry n . Esto implica entradas que no se superponen y un orden de menor a mayor.
G14 Los siguientes tipos de entradas deben tener un desplazamiento alineado con cuatro bytes: 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 Para cada string_id_item , el campo string_data_off debe contener una referencia válida a la sección data . Para el string_data_item al que se hace referencia, el campo data debe contener una cadena MUTF-8 válida y utf16_size debe coincidir con la longitud decodificada de la cadena.
G16 Para cada type_id_item , el campo descriptor_idx debe contener una referencia válida en la lista string_ids . La cadena a la que se hace referencia debe ser un descriptor de tipo válido.
G17 Para cada proto_id_item , el campo shorty_idx debe contener una referencia válida en la lista string_ids . La cadena a la que se hace referencia debe ser un descriptor breve válido. Además, el campo return_type_idx debe ser un índice válido en la sección type_ids , y el campo parameters_off debe ser cero o un desplazamiento válido que apunte a la sección data . Si es distinto de cero, la lista de parámetros no debe contener ninguna entrada nula.
G18 Para cada field_id_item , los campos class_idx y type_idx deben ser índices válidos en la lista type_ids . La entrada a la que hace referencia class_idx debe ser un tipo de referencia que no sea una matriz. Además, el campo name_idx debe ser una referencia válida a la sección string_ids y el contenido de la entrada a la que se hace referencia debe cumplir con la especificación MemberName .
G19 Para cada method_id_item , el campo class_idx debe ser un índice válido en la sección type_ids y la entrada a la que se hace referencia debe ser un tipo de referencia que no sea una matriz. El campo proto_id debe ser una referencia válida en la lista proto_ids . El campo name_idx debe ser una referencia válida a la sección string_ids y el contenido de la entrada a la que se hace referencia debe cumplir con la especificación MemberName .
G20 Para cada field_id_item , el campo class_idx debe ser un índice válido en la lista type_ids . La entrada a la que se hace referencia debe ser un tipo de referencia que no sea una matriz.

Restricciones de código de bytes estático

Las restricciones estáticas son restricciones sobre elementos individuales del código de bytes. Por lo general, se pueden verificar sin emplear técnicas de control o análisis de flujo de datos.

Identificador Descripción
A1 La matriz insns no debe estar vacía.
A2 El primer código de operación en la matriz insns debe tener índice cero.
A3 La matriz insns debe contener sólo códigos de operación Dalvik válidos.
A4 El índice de la instrucción n+1 debe ser igual al índice de la instrucción n más la longitud de la instrucción n , teniendo en cuenta los posibles operandos.
A5 La última instrucción de la matriz insns debe terminar en el índice insns_size-1 .
A6 Todos los objetivos goto e if-<kind> deben ser códigos de operación dentro del mismo método.
A7 Todos los objetivos de una instrucción packed-switch deben ser códigos de operación dentro del mismo método. El tamaño y la lista de objetivos deben ser coherentes.
A8 Todos los objetivos de una instrucción sparse-switch deben ser códigos de operación dentro del mismo método. La tabla correspondiente debe ser coherente y estar ordenada de menor a mayor.
A9 El operando B de las instrucciones const-string y const-string/jumbo debe ser un índice válido en el grupo de constantes de cadena.
A10 El operando C de las instrucciones iget<kind> e iput<kind> debe ser un índice válido en el grupo de constantes de campo. La entrada a la que se hace referencia debe representar un campo de instancia.
A11 El operando C de las instrucciones sget<kind> y sput<kind> debe ser un índice válido en el grupo de constantes de campo. La entrada a la que se hace referencia debe representar un campo estático.
A12 El operando C de las instrucciones invoke-virtual , invoke-super , invoke-direct e invoke-static debe ser un índice válido en el grupo de constantes del método.
A13 El operando B de las instrucciones invoke-virtual/range , invoke-super/range , invoke-direct/range e invoke-static/range debe ser un índice válido en el grupo de constantes del método.
A14 Un método cuyo nombre comienza con '<' solo debe ser invocado implícitamente por la VM, no por el código que se origina en un archivo .dex . La única excepción es el inicializador de instancia, que puede ser invocado mediante invoke-direct .
A15 El operando C de la instrucción invoke-interface debe ser un índice válido en el grupo constante del método. El method_id al que se hace referencia debe pertenecer a una interfaz (no a una clase).
A16 El operando B de la instrucción invoke-interface/range debe ser un índice válido en el grupo constante del método. El method_id al que se hace referencia debe pertenecer a una interfaz (no a una clase).
A17 El operando B de las const-class , check-cast , new-instance y filled-new-array/range debe ser un índice válido en el grupo de constantes de tipo.
A18 El operando C de las instrucciones instance-of , new-array y filled-new-array debe ser un índice válido en el grupo de constantes de tipo.
A19 Las dimensiones de una matriz creada mediante una instrucción new-array deben ser inferiores a 256 .
A20 La new instrucción no debe hacer referencia a clases de matriz, interfaces o clases abstractas.
A21 El tipo al que hace referencia una instrucción new-array debe ser un tipo válido y sin referencia.
A22 Todos los registros a los que hace referencia una instrucción de ancho único (sin par) deben ser válidos para el método actual. Es decir, sus índices deben ser no negativos y más pequeños que registers_size .
A23 Todos los registros a los que hace referencia una instrucción en forma de doble ancho (par) deben ser válidos para el método actual. Es decir, sus índices deben ser no negativos y más pequeños que registers_size-1 .
A24 El operando method_id de las instrucciones invoke-virtual e invoke-direct debe pertenecer a una clase (no a una interfaz). En los archivos Dex anteriores a la versión 037 lo mismo debe ocurrir con las instrucciones invoke-super e invoke-static .
A25 El operando method_id de las instrucciones invoke-virtual/range e invoke-direct/range debe pertenecer a una clase (no a una interfaz). En los archivos Dex anteriores a la versión 037 , lo mismo debe ocurrir con las instrucciones invoke-super/range e invoke-static/range .

Restricciones estructurales de código de bytes

Las restricciones estructurales son restricciones a las relaciones entre varios elementos del código de bytes. Por lo general, no se pueden verificar sin emplear técnicas de control o análisis de flujo de datos.

Identificador Descripción
B1 El número y tipos de argumentos (registros y valores inmediatos) siempre deben coincidir con la instrucción.
B2 Los pares de registros nunca deben dividirse.
B3 Primero se debe asignar un registro (o par) antes de poder leerlo.
B4 Una instrucción invoke-direct debe invocar un inicializador de instancia o un método sólo en la clase actual o en una de sus superclases.
B5 Un inicializador de instancia debe invocarse solo en una instancia no inicializada.
B6 Los métodos de instancia solo se pueden invocar y solo se puede acceder a los campos de instancia en instancias ya inicializadas.
B7 No se debe utilizar un registro que contenga el resultado de una instrucción new-instance si la misma instrucción new-instance se ejecuta nuevamente antes de que se inicialice la instancia.
B8 Un inicializador de instancia debe llamar a otro inicializador de instancia (misma clase o superclase) antes de que se pueda acceder a cualquier miembro de la instancia. Las excepciones son los campos de instancia no heredados, que se pueden asignar antes de llamar a otro inicializador, y la clase Object en general.
B9 Todos los argumentos del método real deben ser compatibles con la asignación de sus respectivos argumentos formales.
B10 Para cada invocación de método de instancia, la instancia real debe ser compatible con la asignación con la clase o interfaz especificada en la instrucción.
B11 Una instrucción return<kind> debe coincidir con el tipo de retorno de su método.
B12 Al acceder a miembros protegidos de una superclase, el tipo real de instancia a la que se accede debe ser la clase actual o una de sus subclases.
B13 El tipo de valor almacenado en un campo estático debe ser compatible con la asignación o convertible al tipo de campo.
B14 El tipo de valor almacenado en un campo debe ser compatible con la asignación o convertible al tipo de campo.
B15 El tipo de cada valor almacenado en una matriz debe ser compatible con la asignación con el tipo de componente de la matriz.
B16 El operando A de una instrucción throw debe ser compatible con la asignación con java.lang.Throwable .
B17 La última instrucción accesible de un método debe ser una instrucción goto atrás o una rama, una return o una instrucción throw . No debe ser posible dejar la matriz insns en la parte inferior.
B18 La mitad no asignada de un par de registros anterior no se puede leer (se considera inválida) hasta que haya sido reasignada mediante alguna otra instrucción.
B19 Una instrucción move-result<kind> debe ir precedida inmediatamente (en la matriz insns ) por una instrucción invoke-<kind> . La única excepción es la instrucción move-result-object , que también puede ir precedida por una instrucción filled-new-array .
B20 Una instrucción move-result<kind> debe ir inmediatamente precedida (en el flujo de control real) por una instrucción return-<kind> coincidente (no se debe saltar a ella). La única excepción es la instrucción move-result-object , que también puede ir precedida por una instrucción filled-new-array .
B21 Una instrucción move-exception debe aparecer sólo como la primera instrucción en un controlador de excepciones.
B22 Las pseudoinstrucciones packed-switch-data , sparse-switch-data y fill-array-data no deben ser accesibles mediante el flujo de control.