fix(libkernel): clamp POSIX deadlines beyond the clock range instead of overflowing

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
This commit is contained in:
Claude committed 2026-10-11 21:01:57 +00:00
1 parent 0a8b1d32b1
commit e463c5d11f
2 files changed
+27 -4

No files matched your search

@@ -24,10 +24,18 @@ inline bool RelativeMicroseconds(int clockId, const KernelTimespec* abstime, Ker
if (!abstime || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) return false;
KernelTimespec now{};
clock_gettime_nid_postfix(clockId, &now);
const auto deadline = std::chrono::seconds(abstime->tv_sec) + std::chrono::nanoseconds(abstime->tv_nsec);
const auto current = std::chrono::seconds(now.tv_sec) + std::chrono::nanoseconds(now.tv_nsec);
const auto remaining = std::chrono::duration_cast<std::chrono::microseconds>(deadline - current).count();
*usec = remaining <= 0 ? 0 : remaining >= std::numeric_limits<KernelUseconds>::max() ? std::numeric_limits<KernelUseconds>::max() : static_cast<KernelUseconds>(remaining);
constexpr auto maximum = std::numeric_limits<KernelUseconds>::max();
if (abstime->tv_sec < now.tv_sec - 1) {
*usec = 0;
return true;
}
const std::int64_t seconds = abstime->tv_sec - now.tv_sec;
if (seconds > static_cast<std::int64_t>(maximum / 1000000) + 1) {
*usec = maximum;
return true;
}
const std::int64_t remaining = (seconds * 1000000000 + abstime->tv_nsec - now.tv_nsec) / 1000;
*usec = remaining <= 0 ? 0 : remaining >= maximum ? maximum : static_cast<KernelUseconds>(remaining);
return true;
}
+15
View File
@@ -190,8 +190,23 @@ static void CheckFailedLockAttempts() {
Require(rwlock == nullptr);
}
static void CheckDeadlinesBeyondTheClockRange() {
PthreadRwlock rwlock = nullptr;
Holder reader{&rwlock, false};
Start(reader);
const KernelTimespec farPast{INT64_MIN, 0};
Require(pthread_rwlock_timedwrlock_nid_postfix(&rwlock, &farPast) == GUEST_ETIMEDOUT);
reader.release.store(true);
const KernelTimespec farFuture{INT64_MAX, 0};
Require(pthread_rwlock_timedwrlock_nid_postfix(&rwlock, &farFuture) == 0);
Require(pthread_rwlock_unlock_nid_postfix(&rwlock) == 0);
Require(scePthreadJoin(reader.thread, nullptr) == SCE_OK);
Require(pthread_rwlock_destroy_nid_postfix(&rwlock) == 0);
}
int main() {
CheckConcurrentFirstWrlockExcludes();
CheckDeadlinesBeyondTheClockRange();
const KernelTimespec invalid{0, NANOS_PER_SECOND};
PthreadRwlock fresh[4] = {};
Require(pthread_rwlock_tryrdlock_nid_postfix(&fresh[0]) == 0);