Skip to content

Data race on source.refresh field in sources.go #3204

Description

@hklcf

Bug Description

There is a data race on the source.refresh field in sources.go. The time.Time value is written at lines 180, 185, and 211 without holding the source lock, while PrefetchSources() reads it at line 267 without any synchronization.

Affected Code

sources.go:180 (in fetchWithCache):

source.refresh = now.Add(ttl)  // write without lock

sources.go:267 (in PrefetchSources):

if source.refresh.IsZero() || source.refresh.After(now) {  // read without lock
    continue
}

Impact

time.Time is a 16-byte struct on 64-bit platforms. Concurrent write and read without synchronization is undefined behavior in Go's memory model. A partially written value could cause IsZero() or After() to read corrupted bytes, leading to incorrect prefetch scheduling or missed source updates.

Fix

Wrap writes in the source lock:

source.Lock()
source.refresh = now.Add(ttl)
source.Unlock()

And reads:

source.RLock()
needsRefresh := source.refresh.IsZero() || !source.refresh.After(now)
source.RUnlock()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions