Skip to content

fix(wait): compute rmw_wait timeout in int64 to preserve infinite blocking [P2] - #8

Merged
benaliabderrahmane merged 1 commit into
mainfrom
fix/p2-10-wait-timeout-overflow
Jun 5, 2026
Merged

benaliabderrahmane merged 1 commit into
mainfrom
fix/p2-10-wait-timeout-overflow

Conversation

@benaliabderrahmane

Copy link
Copy Markdown
Owner

Severity: P2 — found by a full multi-agent code audit (method + findings in AUDIT_FINAL.md).

Problem

timeout_ms = static_cast<int>(wait_timeout->sec * 1000 + wait_timeout->nsec / 1000000) truncated a 64-bit duration to int. RMW_DURATION_INFINITE ({9223372036, 854775807}) → ~9.2e12 ms → truncates to ~2.077e9 ms (~24 days), so "block forever" silently became a ~24-day timeout; a 60-day finite timeout truncated to ~10 days.

Fix

Accumulate the milliseconds in int64_t; map the infinite duration (and any value > INT_MAX ms) to epoll_wait's -1 sentinel (block forever); otherwise clamp to [0, INT_MAX]. Preserves the existing <1ms → 1ms rounding.

File: rmw_unix_socket_cpp/src/rmw_wait.cpp
Build: clean.

@benaliabderrahmane

Copy link
Copy Markdown
Owner Author

Approve (with an optional follow-up).

Verified this is a clean, focused, correct fix for the P2 silent-truncation bug. Re-derived the arithmetic against the live headers: sec/nsec are uint64_t and RMW_DURATION_INFINITE = {9223372036, 854775807}, so the new int64 accumulation at rmw_wait.cpp:300-301 computes 9223372036*1000 + 854775807/1000000 = 9223372036854 ms, which exceeds INT_MAX, so the guard at :302-303 maps it to timeout_ms = -1 and epoll_wait blocks forever. The pre-fix static_cast<int> truncated that ~9.2e12 ms to ~2.077e9 ms (~24 days) — confirmed the bug is resolved and infinite blocking is preserved. Also checked the downstream EINTR-retry path (rmw_wait.cpp:315-335): deadline_ns/rem_ms are computed only when timeout_ms >= 0 (so <= INT_MAX ms) and are bounded — no overflow, and unchanged by this PR.

Scope is clean per CLAUDE.md §1/§2/§3: the diff touches only the timeout computation plus the necessary <limits> include and a one-line comment on the changed line — no "while I was here" edits, matches existing style.

Non-blocking follow-ups:

  • (CLAUDE.md §4) The fix ships without a regression test. test/test_rmw_wait.cpp exists and is registered (CMakeLists.txt:186), but nothing in test/ pins that RMW_DURATION_INFINITE or a >INT_MAX-ms duration does not return early. Worth a bounded large/infinite-timeout assertion to prevent a future refactor silently reintroducing truncation.
  • (cosmetic) The PR body says the non-infinite path clamps to "[0, INT_MAX] ms", but only the upper bound is guarded at rmw_wait.cpp:302; no lower clamp exists or is needed (sec/nsec are uint64). Worth aligning the wording.
  • (latent) static_cast<int64_t>(sec)*1000 at rmw_wait.cpp:300 is signed-overflow UB for sec > ~9.22e15 — unreachable from the real ROS stack and identical to the pre-fix assumption, so no regression; noting only for completeness.

LGTM.

@benaliabderrahmane
benaliabderrahmane merged commit 3674bc2 into main Jun 5, 2026
3 checks passed
@benaliabderrahmane
benaliabderrahmane deleted the fix/p2-10-wait-timeout-overflow branch June 17, 2026 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant