mirror of
https://github.com/redis/redis.git
synced 2026-07-16 13:32:51 -04:00
Fix NULL deref in usUntilEarliestTimer when all time events are deleted (#15391)
Some checks are pending
CI / test-ubuntu-latest (push) Waiting to run
CI / test-sanitizer-address (push) Waiting to run
CI / build-debian-old (push) Waiting to run
CI / build-macos-latest (push) Waiting to run
CI / build-32bit (push) Waiting to run
CI / build-libc-malloc (push) Waiting to run
CI / build-centos-jemalloc (push) Waiting to run
CI / build-old-chain-jemalloc (push) Waiting to run
Codecov / code-coverage (push) Waiting to run
External Server Tests / test-external-standalone (push) Waiting to run
External Server Tests / test-external-cluster (push) Waiting to run
External Server Tests / test-external-nodebug (push) Waiting to run
Spellcheck / Spellcheck (push) Waiting to run
Some checks are pending
CI / test-ubuntu-latest (push) Waiting to run
CI / test-sanitizer-address (push) Waiting to run
CI / build-debian-old (push) Waiting to run
CI / build-macos-latest (push) Waiting to run
CI / build-32bit (push) Waiting to run
CI / build-libc-malloc (push) Waiting to run
CI / build-centos-jemalloc (push) Waiting to run
CI / build-old-chain-jemalloc (push) Waiting to run
Codecov / code-coverage (push) Waiting to run
External Server Tests / test-external-standalone (push) Waiting to run
External Server Tests / test-external-cluster (push) Waiting to run
External Server Tests / test-external-nodebug (push) Waiting to run
Spellcheck / Spellcheck (push) Waiting to run
Fixes #13992 ## The problem `usUntilEarliestTimer()` in `src/ae.c` scans the time event list for the nearest non-deleted timer. It already guards the empty-list case (`if (te == NULL) return -1;`), but when the list is non-empty yet every event is marked `AE_DELETED_EVENT_ID`, the loop finishes with `earliest == NULL` and the subsequent `earliest->when` access is a NULL pointer dereference. ## The fix Add `if (earliest == NULL) return -1;` after the scan, mirroring the existing empty-list guard. `-1` is the correct value here rather than `0`: the caller in `aeProcessEvents()` treats a negative result as "no timer to wait for" and leaves the poll timeout unset (blocking on I/O), whereas `0` would make it poll with a zero timeout and busy-loop until the deleted events are reclaimed. Note: Harmless in practice — Redis always has the self-rearming serverCron timer, so earliest is never NULL. This is defensive hardening for the generic ae.c loop rather than a real crash fix.
This commit is contained in:
parent
5b5c32663b
commit
0e618fafdf
1 changed files with 5 additions and 0 deletions
5
src/ae.c
5
src/ae.c
|
|
@ -271,6 +271,11 @@ static int64_t usUntilEarliestTimer(aeEventLoop *eventLoop) {
|
|||
te = te->next;
|
||||
}
|
||||
|
||||
/* The list may hold only events marked AE_DELETED_EVENT_ID, leaving no
|
||||
* earliest timer. Mirror the empty-list case above and report "no timer"
|
||||
* instead of dereferencing a NULL earliest. */
|
||||
if (earliest == NULL) return -1;
|
||||
|
||||
monotime now = getMonotonicUs();
|
||||
return (now >= earliest->when) ? 0 : earliest->when - now;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue