Skip to content

DefaultSimulationContext derives its Koin scope id from an identity hash code (not unique) #757

Description

@bedaHovorka

Found while building ControlledLoopOverheadBenchmark (PR/commit cd651b1).

Problem

DefaultSimulationContext creates its Koin scope with an id taken from an identity hash code:

// core/src/commonMain/kotlin/cz/vutbr/fit/interlockSim/context/DefaultSimulationContext.kt:152
override val scope =
    KoinPlatformTools.defaultContext().get().createScope(
        scopeId = platformIdentityCode(this),   // <-- System.identityHashCode
        ...
    )

platformIdentityCode delegates to System.identityHashCode on JVM (and kotlin.native.identityHashCode on native). Identity hash codes are not unique — distinct live objects can collide. Its own KDoc even says so ("collisions are possible") and describes the function as being for debug logging, but here it is load-bearing: it is the scopes primary key.

DefaultEditingContext:98 has the same shape (scopeId = this.hashCode().toString()).

Impact

Context.close() does close the scope (Context.kt:126), so at normal context volumes ids get recycled harmlessly and this never shows. Under context churn it throws:

org.koin.core.error.ScopeAlreadyCreatedException: Scope with id 1052863908 is already created

Reproduced reliably by running the controlled-loop benchmark in JMH AverageTime mode, which builds ~38k contexts per iteration. Birthday-bound on a 31-bit space makes a collision near-certain at that volume.

This is currently latent rather than user-visible — no production path creates contexts at that rate. But the scope id is not a safe identifier, and any future work that creates many contexts (scale validation, long agent-driven runs, fuzzing, stress tests) can hit it. It also means two simultaneously-live contexts can, in principle, collide.

Suggested fix

Replace the identity-hash scope id with something actually unique — a monotonic counter (AtomicLong/atomicfu for KMP) or a UUID — in both DefaultSimulationContext and DefaultEditingContext. While there, correct the platformIdentityCode KDoc, or restrict it to logging as documented.

Workaround in place

ControlledLoopOverheadBenchmark uses Mode.SingleShotTime to keep context count in the hundreds, and documents why. That constraint can be lifted once this is fixed.

Metadata

Metadata

Labels

bugSomething isn't workingcoreChanges to the :core multiplatform module

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions