Skip to content

[Bug] gh59: VerifyError em apks instrumentados — wide-slot tracking em PointcutMatcher.buildCallMatch (regressão pós-gh56) #59

@phtcosta

Description

@phtcosta

Summary

Re-instrumentação do dataset de 190 APKs JCA com a imagem phtcosta/rvandroid:0.9.0 (gh56/gh57/gh58 aplicados) produz 5 APKs com java.lang.VerifyError em runtime. Causa: bug de off-by-N no binding de argumentos do callee quando o construtor casado tem parâmetros long / double (wide, 2 slots) entremeados com refs.

O trabalho de gh56 (binding-correctness, commit 3d51b410, refs #56) corrigiu offset de receiver e semântica de <init> mas não tratou contagem de slots widos no cursor de registradores de argumentos.

Reprodução

  1. Instrumentar experimento-20260508/filters/experiment_apks.txt a partir dos originais em JOAO/APKs/ via docker/docker-compose.instrument-jca190.yml (imagem 0.9.0, dexlib2, JCA, skip-static/skip-execution).
  2. Rodar scripts/validate_instrument_jca190.py contra emulador API 30 x86_64.
  3. Observar 5 / 190 com FAIL_VERIFY — verifier rejeita <init> por registrador não-referência (Long Low Half ou Boolean) tratado como referência.

APKs afetados (FAIL_VERIFY)

APK Classe Forma do construtor
com.github.soundpod_16.apk yu5 25 params, 6× long intercalados; rejeita v7 (Long Low Half)
com.grappim.taigamobile.fdroid_38.apk ga.e 19 params, boolean/refs mistos; rejeita v3 (Boolean)
com.shub39.rush_5730.apk
gizz.tapes.foss_63.apk
org.fossify.musicplayer_14.apk

Logcats de crash preservados em out/validate_instrument_jca190/logs/<apk>.logcat.

Mensagem do verifier (amostra)

java.lang.VerifyError: Verifier rejected class yu5: void yu5.<init>(java.lang.String, mu5, java.lang.String, java.lang.String, cs0, cs0, long, long, long, ok0, int, xr, long, long, long, long, boolean, gl3, int, int, long, int, int, java.lang.String, java.lang.Boolean) failed to verify: [0xF] tried to get class from non-reference register v7 (type=Long (Low Half))

Causa raiz

PointcutMatcher.buildCallMatch (~linha 222) em rvsec-instrumentation-dexlib2/pointcut-engine/src/main/java/br/unb/cic/rv/pointcut/PointcutMatcher.java itera os paramTypes do callee e mapeia cada um para regs[baseOffset + i] — avançando o cursor de regs em exatamente 1 por parâmetro. DEX representa long e double com 2 slots contíguos, então para callees cuja lista de params contenha um wide antes do param sendo bindado, todo argBinding subsequente resolve para o registrador errado (high half do wide, ou primitivo a jusante).

O próprio arquivo já documenta a contiguidade de wide-pair (linha 244, contexto de $return/move-result-wide) mas nunca aplica a regra ao argBindings.

Fix proposto

Substituir o mapeamento por índice por um cursor de registrador que avança 2 para J/D e 1 caso contrário:

int regOffset = baseOffset;
for (int i = 0; i < paramTypes.size(); i++) {
    String paramType = paramTypes.get(i);
    int reg = regs[regOffset];
    // bind argument i to register `reg`
    regOffset += (paramType.equals("J") || paramType.equals("D")) ? 2 : 1;
}

Lacuna de teste

PointcutMatcherConstructorTest.java e DexWeaverConstructorAdviceTest.java só cobrem [B e String. Nenhum teste do INV-INS-70..73 cobre construtor com long/double interleaved com refs. A remediação deve adicionar fixture espelhando a forma de 25 params do yu5 antes do fix.

Track

Quick Path (fix mecânico single-file; sem decisões de design; bug-fix com teste de regressão).

Critérios de aceitação

  1. Nova fixture em PointcutMatcherConstructorTest com pelo menos um long e um boolean intercalados com refs no callee — falha antes do fix, passa depois.
  2. Re-instrumentar os 190 APKs com o fix produz zero FAIL_VERIFY em validate_instrument_jca190.py.
  3. Contagens de FAIL_FATAL (categoria R8/Compose) e FAIL_INSTALL não mudam (fora do escopo de gh59).

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions