Restrições

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

Restrições gerais de integridade de .dex

As restrições de integridade geral 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 precisa ser dex\n035\0 para a versão 35 ou semelhante para versões mais recentes.
G2 A soma de verificação precisa ser uma soma de verificação Adler-32 de todo o conteúdo do arquivo, exceto os campos magic e checksum.
G3 A assinatura precisa ser um hash SHA-1 de todo o conteúdo do arquivo, exceto magic, checksum e signature.
G4

O file_size precisa corresponder ao tamanho real do arquivo em bytes. (v40 ou anterior)

O file_size precisa apontar para o próximo cabeçalho no contêiner ou no final do arquivo físico (o contêiner). Se ele apontar para o próximo cabeçalho, o tamanho do arquivo precisará ser alinhado a 4 bytes. A soma de todos os campos file_size precisa ser igual a container_size. (v41 ou mais recente)

G5

O header_size precisa ter o valor: 0x70 (v40 ou anterior)

O header_size precisa ter o valor: 0x78 (v41 ou mais recente)

G6 O endian_tag precisa 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 precisam ser zero ou não zero. Nesse último caso, o deslocamento precisa ser alinhado a quatro bytes.

Os campos offset e size precisam estar dentro do contêiner e se referir a dados localizados após o cabeçalho que os define. (v41 ou mais recente)

G8 Todos os campos de deslocamento no cabeçalho, exceto map_off, precisam estar alinhados a quatro bytes.
G9 O campo map_off precisa ser zero ou apontar para a seção de dados. No segundo caso, a seção data precisa existir.
G10 Nenhuma das seções link, string_ids, type_ids, proto_ids, field_ids, method_ids, class_defs e data pode se sobrepor ou se sobrepor ao cabeçalho.
G11 Se um mapa existir, cada entrada de mapa precisa ter um tipo válido. Cada tipo pode aparecer no máximo uma vez.
G12 Se um mapa existir, cada entrada de mapa precisa ter um deslocamento e tamanho diferentes de zero. O deslocamento precisa apontar para a seção correspondente do arquivo (ou seja, um string_id_item precisa apontar para a seção string_ids) e o tamanho explícito ou implícito do item precisa corresponder ao conteúdo e ao tamanho reais da seção.
G13 Se um mapa existir, o deslocamento da entrada do mapa n+1 precisará ser maior ou igual ao deslocamento da entrada do mapa n plus than size of map entry n. Isso implica entradas que não se sobrepõem e ordenação de baixo para alto.
G14 Os seguintes tipos de entradas precisam 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 precisa conter uma referência válida na seção data. (v40 ou anterior)

Para cada string_id_item, o campo string_data_off precisa ser um deslocamento dentro do contêiner e depois de qualquer cabeçalho que o use. (v41 ou mais recente)

Para a string_data_item referenciada, o campo data precisa conter uma string MUTF-8 válida, e o utf16_size precisa corresponder ao comprimento decodificado da string.

G16 Para cada type_id_item, o campo descriptor_idx precisa conter uma referência válida na lista string_ids. A string referenciada precisa ser um descritor de tipo válido.
G17 Para cada proto_id_item, o campo shorty_idx precisa conter uma referência válida na lista string_ids. A string referenciada precisa ser um descritor shorty válido. Além disso, o campo return_type_idx precisa ser um índice válido na seção type_ids, e o campo parameters_off precisa ser zero ou um deslocamento válido que aponte para a seção data. Se não for igual a zero, a lista de parâmetros não poderá conter entradas nulas.
G18 Para cada field_id_item, os campos class_idx e type_idx precisam ser índices válidos na lista type_ids. A entrada referenciada por class_idx precisa ser um tipo de referência que não seja de matriz. Além disso, o campo name_idx precisa ser uma referência válida na seção string_ids, e o conteúdo da entrada referenciada precisa estar em conformidade com a especificação MemberName.
G19 Para cada method_id_item, o campo class_idx precisa ser um índice válido na seção type_ids, e a entrada referenciada precisa ser um tipo de referência que não seja uma matriz. O campo proto_id precisa ser uma referência válida na lista proto_ids. O campo name_idx precisa ser uma referência válida na seção string_ids, e o conteúdo da entrada referenciada precisa estar em conformidade com a especificação MemberName.
G20 Para cada field_id_item, o campo class_idx precisa ser um índice válido na lista type_ids. A entrada referenciada precisa ser um tipo de referência que não seja de matriz.

Restrições de bytecode estáticas

As restrições estáticas são restrições em elementos individuais do bytecode. Geralmente, elas podem ser verificadas sem usar técnicas de controle ou de análise de fluxo de dados.

Identificador Descrição
A1 A matriz insns não pode estar vazia.
A2 O primeiro opcode na matriz insns precisa ter o índice zero.
A3 A matriz insns precisa conter apenas opcodes Dalvik válidos.
A4 O índice da instrução n+1 precisa ser igual ao índice da instrução n mais a duração da instrução n, considerando possíveis operandos.
A5 A última instrução na matriz insns precisa terminar no índice insns_size-1.
A6 Todas as metas goto e if-<kind> precisam ser opcodes no mesmo método.
A7 Todos os destinos de uma instrução packed-switch precisam ser opcodes no mesmo método. O tamanho e a lista de destinos precisam ser consistentes.
A8 Todos os destinos de uma instrução sparse-switch precisam ser opcodes no mesmo método. A tabela correspondente precisa ser consistente e classificada de menor para maior.
A9 O operando B das instruções const-string e const-string/jumbo precisa ser um índice válido no pool de constantes de string.
A10 O operando C das instruções iget<kind> e iput<kind> precisa ser um índice válido no pool de constantes de campo. A entrada referenciada precisa representar um campo de instância.
A11 O operando C das instruções sget<kind> e sput<kind> precisa ser um índice válido no pool de constantes de campo. A entrada referenciada precisa representar um campo estático.
A12 O operando C das instruções invoke-virtual, invoke-super, invoke-direct e invoke-static precisa ser um índice válido no pool de constantes de método.
A13 O operando B das instruções invoke-virtual/range, invoke-super/range, invoke-direct/range e invoke-static/range precisa ser um índice válido no pool de constantes do método.
A14 Um método com nome que começa com '<' só pode ser invocado implicitamente pela VM, 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 precisa ser um índice válido no pool de constantes do método. O method_id referenciado precisa pertencer a uma interface (não a uma classe).
A16 O operando B da instrução invoke-interface/range precisa ser um índice válido no pool de constantes do método. O method_id referenciado precisa 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 precisa 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 precisa ser um índice válido no pool de constantes do tipo.
A19 As dimensões de uma matriz criada por uma instrução new-array precisam ser menores que 256.
A20 A instrução new não pode se referir a classes de matriz, interfaces ou classes abstratas.
A21 O tipo mencionado por uma instrução new-array precisa ser um tipo válido sem referência.
A22 Todos os registros mencionados por uma instrução de largura única (não em par) precisam ser válidos para o método atual. Ou seja, os índices precisam ser não negativos e menores que registers_size.
A23 Todos os registros mencionados por uma instrução em um formato de largura dupla (par) precisam ser válidos para o método atual. Ou seja, os índices precisam ser não negativos e menores que registers_size-1.
A24 O operando method_id das instruções invoke-virtual e invoke-direct precisa pertencer a uma classe (não a uma interface). Em arquivos Dex anteriores à versão 037, o mesmo precisa 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 precisa pertencer a uma classe (não a uma interface). Em arquivos Dex anteriores à versão 037, o mesmo precisa ser verdadeiro para as instruções invoke-super/range e invoke-static/range.

Restrições de bytecode estrutural

As restrições estruturais são restrições sobre as relações entre vários elementos do bytecode. Geralmente, eles não podem ser verificados sem o uso de técnicas de controle ou análise de fluxo de dados.

Identificador Descrição
B1 O número e os tipos de argumentos (registradores e valores imediatos) precisam sempre corresponder à instrução.
B2 Os pares de registro nunca podem ser divididos.
B3 Um registro (ou par) precisa ser atribuído primeiro para poder ser lido.
B4 Uma instrução invoke-direct precisa invocar um inicializador de instância ou um método apenas na classe atual ou em uma das superclasses.
B5 Um inicializador de instância precisa 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 registro que contém o resultado de uma instrução new-instance não pode 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 precisa chamar outro inicializador de instância (mesma classe ou superclasse) antes que os membros de instância possam ser acessados. 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étodo reais precisam ser compatíveis com a atribuição dos respectivos argumentos formais.
B10 Para cada invocação de método de instância, a instância real precisa ser compatível com a atribuição da classe ou interface especificada na instrução.
B11 Uma instrução return<kind> precisa corresponder ao tipo de retorno do método.
B12 Ao acessar membros protegidos de uma superclasse, o tipo real da instância que está sendo acessada precisa ser a classe atual ou uma das subclasses.
B13 O tipo de um valor armazenado em um campo estático precisa ser compatível com a atribuição ou convertível para o tipo do campo.
B14 O tipo de um valor armazenado em um campo precisa ser compatível com a atribuição ou ser convertível para o tipo do campo.
B15 O tipo de cada valor armazenado em uma matriz precisa ser compatível com a atribuição do tipo de componente da matriz.
B16 O operando A de uma instrução throw precisa ser compatível com a atribuição de java.lang.Throwable.
B17 A última instrução alcançável de um método precisa ser uma goto reversiva ou de ramificação, uma return ou uma instrução throw. Não é possível deixar a matriz insns na parte de baixo.
B18 A metade não atribuída de um antigo par de registros não pode ser lida (é considerada inválida) até que seja reatribuída por outra instrução.
B19 Uma instrução move-result<kind> precisa ser imediatamente precedida (na matriz 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> precisa ser imediatamente precedida (no fluxo de controle real) por uma instrução return-<kind> correspondente (ela não pode ser pulada). 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 precisa aparecer apenas como a primeira instrução em um gerenciador de exceções.
B22 As pseudoinstruções packed-switch-data, sparse-switch-data e fill-array-data não podem ser alcançadas pelo fluxo de controle.