Skip to content

[Unsolvable] Constructor call: Variable reuse in ternary operator (Type A - 10 cases) #2761

@devload

Description

@devload

Problem

Same variable is used in both condition and value of ternary operator before constructor call. This prevents safe inlining because the expression would be evaluated twice.


Affected Files (10 cases)

A-1: RecyclerView.java

File: androidx/recyclerview/widget/RecyclerView.java

public RecyclerView(Context context, AttributeSet attributeSet, int i) {
    Context context2 = context;  // MOVE: copy context to context2
    super(context2, attributeSet, i);
    // context2 may be used in subsequent code
}

A-2: DefaultBHttpServerConnection.java

File: cz/msebera/android/httpclient/impl/DefaultBHttpServerConnection.java

public DefaultBHttpServerConnection(..., ContentLengthStrategy contentLengthStrategy, ...) {
    ContentLengthStrategy contentLengthStrategy3 = contentLengthStrategy;

    super(..., contentLengthStrategy3 == null
        ? DisallowIdentityContentLengthStrategy.INSTANCE
        : contentLengthStrategy3, ...);
    //  ^^^^^^^^^^^^^^^^^^^^^^^ condition  ^^^^^^^^^^^^^^^^^^^^^^^ value

    // contentLengthStrategy3 used after super()
    this.requestParser = (httpMessageParserFactory2 == null ? ... : httpMessageParserFactory2).create(...);
}

A-3, A-4, A-5: DefaultDrmSessionManager.java (3 cases)

File: com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java

public DefaultDrmSessionManager(UUID uuid, ExoMediaDrm<T> exoMediaDrm,
        MediaDrmCallback mediaDrmCallback, HashMap<String, String> map) {
    HashMap<String, String> map2 = map;
    this(uuid, exoMediaDrm, mediaDrmCallback,
        map2 == null ? new HashMap<>() : map2, false, 3);
    //  ^^^^ condition                   ^^^^ value
}

A-6: zzbsq.java

File: com/google/android/gms/internal/ads/zzbsq.java

public zzbsq(Context context, Looper looper, ...) {
    Context applicationContext = context.getApplicationContext();
    super(applicationContext == null ? context : applicationContext, looper, 8, ...);
    //    ^^^^^^^^^^^^^^^^^^ condition   ^^^^^^^^^^^^^^^^^^ value
}

A-7, A-8, A-9, A-10: String.valueOf Pattern (4 cases)

Files: zzga.java, zzwq.java, zzbn.java (2 cases)

zza(String str, Throwable th) {
    String strValueOf = String.valueOf(str);
    super(strValueOf.length() != 0
        ? "CodedOutputStream was writing...".concat(strValueOf)
        : new String("CodedOutputStream was writing..."), th);
    //    ^^^^^^^^^ condition (.length())      ^^^^^^^^^ value (.concat())
}

DEX Bytecode Analysis

# Example: getApplicationContext pattern
invoke-virtual {p1}, Landroid/content/Context;->getApplicationContext()Landroid/content/Context;
move-result-object v0                    # v0 = result

# v0 used in BOTH condition and value
if-eqz v0, :use_default
move-object v1, v0                       # Use v0 as value
goto :continue

:use_default
move-object v1, p1                       # Use original context

:continue
invoke-direct {p0, v1, ...}, <init>      # super(v1, ...)

Why Inlining Fails

// Original (with temp variable - VALID bytecode, INVALID Java)
Context appContext = context.getApplicationContext();
super(appContext == null ? context : appContext, ...);

// If we inline (INVALID - method called TWICE!)
super(context.getApplicationContext() == null 
    ? context 
    : context.getApplicationContext(),  // ❌ Second call!
    ...);

Problems with double evaluation:

  1. Side effects: Method may modify state
  2. Performance: Expensive operations run twice
  3. Inconsistency: Results may differ between calls

Theoretical Solution

Implement side-effect analysis to identify pure expressions:

Expression Side-effect Safe to Inline
String.valueOf(str) None ✅ Yes
map (parameter) None ✅ Yes
context.getApplicationContext() Uncertain ⚠️ Risky
contentLengthStrategy (parameter) None ✅ Yes

Implementation approach:

  1. Parameter references → Always safe
  2. Known pure functions (String.valueOf, Integer.valueOf, etc.) → Safe
  3. General method calls → Require analysis or whitelist

Status

Partially solvable - Requires side-effect analysis implementation.

Would need to:

  1. Build a whitelist of known pure methods
  2. Detect direct parameter references
  3. Analyze method purity (complex)

Related

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