shared × unstructured — bad data written permanently, and it spreads

Lossy Coercion Poisons a Shared Ledger

A value silently narrowed to the wrong type is added to a shared running total; the lock keeps the write safe but cannot restore the meaning the coercion threw away.

01the recipe

In the wild

example.py
# SMELL: cents truncated to int before adding to a shared ledger.
# (type errors x threading & mutexes)
with lock:
    ledger["cents"] += int(amount)     # amount=10.99 -> 10; 0.99 lost every add
# the lock serializes the write, but the truncation is already baked in;
# the shared total drifts low and can never be reconciled.

# RIGHT: keep an exact integer-cents type end to end; never coerce lossily.
cents = round(Decimal(amount) * 100)   # exact, total-preserving
with lock:
    ledger["cents"] += cents
int(amount) discards the fractional cents before the value ever reaches the shared ledger. The mutex makes the increment thread-safe, but it locks in an already-wrong number; every contributor under-reports and the shared total is permanently, unreconcilably low. Carry an exact type (integer cents / Decimal) so no meaning is lost at the coercion.
// observed
lossy: the shared total drifts low by the truncated remainder, forever
right: exact integer cents; the aggregate reconciles to the penny
02weakness catalog

Mapped weaknesses (CWE)

On its own, this defect is catalogued by MITRE as one or more of these weaknesses. The exploitable vulnerability usually appears only when it chains or combines with another.