diff --git a/core/libs/prx/libSceRtc/Export.cpp b/core/libs/prx/libSceRtc/Export.cpp index 272b78cb3..3a0895ae1 100644 --- a/core/libs/prx/libSceRtc/Export.cpp +++ b/core/libs/prx/libSceRtc/Export.cpp @@ -109,6 +109,7 @@ std::int64_t localOffsetSeconds(std::uint64_t utcTick) { int addTicks(RtcTick* dst, const RtcTick* src, std::int64_t count, std::int64_t unit) { if (!dst || !src) return SCE_RTC_ERROR_INVALID_POINTER; + if (src->tick > MAX_TICK) return SCE_RTC_ERROR_INVALID_VALUE; if (count != 0 && (count > std::numeric_limits::max() / unit || count < std::numeric_limits::min() / unit)) return SCE_RTC_ERROR_INVALID_VALUE; const std::int64_t delta = count * unit; if (delta < 0 ? src->tick < static_cast(-(delta + 1)) + 1 : MAX_TICK - src->tick < static_cast(delta)) return SCE_RTC_ERROR_INVALID_VALUE; @@ -118,6 +119,7 @@ int addTicks(RtcTick* dst, const RtcTick* src, std::int64_t count, std::int64_t int addMonths(RtcTick* dst, const RtcTick* src, std::int64_t months) { if (!dst || !src) return SCE_RTC_ERROR_INVALID_POINTER; + if (src->tick > MAX_TICK) return SCE_RTC_ERROR_INVALID_VALUE; RtcDateTime time = fromTick(src->tick); const std::int64_t monthIndex = time.year * 12 + (time.month - 1) + months; const std::int64_t year = monthIndex / 12; diff --git a/core/libs/tests/GuestRtc.cpp b/core/libs/tests/GuestRtc.cpp index 23d203f06..fca1f2688 100644 --- a/core/libs/tests/GuestRtc.cpp +++ b/core/libs/tests/GuestRtc.cpp @@ -4,6 +4,7 @@ #include #include #include +#include extern "C" { int APS5_VABI sceRtcCheckValid(const RtcDateTime*); @@ -168,6 +169,38 @@ int main() { Require(sceRtcTickAddTicks(&result, &source, 1) == invalidValue); Require(sceRtcTickAddTicks(nullptr, &source, 1) == invalidPointer); + const std::uint64_t invalidTicks[] = {maxTick + 1, std::numeric_limits::max()}; + for (std::uint64_t invalidTick : invalidTicks) { + source.tick = invalidTick; + result.tick = 123; + Require(sceRtcTickAddTicks(&result, &source, 0) == invalidValue && result.tick == 123); + Require(sceRtcTickAddTicks(&result, &source, 1) == invalidValue && result.tick == 123); + Require(sceRtcTickAddTicks(&result, &source, -1) == invalidValue && result.tick == 123); + Require(sceRtcTickAddSeconds(&result, &source, 0) == invalidValue && result.tick == 123); + Require(sceRtcTickAddDays(&result, &source, -1) == invalidValue && result.tick == 123); + Require(sceRtcTickAddMonths(&result, &source, 0) == invalidValue && result.tick == 123); + Require(sceRtcTickAddYears(&result, &source, -1) == invalidValue && result.tick == 123); + Require(sceRtcTickAddTicks(&source, &source, 0) == invalidValue && source.tick == invalidTick); + Require(sceRtcTickAddMonths(&source, &source, -1) == invalidValue && source.tick == invalidTick); + Require(sceRtcTickAddTicks(nullptr, &source, 0) == invalidPointer); + Require(sceRtcTickAddMonths(nullptr, &source, 0) == invalidPointer); + } + + source.tick = maxTick; + Require(sceRtcTickAddTicks(&source, &source, 0) == 0 && source.tick == maxTick); + Require(sceRtcTickAddTicks(&source, &source, -1) == 0 && source.tick == maxTick - 1); + source.tick = maxTick; + Require(sceRtcTickAddMonths(&source, &source, 0) == 0 && source.tick == maxTick); + Require(sceRtcTickAddYears(&result, &source, -1) == 0); + Require(sceRtcSetTick(&converted, &result) == 0 && Equal(converted, RtcDateTime{9998, 12, 31, 23, 59, 59, 999999})); + result.tick = 123; + Require(sceRtcTickAddMonths(&result, &source, 1) == invalidValue && result.tick == 123); + Require(sceRtcTickAddTicks(&result, &source, std::numeric_limits::min()) == invalidValue && result.tick == 123); + Require(sceRtcTickAddSeconds(&result, &source, std::numeric_limits::max()) == invalidValue && result.tick == 123); + source.tick = 0; + Require(sceRtcTickAddMonths(&source, &source, 0) == 0 && source.tick == 0); + Require(sceRtcTickAddMonths(&result, &source, -1) == invalidValue && result.tick == 123); + RtcTick now{}; Require(sceRtcGetCurrentTick(&now) == 0 && now.tick > leapDayTick); RtcTick local{};