Skip to content

Fix NPE race condition in EmbeddedSessionManager.updateDisplayCountAndDuration()#1053

Open
Shamyyoun wants to merge 2 commits into
Iterable:masterfrom
Shamyyoun:fix/npe-race-condition-in-update-display-count-and-duration
Open

Fix NPE race condition in EmbeddedSessionManager.updateDisplayCountAndDuration()#1053
Shamyyoun wants to merge 2 commits into
Iterable:masterfrom
Shamyyoun:fix/npe-race-condition-in-update-display-count-and-duration

Conversation

@Shamyyoun
Copy link
Copy Markdown

Summary

Fixes a NullPointerException crash in updateDisplayCountAndDuration() caused by a TOCTOU (time-of-check/time-of-use) race condition.

Closes #1052


Problem

EmbeddedImpressionData.start is a plain var Date? with no synchronisation. The previous code checked if (impressionData.start != null) but then accessed impressionData.start!! in the body. When called concurrently from multiple threads (e.g. via Dispatchers.Default coroutines), another thread can set start = null between the null-check and the dereference, causing a crash:

Fatal Exception: java.lang.NullPointerException
  at com.iterable.iterableapi.EmbeddedSessionManager.updateDisplayCountAndDuration(EmbeddedSessionManager.kt:114)
  at com.iterable.iterableapi.EmbeddedSessionManager.endAllImpressions(EmbeddedSessionManager.kt:91)
  at com.iterable.iterableapi.EmbeddedSessionManager.endSession(EmbeddedSessionManager.kt:41)
  at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:704)

Fix

Capture impressionData.start into a local val before the null-check. Because local variables are thread-confined (stack-allocated), the value cannot be changed by another thread after the null-check passes:

// Before
if (impressionData.start != null) {
    impressionData.duration = ... - impressionData.start!!.time  // ← NPE under concurrent access
}

// After
val start = impressionData.start
if (start != null) {
    impressionData.duration = ... - start.time  // ← safe, local val is immutable
}

This is the idiomatic Kotlin/Java pattern for safe null-check-then-use on shared mutable fields.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NullPointerException in EmbeddedSessionManager.updateDisplayCountAndDuration() — thread-safety race condition

1 participant