read before it was ever written
Improper Initialization
A binding read before it is assigned, a field a constructor forgot, a resource left at its default: the undefined → defined transition is where state begins, and skipping it makes illegal states representable from the very first line.
The first state transition — undefined to defined — is the purest mutated-state bug: use a value before it exists and every later read inherits garbage.
In the wild
Used Before Assigned
A variable or field read before anything wrote to it hands back whatever was already there.
// SMELL: local is never initialized -- reads indeterminate memory
int total() {
int sum; // garbage value
for (int i = 0; i < 10; i++)
sum += i; // adds to garbage; result is nonsense
return sum;
}
// RIGHT: initialize at the point of declaration
int total() {
int sum = 0; // a defined starting state
for (int i = 0; i < 10; i++)
sum += i;
return sum;
}uninit: sum += i over garbage -> nonsense init: sum starts at 0 -> 45
// SMELL: the zero value of a map is nil, and writing to nil panics
var counts map[string]int // nil, not empty
counts["a"]++ // panic: assignment to entry in nil map
// RIGHT: make() gives a real, writable map
counts := make(map[string]int) // initialized
counts["a"]++ // 1
// (reading a nil map is fine -- it's the WRITE that needs init)nil map: counts["a"]++ -> panic made map: counts["a"]++ -> 1
Insecure Default Initialization
A field left at a permissive default — or a constructor that skips it — is a security hole, not just a bug.
class Session:
def __init__(self, user):
self.user = user
# SMELL: is_admin never set; some paths read it -> AttributeError,
# or a __getattr__ shim quietly returns a truthy default
def can_delete(self):
return self.is_admin # AttributeError, or worse: True
# RIGHT: initialize every field to a safe, explicit default
class Session:
def __init__(self, user):
self.user = user
self.is_admin = False # deny by defaultmissing: self.is_admin -> AttributeError / unsafe default: is_admin = False -> deny by default
// SMELL: a half-built object escapes before it's fully set up
function makeUser(req) {
const u = {};
u.name = req.name;
save(u); // saved with role === undefined
u.role = "member"; // too late -- the saved copy is broken
return u;
}
// RIGHT: build the whole value, then let it escape
function makeUser(req) {
return { name: req.name, role: "member" }; // fully initialized
}leaked: save() sees role === undefined whole: object is complete before it escapes
Where this compounds
- TOCTOU Race (Check-Then-Act) × Race Conditions
- Lazy-Init Visibility Race (Double-Checked Locking) × Threading & Mutexes
- Null / Undefined Dereference × Missing & Undefined Returns
- Shape-Drift AttributeError × Duck Typing Without Contracts
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.