mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-03 11:15:20 +02:00
The "is this an ELF rather than a PBP" test compared against "\nFLE", which is neither ELF's magic (\x7fELF) nor anything else - most likely a \x7f escape that swallowed the E when it was written in 2013. Since no real file matches it, every file that wasn't a PBP was reported as an ELF and the error branch was unreachable. Compares against the real magic now, so something that's neither is reported as neither. That error also printed the 4-byte magic with %s, which isn't NUL-terminated - it's four hex bytes instead. GetSubFileSize subtracted offsets that come straight out of the file without checking they're ordered or even inside it, so a corrupt PBP produced a size from an unsigned underflow - nearly 4GB, which the callers then had to catch by size limit. It returns 0 for anything that doesn't make sense. Also &(*out)[0] on a zero-length subfile, which is UB on an empty vector. Plus one in ParamSFO: GetDataOffset mixed int and u32 for the data offset, so its bounds check ran in whichever type the promotion landed on. It's size_t throughout now, matching how ReadSFO does the same arithmetic. Booted an EBOOT.PBP to check the PBP path end to end - loads, and generates the same fake disc ID as before. pspautotests 314/314, UnitTest 55/55. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
80 lines
2.4 KiB
C++
80 lines
2.4 KiB
C++
// Copyright (c) 2013- PPSSPP Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official git repository and contact information can be found at
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
|
|
#pragma once
|
|
|
|
#include <vector>
|
|
|
|
#include "Common/Common.h"
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/Swap.h"
|
|
|
|
enum PBPSubFile {
|
|
PBP_PARAM_SFO,
|
|
PBP_ICON0_PNG,
|
|
PBP_ICON1_PMF,
|
|
PBP_PIC0_PNG,
|
|
PBP_PIC1_PNG,
|
|
PBP_SND0_AT3,
|
|
PBP_EXECUTABLE_PSP,
|
|
PBP_UNKNOWN_PSAR,
|
|
};
|
|
|
|
struct PBPHeader {
|
|
char magic[4];
|
|
u32_le version;
|
|
u32_le offsets[8];
|
|
};
|
|
|
|
class FileLoader;
|
|
|
|
class PBPReader {
|
|
public:
|
|
PBPReader(FileLoader *fileLoader);
|
|
~PBPReader();
|
|
|
|
bool IsValid() const { return file_ != nullptr; }
|
|
bool IsELF() const { return file_ == nullptr && isELF_; }
|
|
|
|
bool GetSubFile(PBPSubFile file, std::vector<u8> *out) const;
|
|
bool GetSubFileAsString(PBPSubFile file, std::string *out) const;
|
|
|
|
size_t GetSubFileSize(PBPSubFile file) const {
|
|
const int num = (int)file;
|
|
if (num < 0 || num >= (int)ARRAY_SIZE(header_.offsets))
|
|
return 0;
|
|
const u32 start = header_.offsets[num];
|
|
// The last subfile runs to the end of the file, the rest to where the next one starts.
|
|
const u32 stop = num + 1 < (int)ARRAY_SIZE(header_.offsets) ? header_.offsets[num + 1] : (u32)fileSize_;
|
|
// These offsets come out of the file, so they aren't necessarily ordered or even inside it.
|
|
// Subtracting them blind produced a huge size from an underflow.
|
|
if (stop < start || stop > fileSize_)
|
|
return 0;
|
|
return stop - start;
|
|
}
|
|
|
|
private:
|
|
FileLoader *file_ = nullptr;
|
|
size_t fileSize_ = 0;
|
|
// Not const: the constructor reads the file straight into this. It used to be, and was written
|
|
// through a cast that stripped the const away - which compiles, but lets the compiler assume the
|
|
// value never changes from the {} it was initialized with.
|
|
PBPHeader header_{};
|
|
bool isELF_ = false;
|
|
};
|