diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index 8fb90106e1..73f0c87984 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -44,6 +44,8 @@ int CPU_HZ = 222000000; namespace CoreTiming { static std::vector event_types; +// Far more than ever registered. Counts and ids from a savestate are checked against it. +static constexpr int MAX_EVENT_TYPES = 4096; // Only used during restore. static std::set usedEventTypes; static std::set restoredEventTypes; @@ -189,6 +191,9 @@ void RestoreRegisterEvent(int &event_type, const char *name, TimedCallback callb // Some old states have a duplicate restore, do our best to fix... if (restoredEventTypes.count(event_type) != 0) event_type = -1; + // Straight from the file, so don't let a bogus id size the table. + if (event_type < -1 || event_type >= MAX_EVENT_TYPES) + event_type = -1; if (event_type == -1) event_type = nextEventTypeRestoreId++; if (event_type >= (int)event_types.size()) { @@ -542,6 +547,11 @@ void DoState(PointerWrap &p) { int n = (int)event_types.size(); int current = n; Do(p, n); + if (n < 0 || n > MAX_EVENT_TYPES) { + ERROR_LOG(Log::SaveState, "Savestate failure: implausible event type count %d", n); + p.SetError(p.ERROR_FAILURE); + return; + } if (n > current) { if (p.mode != PointerWrap::MODE_READ) { WARN_LOG(Log::SaveState, "Savestate failure: more events than current"); @@ -579,6 +589,13 @@ void DoState(PointerWrap &p) { } Do(p, CPU_HZ); + if (CPU_HZ <= 0) { + // Everything divides by it. + ERROR_LOG(Log::SaveState, "Savestate failure: bad CPU frequency %d", (int)CPU_HZ); + p.SetError(p.ERROR_FAILURE); + CPU_HZ = 222000000; + return; + } Do(p, slicelength); Do(p, globalTimer); Do(p, idledCycles); diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index a15ae8f701..f3e12f4d05 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -497,7 +497,8 @@ void HLEDoState(PointerWrap &p) { delete action; } mipsCallActions.clear(); - if (actions < 0) { + // Each action takes at least its type id. + if (actions < 0 || (size_t)actions > p.Remaining() / sizeof(int)) { p.SetError(p.ERROR_FAILURE); return; }