Skip to content

[Unsolvable] Constructor call: Combined pattern - zzqz (Type C) #2766

@devload

Description

@devload

Summary

This case combines multiple problematic patterns: string concatenation + API level check + instanceof check + conditional assignment, all before this(). It represents the most complex category of constructor call issues.


Problem Description

Decompiled Java (Invalid!)

/* JADX WARN: Illegal instructions before constructor call */
public zzqz(zzaf zzafVar, Throwable th, boolean z, zzqx zzqxVar) {
    // ═══════════════════════════════════════════════════
    // PATTERN 1: String concatenation before this()
    // ═══════════════════════════════════════════════════
    String str = "Decoder init failed: " + zzqxVar.zza + ", " + String.valueOf(zzafVar);
    
    String codecName = zzafVar.zzm;
    String diagnosticInfo = null;
    
    // ═══════════════════════════════════════════════════
    // PATTERN 2: API level check (SDK_INT >= 21)
    // ═══════════════════════════════════════════════════
    // ═══════════════════════════════════════════════════
    // PATTERN 3: instanceof check
    // ═══════════════════════════════════════════════════
    if (zzew.zza >= 21 && (th instanceof MediaCodec.CodecException)) {
        // ═══════════════════════════════════════════════════
        // PATTERN 4: Conditional assignment
        // ═══════════════════════════════════════════════════
        diagnosticInfo = ((MediaCodec.CodecException) th).getDiagnosticInfo();
    }
    
    this(str, th, codecName, false, zzqxVar, diagnosticInfo, null);  // ❌ this() after all patterns
}

Original Kotlin (Inferred)

class DecoderException(
    message: String,
    cause: Throwable?,
    codecName: String?,
    isRecoverable: Boolean,
    codecInfo: CodecInfo,
    diagnosticInfo: String?,
    extra: Any?
) : Exception(message, cause) {

    constructor(format: Format, cause: Throwable?, flag: Boolean, codecInfo: CodecInfo) : this(
        message = "Decoder init failed: ${codecInfo.name}, $format",
        cause = cause,
        codecName = format.codecName,
        isRecoverable = false,
        codecInfo = codecInfo,
        diagnosticInfo = if (Build.VERSION.SDK_INT >= 21 && cause is MediaCodec.CodecException) {
            cause.diagnosticInfo  // Kotlin smart cast
        } else null,
        extra = null
    )
}

DEX Bytecode Analysis

.method public constructor <init>(Lzzaf;Ljava/lang/Throwable;ZLzzqx;)V
    .registers 11

    # ═══════════════════════════════════════════════════
    # STAGE 1: Build error message string
    # ═══════════════════════════════════════════════════
    new-instance v0, Ljava/lang/StringBuilder;
    invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V
    
    const-string v1, "Decoder init failed: "
    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
    # Append zzqxVar.zza
    iget-object v1, p4, Lzzqx;->zza:Ljava/lang/String;
    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
    const-string v1, ", "
    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
    # Append String.valueOf(zzafVar)
    invoke-static {p1}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;
    move-result-object v1
    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
    move-result-object v0    # v0 = error message
    
    # ═══════════════════════════════════════════════════
    # STAGE 2: Get codec name
    # ═══════════════════════════════════════════════════
    iget-object v1, p1, Lzzaf;->zzm:Ljava/lang/String;    # v1 = codecName
    
    # ═══════════════════════════════════════════════════
    # STAGE 3: API level check (SDK_INT >= 21)
    # ═══════════════════════════════════════════════════
    const/4 v2, 0x0    # v2 = diagnosticInfo = null (default)
    
    sget v3, Lzzew;->zza:I    # v3 = SDK version wrapper
    const/16 v4, 0x15         # v4 = 21 (LOLLIPOP)
    if-lt v3, v4, :skip_diagnostic
    
    # ═══════════════════════════════════════════════════
    # STAGE 4: instanceof check
    # ═══════════════════════════════════════════════════
    instance-of v3, p2, Landroid/media/MediaCodec$CodecException;
    if-eqz v3, :skip_diagnostic
    
    # ═══════════════════════════════════════════════════
    # STAGE 5: Get diagnostic info (API 21+)
    # ═══════════════════════════════════════════════════
    check-cast p2, Landroid/media/MediaCodec$CodecException;
    invoke-virtual {p2}, Landroid/media/MediaCodec$CodecException;->getDiagnosticInfo()Ljava/lang/String;
    move-result-object v2    # v2 = diagnosticInfo
    
    :skip_diagnostic
    # ═══════════════════════════════════════════════════
    # STAGE 6: Call this() with all computed values
    # ═══════════════════════════════════════════════════
    const/4 v3, 0x0    # false
    const/4 v4, 0x0    # null
    invoke-direct/range {p0 .. p0}, Lzzqz;-><init>(Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/String;ZLzzqx;Ljava/lang/String;Ljava/lang/Object;)V
    return-void
.end method

Control Flow Graph

                        ┌─────────────────────────┐
                        │    Entry: zzqz()        │
                        │ p1=zzafVar, p2=th,      │
                        │ p3=z, p4=zzqxVar        │
                        └───────────┬─────────────┘
                                    │
                        ┌───────────▼─────────────┐
                        │ PATTERN 1: StringBuilder │
                        │ v0 = "Decoder init      │
                        │       failed: " +       │
                        │       zzqxVar.zza +     │
                        │       ", " + zzafVar    │
                        └───────────┬─────────────┘
                                    │
                        ┌───────────▼─────────────┐
                        │ v1 = zzafVar.zzm        │
                        │ v2 = null (default)     │
                        └───────────┬─────────────┘
                                    │
                        ┌───────────▼─────────────┐
                        │ PATTERN 2: API check    │
                        │ zzew.zza >= 21?         │
                        └───────────┬─────────────┘
                                   / \
                                 no   yes
                                 /       \
                                /         \
                   ┌───────────▼┐     ┌───▼─────────────────┐
                   │ Keep v2    │     │ PATTERN 3: instanceof│
                   │ as null    │     │ th instanceof       │
                   │            │     │ CodecException?     │
                   └─────┬──────┘     └───────────┬─────────┘
                         │                       / \
                         │                     no   yes
                         │                     /       \
                         │      ┌─────────────▼┐   ┌───▼────────────────┐
                         │      │ Keep v2      │   │ PATTERN 4:         │
                         │      │ as null      │   │ v2 = th.getDiag-   │
                         │      │              │   │     nosticInfo()   │
                         │      └──────┬───────┘   └──────────┬─────────┘
                         │             │                      │
                         └──────┬──────┴──────────────────────┘
                                │
                     ┌──────────▼──────────────┐
                     │ this(v0, th, v1, false, │
                     │      p4, v2, null)      │ ← AFTER all patterns
                     └──────────┬──────────────┘
                                │
                     ┌──────────▼──────────────┐
                     │        return           │
                     └─────────────────────────┘

Why This is Unsolvable

Multiple Constraint Violations

Pattern Java Constraint Violated
String concatenation Multiple statements before this()
API level check Conditional logic before this()
instanceof check Type check before this()
Conditional assignment Variable assignment before this()

Why Each Pattern is Problematic

Pattern 1: String Concatenation

// Cannot inline StringBuilder operations
this("Decoder init failed: " + zzqxVar.zza + ", " + String.valueOf(zzafVar), ...);
// ✅ This COULD work if it were the ONLY issue

Pattern 2: API Level Check

// Android SDK version check - must be evaluated at runtime
if (Build.VERSION.SDK_INT >= 21) { ... }
// ❌ Cannot be part of this() arguments

Pattern 3: instanceof Check

// Type check required before casting
if (th instanceof MediaCodec.CodecException) { ... }
// ❌ Cannot be inlined into this() call

Pattern 4: Conditional Assignment

// diagnosticInfo depends on patterns 2 & 3
String diagnosticInfo = (condition1 && condition2) 
    ? ((MediaCodec.CodecException) th).getDiagnosticInfo() 
    : null;
// ⚠️ Could be ternary, BUT requires cast inside ternary

Attempted Combined Solution

// Extremely complex ternary - still INVALID due to StringBuilder
this(
    new StringBuilder("Decoder init failed: ")
        .append(zzqxVar.zza)
        .append(", ")
        .append(String.valueOf(zzafVar))
        .toString(),  // ❌ Cannot use new inside this()
    th,
    zzafVar.zzm,
    false,
    zzqxVar,
    (zzew.zza >= 21 && th instanceof MediaCodec.CodecException)
        ? ((MediaCodec.CodecException) th).getDiagnosticInfo()
        : null,
    null
);

Failure reason: new StringBuilder() cannot be used directly in this() arguments because object instantiation is not allowed before constructor delegation.


Affected Files

File Package
zzqz.java com.google.android.gms.internal.ads

Comparison: Kotlin vs Java

Feature Kotlin Java
String templates "$var1, $var2" StringBuilder needed
Smart cast if (x is T) x.method() Explicit cast after instanceof
when expression Returns value if/else doesn't
API level check if (SDK_INT >= 21) Same, but can't use in this()
Combined in constructor ✅ All above work ❌ None work before this()

Why This Case is "Type C"

This case is classified as Type C (Combined) because it requires solving ALL of:

  1. ✅ String concatenation → Could use String.format() or concat()
  2. ❌ API level check → Cannot express as argument
  3. ❌ instanceof + cast → Cannot safely inline
  4. ❌ Conditional value based on 2 & 3 → Depends on unsolvable patterns

Even if JADX solved patterns 1 individually, patterns 2-4 make this fundamentally unsolvable in Java syntax.


Status

Unsolvable - Multiple Java language constraints combined.

Possible Future Solutions

  1. Emit Kotlin source - All patterns work naturally in Kotlin
  2. Factory method + helper - Extract all logic to static methods
  3. Accept pseudo-Java - Mark as invalid with explanatory comment
  4. Two-pass decompilation - First pass identifies patterns, second restructures code

Related Issues

This is the most complex case combining elements from multiple pattern types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions