mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Savestate: Bounds-check sizes from the file, and plug leaks on load
Reject sizes past the end of the state before allocating (FPL, PGF, achievements, SAS grain, savedata list, the memory fast path), fail instead of desyncing on a SAS voice count mismatch, and free what old states' paths and shrinking pointer containers dropped. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
7fa6be6a25
commit
0a687b9435
12 files changed
+68
-3
No files matched your search
@@ -27,7 +27,7 @@ void DoDeque(PointerWrap &p, std::deque<T> &x, T &default_val) {
|
||||
Do(p, deq_size);
|
||||
// Guard against an attacker-controlled size driving a huge resize, same as DoVector.
|
||||
if (p.mode == PointerWrap::MODE_READ || p.mode == PointerWrap::MODE_VERIFY) {
|
||||
if (deq_size > p.Remaining() / sizeof(T)) {
|
||||
if (deq_size > p.Remaining() / SerializeMinElemSize<T>()) {
|
||||
p.SetError(PointerWrap::ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
@@ -40,6 +40,13 @@ void DoDeque(PointerWrap &p, std::deque<T> &x, T &default_val) {
|
||||
|
||||
template<class T>
|
||||
void Do(PointerWrap &p, std::deque<T *> &x) {
|
||||
if (p.mode == PointerWrap::MODE_READ) {
|
||||
// The elements are owned (DoClass replaces them), and a shorter deque would drop the rest.
|
||||
for (T *elem : x) {
|
||||
delete elem;
|
||||
}
|
||||
x.clear();
|
||||
}
|
||||
T *dv = nullptr;
|
||||
DoDeque(p, x, dv);
|
||||
}
|
||||
|
||||
@@ -126,6 +126,13 @@ void DoVector(PointerWrap &p, std::vector<T> &x, T &default_val) {
|
||||
|
||||
template<class T>
|
||||
void Do(PointerWrap &p, std::vector<T *> &x) {
|
||||
if (p.mode == PointerWrap::MODE_READ) {
|
||||
// The elements are owned (DoClass replaces them), and a shorter vector would drop the rest.
|
||||
for (T *elem : x) {
|
||||
delete elem;
|
||||
}
|
||||
x.clear();
|
||||
}
|
||||
T *dv = nullptr;
|
||||
DoVector(p, x, dv);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,13 @@ void DoList(PointerWrap &p, std::list<T> &x, T &default_val) {
|
||||
|
||||
template<class T>
|
||||
void Do(PointerWrap &p, std::list<T *> &x) {
|
||||
if (p.mode == PointerWrap::MODE_READ) {
|
||||
// The elements are owned (DoClass replaces them), and a shorter list would drop the rest.
|
||||
for (T *elem : x) {
|
||||
delete elem;
|
||||
}
|
||||
x.clear();
|
||||
}
|
||||
T *dv = nullptr;
|
||||
Do(p, x, dv);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user