Restrições

Um arquivo .dex é o formato de transporte para Dalvik Bytecode. 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 dar suporte apenas a arquivos .dex válidos.

Restrições gerais de integridade .dex

As restrições gerais de integridade estão relacionadas à estrutura maior de um arquivo .dex , conforme descrito em detalhes no 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 ambos diferentes de zero. No último caso, o deslocamento deve ser alinhado a quatro bytes.
G8 Todos os campos de deslocamento no cabeçalho, exceto map_off , devem ser alinhados a quatro bytes.
G9 O campo map_off deve ser zero ou apontar para a seção de dados. Neste último caso, a seção de data deve existir.
G10 Nenhuma das seções 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 de mapa deverá ter um tipo válido. Cada tipo pode aparecer no máximo uma vez.
G12 Se existir um mapa, cada entrada de mapa deverá ter um deslocamento e tamanho diferentes 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 real e ao tamanho da seção.
G13 Se existir um mapa, então o deslocamento da entrada do mapa n+1 deve 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 baixa a alta.
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 de data . Para o string_data_item referenciado, o campo de data deve conter uma string MUTF-8 válida e o 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 de data . Se for diferente de zero, a lista de parâmetros não deve conter nenhuma entrada void.
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 não 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 sem matriz.

Restrições de bytecode estático

Restrições estáticas são restrições em elementos individuais do bytecode. Eles geralmente podem ser verificados sem empregar 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 alvos goto e if-<kind> devem ser opcodes dentro do mesmo método.
A7 Todos os alvos de uma instrução packed-switch devem ser opcodes dentro do mesmo método. O tamanho e a lista de destinos 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 alto.
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 iget<kind> e iput<kind> deve ser um índice válido no pool de constantes de campo. A entrada referenciada deve representar um campo de instância.
A11 O operando C das sget<kind> e sput<kind> deve ser um índice válido no pool 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 pool de constante de 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 de método.
A14 Um método cujo nome começa com um '<' deve ser invocado apenas implicitamente pela VM, não pelo 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 de 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 de método. O method_id referenciado deve pertencer a uma interface (não a uma classe).
A17 O operando B das instruções const-class , check-cast , new-instance e filled-new-array/range deve ser um índice válido no pool 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 pool 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 se referir 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 referenciados por uma instrução 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 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). Nos arquivos Dex anteriores à versão 037 , o mesmo deve ser verdade 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). Nos arquivos Dex anteriores à versão 037 , o mesmo deve ser verdade para as instruções invoke-super/range e invoke-static/range .

Restrições estruturais de bytecode

As restrições estruturais são restrições nos relacionamentos entre vários elementos do bytecode. Eles geralmente não podem ser verificados sem empregar técnicas de controle ou 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 Pares de registradores nunca devem ser quebrados.
B3 Um registrador (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 apenas em uma instância não inicializada.
B6 Os métodos de instância só podem ser invocados 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 de new-instance não deve ser usado se a mesma instrução new-instance for executada novamente antes que a instância seja inicializada.
B8 Um inicializador de instância deve chamar outro inicializador de instância (mesma classe ou superclasse) antes que qualquer membro de 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 de métodos reais devem ser compatíveis com atribuição com seus respectivos argumentos formais.
B10 Para cada chamada de método de instância, a instância real deve ser compatível com a atribuição da classe ou interface especificada na instrução.
B11 Uma instrução return<kind> deve corresponder ao tipo de retorno de seu método.
B12 Ao acessar membros protegidos de uma superclasse, o tipo real da instância que está sendo acessada deve ser a classe atual ou uma de suas subclasses.
B13 O tipo de um valor armazenado em um campo estático deve ser compatível com atribuição ou conversível para o tipo do campo.
B14 O tipo de um valor armazenado em um campo deve ser compatível com atribuição ou conversível para o tipo do campo.
B15 O tipo de cada valor armazenado em uma matriz deve ser compatível com a atribuição do tipo de componente da matriz.
B16 O operando A de uma instrução throw deve ser compatível com atribuição com java.lang.Throwable .
B17 A última instrução alcançável de um método deve ser uma instrução goto ou branch para trás, 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 antigo par de registradores 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 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). 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 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 alcançadas pelo fluxo de controle.