mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-12 17:19:28 +01:00
UI, texture packs, headless: Validate values from files
- textures.ini skipLastDXT1Blocks* is subtracted from the hashed size after the memory check, so a large value (or a small one with reduceHash) underflowed it and hashed ~4 GB. Clamp it to the blocks there are. - SND0.AT3 loops with a negative or backwards range pointed playback before the data. Ignore those, and loops outside the data. - impose.rsc sprite bounds were checked as x + w in 32 bits, which wraps. - Store entries are also uninstalled by name, so require a plain filename (. or / was the whole GAME directory). - Headless screenshot compare read (and converted in place) w x h pixels of a reference PNG that could be smaller. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
128cf1b7c4
commit
ebafb89215
5 files changed
+35
-8
No files matched your search
@@ -367,6 +367,9 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, VFSBackend *dir, bool isOverri
|
||||
}
|
||||
options->Get("skipLastDXT1Blocks128x64", &skipLastDXT1Blocks128x64_);
|
||||
options->Get("skipLastDXT1Blocks128x128", &skipLastDXT1Blocks128x128_);
|
||||
// These are subtracted from the hashed size, so can't be more than the blocks there are.
|
||||
skipLastDXT1Blocks128x64_ = std::clamp(skipLastDXT1Blocks128x64_, 0, (128 / 4) * (64 / 4));
|
||||
skipLastDXT1Blocks128x128_ = std::clamp(skipLastDXT1Blocks128x128_, 0, (128 / 4) * (128 / 4));
|
||||
if (reduceHash_ && textureHash_ == ReplacedTextureHash::QUICK) {
|
||||
reduceHash_ = false;
|
||||
ERROR_LOG(Log::TexReplacement, "Texture Replacement: reduceHash option requires safer hash, use xxh32 or xxh64 instead.");
|
||||
@@ -635,11 +638,12 @@ u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, bool swizzled
|
||||
}
|
||||
|
||||
// Hack for Yu Gi Oh texture hashing problem. See issue #19714
|
||||
if (skipLastDXT1Blocks128x64_ && fmt == GE_TFMT_DXT1 && w == 128 && h == 64) {
|
||||
// (reduceHash can make sizeInRAM smaller than all the blocks, so check it can't underflow.)
|
||||
if (skipLastDXT1Blocks128x64_ && fmt == GE_TFMT_DXT1 && w == 128 && h == 64 && (u32)(8 * skipLastDXT1Blocks128x64_) < (u32)sizeInRAM) {
|
||||
// Skip the last few blocks as specified.
|
||||
sizeInRAM -= 8 * skipLastDXT1Blocks128x64_;
|
||||
}
|
||||
if (skipLastDXT1Blocks128x128_ && fmt == GE_TFMT_DXT1 && w == 128 && h == 128) {
|
||||
if (skipLastDXT1Blocks128x128_ && fmt == GE_TFMT_DXT1 && w == 128 && h == 128 && (u32)(8 * skipLastDXT1Blocks128x128_) < (u32)sizeInRAM) {
|
||||
sizeInRAM -= 8 * skipLastDXT1Blocks128x128_;
|
||||
}
|
||||
|
||||
|
||||
+18
-4
@@ -2,6 +2,7 @@
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
|
||||
#include "Common/File/VFS/VFS.h"
|
||||
#include "Common/UI/Root.h"
|
||||
@@ -132,14 +133,19 @@ bool WavData::Read(RIFFReader &file_) {
|
||||
int samplesPerFrame = codec == PSP_CODEC_AT3PLUS ? 2048 : 1024;
|
||||
|
||||
for (int i = 0; i < numLoops; ++i) {
|
||||
// Only seen forward loops, so let's ignore others.
|
||||
if (loops[i].type != 0)
|
||||
// Only seen forward loops, so let's ignore others. Also ones that don't go forwards,
|
||||
// which would point playback before the data.
|
||||
if (loops[i].type != 0 || loops[i].startSample < 0 || loops[i].endSample <= loops[i].startSample)
|
||||
continue;
|
||||
|
||||
// We ignore loop interpolation (fraction) and play count for now.
|
||||
raw_offset_loop_start = (loops[i].startSample / samplesPerFrame) * raw_bytes_per_frame;
|
||||
const s64 loopStart = (s64)(loops[i].startSample / samplesPerFrame) * raw_bytes_per_frame;
|
||||
const s64 loopEnd = (s64)(loops[i].endSample / samplesPerFrame) * raw_bytes_per_frame;
|
||||
if (loopEnd > INT_MAX)
|
||||
continue;
|
||||
raw_offset_loop_start = (int)loopStart;
|
||||
loop_start_offset = loops[i].startSample % samplesPerFrame;
|
||||
raw_offset_loop_end = (loops[i].endSample / samplesPerFrame) * raw_bytes_per_frame;
|
||||
raw_offset_loop_end = (int)loopEnd;
|
||||
loop_end_offset = loops[i].endSample % samplesPerFrame;
|
||||
|
||||
if (loops[i].playCount == 0) {
|
||||
@@ -201,6 +207,14 @@ bool WavData::Read(RIFFReader &file_) {
|
||||
ERROR_LOG(Log::Audio, "Could not descend into RIFF file.");
|
||||
return false;
|
||||
}
|
||||
// The loop points came from the smpl chunk, so they have to land in the data. The sample
|
||||
// offsets (within a frame) are always positive, since the loop samples were checked above.
|
||||
if (raw_offset_loop_start < 0 || raw_offset_loop_end > raw_data_size || raw_offset_loop_start > raw_offset_loop_end) {
|
||||
raw_offset_loop_start = 0;
|
||||
raw_offset_loop_end = 0;
|
||||
loop_start_offset = 0;
|
||||
loop_end_offset = 0;
|
||||
}
|
||||
sample_rate = samplesPerSec;
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -298,7 +298,7 @@ bool ImposeArt::Parse(const std::vector<uint8_t> &file, int pspLanguage) {
|
||||
const uint32_t w = r.U32(rec + 16);
|
||||
const uint32_t h = r.U32(rec + 20);
|
||||
const uint32_t offset = r.U32(rec + 24);
|
||||
if (!r.ok || palette >= NUM_PALETTES || w == 0 || h == 0 || x + w > PSP_W || y + h > PSP_H || (w * h + 1) / 2 != size) {
|
||||
if (!r.ok || palette >= NUM_PALETTES || w == 0 || h == 0 || w > PSP_W || x > PSP_W - w || h > PSP_H || y > PSP_H - h || (w * h + 1) / 2 != size) {
|
||||
return false;
|
||||
}
|
||||
const size_t pixels = block + TEXT_RECORDS + (size_t)offset;
|
||||
|
||||
+3
-1
@@ -448,7 +448,9 @@ void StoreScreen::ParseListing(const std::string &json) {
|
||||
// (Path::operator/ does no ".." normalization); on platforms/builds where
|
||||
// the store index isn't fetched over HTTPS, a MITM'd or compromised
|
||||
// response could otherwise point "launch" at an arbitrary host path.
|
||||
if (HasParentDirComponent(file))
|
||||
// It's also uninstalled (deleted recursively) by name, so "." or "/" would be the
|
||||
// whole GAME directory.
|
||||
if (HasParentDirComponent(file) || !IsSafePathComponent(file))
|
||||
continue;
|
||||
e.file = file;
|
||||
entries_.push_back(e);
|
||||
|
||||
@@ -403,6 +403,13 @@ double ScreenshotComparer::Compare(const Path &screenshotFilename) {
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
// Everything below reads w_ x h_ pixels from it.
|
||||
if (width < (int)w_ || height < (int)h_) {
|
||||
error_ = StringFromFormat("Screenshot is too small (%dx%d, expected %dx%d): %s", width, height, (int)w_, (int)h_, screenshotFilename.ToVisualString().c_str());
|
||||
free(reference_);
|
||||
reference_ = nullptr;
|
||||
return -1.0f;
|
||||
}
|
||||
referenceStride_ = width;
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in new issue
Block a user