Restrições

Um arquivo .dex é o formato de transporte do bytecode Dalvik. Existem certas restrições sintáticas e semânticas para que um arquivo seja um arquivo .dex válido, e um tempo de execução é necessário para oferecer suporte apenas a arquivos .dex válidos.

Restrições gerais de integridade .dex

As restrições gerais de integridade dizem respeito à estrutura maior de um arquivo .dex , conforme descrito detalhadamente em Formato .dex .

Identificador Descrição
G1 O número magic do arquivo .dex deve ser dex\n035\0 ou dex\n037\0 .
G2 A soma de verificação deve ser uma soma de verificação Adler-32 de todo o conteúdo do arquivo, exceto o campo magic e checksum .
G3 A assinatura deve ser um hash SHA-1 de todo o conteúdo do arquivo, exceto magic , checksum e signature .
G4 O file_size deve corresponder ao tamanho real do arquivo em bytes.
G5 O header_size deve ter o valor: 0x70
G6 A endian_tag deve ter o valor: ENDIAN_CONSTANT ou REVERSE_ENDIAN_CONSTANT
G7 Para cada uma das seções link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs e data , os campos offset e size devem ser zero ou diferentes de zero. Neste último caso, o deslocamento deve ser alinhado com quatro bytes.
G8 Todos os campos de deslocamento no cabeçalho, exceto map_off devem ser alinhados com quatro bytes.
G9 O campo map_off deve ser zero ou apontar para a seção de dados. Neste último caso, a seção data deve existir.
G10 Nenhuma das link , string_ids , type_ids , proto_ids , field_ids , method_ids , class_defs e data deve se sobrepor ou ao cabeçalho.
G11 Se existir um mapa, cada entrada do mapa deverá ter um tipo válido. Cada tipo pode aparecer no máximo uma vez.
G12 Se existir um mapa, cada entrada do mapa deverá ter um deslocamento e tamanho diferente de zero. O deslocamento deve apontar para a seção correspondente do arquivo (ou seja, um string_id_item deve apontar para a seção string_ids ) e o tamanho explícito ou implícito do item deve corresponder ao conteúdo e tamanho reais da seção.
G13 Se existir um mapa, o deslocamento da entrada do mapa n+1 deverá ser maior ou igual ao deslocamento da entrada do mapa n plus than size of map entry n . Isso implica entradas não sobrepostas e ordenação de baixo para cima.
G14 Os seguintes tipos de entradas devem ter um deslocamento alinhado a quatro 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 , o campo string_data_off deve conter uma referência válida na seção data . Para o string_data_item referenciado, o campo data deve conter uma string MUTF-8 válida e utf16_size deve corresponder ao comprimento decodificado da string.
G16 Para cada type_id_item , o campo descriptor_idx deve conter uma referência válida na lista string_ids . A string referenciada deve ser um descritor de tipo válido.
G17 Para cada proto_id_item , o campo shorty_idx deve conter uma referência válida na lista string_ids . A string referenciada deve ser um descritor shorty válido. Além disso, o campo return_type_idx deve ser um índice válido na seção type_ids e o campo parameters_off deve ser zero ou um deslocamento válido apontando para a seção data . Se for diferente de zero, a lista de parâmetros não deverá conter nenhuma entrada nula.
G18 Para cada field_id_item , os campos class_idx e type_idx devem ser índices válidos na lista type_ids . A entrada referenciada por class_idx deve ser um tipo de referência que não seja de array. Além disso, o campo name_idx deve ser uma referência válida na seção string_ids e o conteúdo da entrada referenciada deve estar em conformidade com a especificação MemberName .
G19 Para cada method_id_item , o campo class_idx deve ser um índice válido na seção type_ids e a entrada referenciada deve ser um tipo de referência não array. O campo proto_id deve ser uma referência válida na lista proto_ids . O campo name_idx deve ser uma referência válida na seção string_ids e o conteúdo da entrada referenciada deve estar em conformidade com a especificação MemberName .
G20 Para cada field_id_item , o campo class_idx deve ser um índice válido na lista type_ids . A entrada referenciada deve ser um tipo de referência que não seja de matriz.

Restrições de bytecode estáticas

Restrições estáticas são restrições em elementos individuais do bytecode. Eles geralmente podem ser verificados sem o uso de técnicas de controle ou análise de fluxo de dados.

Identificador Descrição
A1 A matriz insns não deve estar vazia.
A2 O primeiro opcode no array insns deve ter índice zero.
A3 A matriz insns deve conter apenas opcodes Dalvik válidos.
A4 O índice da instrução n+1 deve ser igual ao índice da instrução n mais o comprimento da instrução n , levando em consideração os possíveis operandos.
A5 A última instrução no array insns deve terminar no índice insns_size-1 .
A6 Todos os destinos goto e if-<kind> devem ser opcodes dentro do mesmo método.
A7 Todos os destinos de uma instrução packed-switch devem ser opcodes dentro do mesmo método. O tamanho e a lista de alvos devem ser consistentes.
A8 Todos os alvos de uma instrução sparse-switch devem ser opcodes dentro do mesmo método. A tabela correspondente deve ser consistente e classificada de baixo para cima.
A9 O operando B das instruções const-string e const-string/jumbo deve ser um índice válido no conjunto de constantes de string.
A10 O operando C das instruções iget<kind> e iput<kind> deve ser um índice válido no conjunto de constantes de campo. A entrada referenciada deve representar um campo de instância.
A11 O operando C das instruções sget<kind> e sput<kind> deve ser um índice válido no conjunto de constantes de campo. A entrada referenciada deve representar um campo estático.
A12 O operando C das instruções invoke-virtual , invoke-super , invoke-direct e invoke-static deve ser um índice válido no conjunto de constantes do método.
A13 O operando B das instruções invoke-virtual/range , invoke-super/range , invoke-direct/range e invoke-static/range deve ser um índice válido no conjunto de constantes do método.
A14 Um método cujo nome começa com '<' só deve ser invocado implicitamente pela VM, e não por código originado de um arquivo .dex . A única exceção é o inicializador de instância, que pode ser invocado por invoke-direct .
A15 O operando C da instrução invoke-interface deve ser um índice válido no conjunto de constantes do método. O method_id referenciado deve pertencer a uma interface (não a uma classe).
A16 O operando B da instrução invoke-interface/range deve ser um índice válido no conjunto de constantes do método. O method_id referenciado deve pertencer a uma interface (não a uma classe).
A17 O operando B das const-class , check-cast , new-instance e filled-new-array/range deve ser um índice válido no conjunto de constantes de tipo.
A18 O operando C das instruções instance-of , new-array e filled-new-array deve ser um índice válido no conjunto de constantes de tipo.
A19 As dimensões de um array criado por uma instrução new-array devem ser menores que 256 .
A20 A new instrução não deve referir-se a classes de array, interfaces ou classes abstratas.
A21 O tipo referido por uma instrução new-array deve ser um tipo válido e sem referência.
A22 Todos os registradores referidos por uma instrução de forma de largura única (sem par) devem ser válidos para o método atual. Ou seja, seus índices devem ser não negativos e menores que registers_size .
A23 Todos os registradores referidos por uma instrução em formato de largura dupla (par) devem ser válidos para o método atual. Ou seja, seus índices devem ser não negativos e menores que registers_size-1 .
A24 O operando method_id das instruções invoke-virtual e invoke-direct deve pertencer a uma classe (não a uma interface). Em arquivos Dex anteriores à versão 037 , o mesmo deve ser verdadeiro para as instruções invoke-super e invoke-static .
A25 O operando method_id das instruções invoke-virtual/range e invoke-direct/range deve pertencer a uma classe (não a uma interface). Em arquivos Dex anteriores à versão 037 , o mesmo deve ser verdadeiro para as instruções invoke-super/range e invoke-static/range .

Restrições estruturais de bytecode

Restrições estruturais são restrições nos relacionamentos entre vários elementos do bytecode. Eles geralmente não podem ser verificados sem o emprego de técnicas de controle ou de análise de fluxo de dados.

Identificador Descrição
B1 O número e os tipos de argumentos (registros e valores imediatos) devem sempre corresponder à instrução.
B2 Os pares de registros nunca devem ser divididos.
B3 Um registro (ou par) deve ser atribuído primeiro antes de poder ser lido.
B4 Uma instrução invoke-direct deve invocar um inicializador de instância ou um método apenas na classe atual ou em uma de suas superclasses.
B5 Um inicializador de instância deve ser invocado somente em uma instância não inicializada.
B6 Os métodos de instância podem ser invocados apenas e os campos de instância só podem ser acessados ​​em instâncias já inicializadas.
B7 Um registrador que contém o resultado de uma instrução new-instance não deve ser usado se a mesma instrução new-instance for executada novamente antes da inicialização da instância.
B8 Um inicializador de instância deve chamar outro inicializador de instância (mesma classe ou superclasse) antes que qualquer membro da instância possa ser acessado. As exceções são campos de instância não herdados, que podem ser atribuídos antes de chamar outro inicializador, e a classe Object em geral.
B9 Todos os argumentos reais do método devem ser compatíveis com a atribuição com seus respectivos argumentos formais.
B10 Para cada invocação de método de instância, a instância real deve ser compatível com a atribuição com a classe ou interface especificada na instrução.
B11 Uma instrução return<kind> deve corresponder ao tipo de retorno do seu método.
B12 Ao acessar membros protegidos de uma superclasse, o tipo real da instância acessada deve ser a classe atual ou uma de suas subclasses.
B13 O tipo de valor armazenado em um campo estático deve ser compatível com a atribuição ou conversível no tipo do campo.
B14 O tipo de valor armazenado em um campo deve ser compatível com a atribuição ou conversível no tipo do campo.
B15 O tipo de cada valor armazenado em um array deve ser compatível com a atribuição ao tipo de componente do array.
B16 O operando A de uma instrução throw deve ser compatível com a atribuição java.lang.Throwable .
B17 A última instrução alcançável de um método deve ser um goto ou branch reverso, um return ou uma instrução throw . Não deve ser possível deixar o array insns na parte inferior.
B18 A metade não atribuída de um par de registradores anterior não pode ser lida (é considerada inválida) até que seja reatribuída por alguma outra instrução.
B19 Uma instrução move-result<kind> deve ser imediatamente precedida (no array insns ) por uma instrução invoke-<kind> . A única exceção é a instrução move-result-object , que também pode ser precedida por uma instrução filled-new-array .
B20 Uma instrução move-result<kind> deve ser imediatamente precedida (no fluxo de controle real) por uma instrução return-<kind> correspondente (não deve ser saltada para ela). A única exceção é a instrução move-result-object , que também pode ser precedida por uma instrução filled-new-array .
B21 Uma instrução de move-exception deve aparecer apenas como a primeira instrução em um manipulador de exceção.
B22 As pseudo-instruções packed-switch-data , sparse-switch-data e fill-array-data não devem ser acessíveis pelo fluxo de controle.