gsdx: Fix GS dump readback EOF handling

An EOF only occurs after attempting to read past the end of the file.
Account for this correctly, which fixes a potential infinite loop when
reading back an xz compressed GS dump.
This commit is contained in:
Jonathan Li 2017-05-27 12:21:09 +01:00 committed by Gregory Hainaut
parent a6ed698fca
commit 742b0edaa8
3 changed files with 29 additions and 27 deletions

View File

@ -1603,11 +1603,9 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
file->Read(regs, 0x2000); file->Read(regs, 0x2000);
while(!file->IsEof()) uint8 type;
while(file->Read(&type, 1))
{ {
uint8 type;
file->Read(&type, 1);
Packet* p = new Packet(); Packet* p = new Packet();
p->type = type; p->type = type;

View File

@ -111,14 +111,14 @@ void GSDumpLzma::Decompress() {
} }
bool GSDumpLzma::IsEof() { bool GSDumpLzma::IsEof() {
return feof(m_fp) && (m_avail == 0); return feof(m_fp) && m_avail == 0 && m_strm.avail_in == 0;
} }
void GSDumpLzma::Read(void* ptr, size_t size) { bool GSDumpLzma::Read(void* ptr, size_t size) {
size_t off = 0; size_t off = 0;
uint8_t* dst = (uint8_t*)ptr; uint8_t* dst = (uint8_t*)ptr;
size_t full_size = size; size_t full_size = size;
while (size) { while (size && !IsEof()) {
if (m_avail == 0) { if (m_avail == 0) {
Decompress(); Decompress();
} }
@ -130,7 +130,13 @@ void GSDumpLzma::Read(void* ptr, size_t size) {
m_start += l; m_start += l;
off += l; off += l;
} }
Repack(ptr, full_size);
if (size == 0) {
Repack(ptr, full_size);
return true;
}
return false;
} }
GSDumpLzma::~GSDumpLzma() { GSDumpLzma::~GSDumpLzma() {
@ -156,17 +162,17 @@ bool GSDumpRaw::IsEof() {
return feof(m_fp); return feof(m_fp);
} }
void GSDumpRaw::Read(void* ptr, size_t size) { bool GSDumpRaw::Read(void* ptr, size_t size) {
if (size == 1) { size_t ret = fread(ptr, 1, size, m_fp);
// I don't know why but read of size 1 is not happy if (ret != size && ferror(m_fp)) {
int v = fgetc(m_fp); fprintf(stderr, "GSDumpRaw:: Read error (%zu/%zu)\n", ret, size);
memcpy(ptr, &v, 1); throw "BAD"; // Just exit the program
} else {
size_t ret = fread(ptr, 1, size, m_fp);
if (ret != size) {
fprintf(stderr, "GSDumpRaw:: Read error (%zu/%zu)\n", ret, size);
throw "BAD"; // Just exit the program
}
} }
Repack(ptr, size);
if (ret == size) {
Repack(ptr, size);
return true;
}
return false;
} }

View File

@ -30,7 +30,7 @@ class GSDumpFile {
public: public:
virtual bool IsEof() = 0; virtual bool IsEof() = 0;
virtual void Read(void* ptr, size_t size) = 0; virtual bool Read(void* ptr, size_t size) = 0;
GSDumpFile(char* filename, const char* repack_filename); GSDumpFile(char* filename, const char* repack_filename);
virtual ~GSDumpFile(); virtual ~GSDumpFile();
@ -54,8 +54,8 @@ class GSDumpLzma : public GSDumpFile {
GSDumpLzma(char* filename, const char* repack_filename); GSDumpLzma(char* filename, const char* repack_filename);
virtual ~GSDumpLzma(); virtual ~GSDumpLzma();
bool IsEof(); bool IsEof() final;
void Read(void* ptr, size_t size); bool Read(void* ptr, size_t size) final;
}; };
class GSDumpRaw : public GSDumpFile { class GSDumpRaw : public GSDumpFile {
@ -67,13 +67,11 @@ class GSDumpRaw : public GSDumpFile {
size_t m_avail; size_t m_avail;
size_t m_start; size_t m_start;
void Decompress();
public: public:
GSDumpRaw(char* filename, const char* repack_filename); GSDumpRaw(char* filename, const char* repack_filename);
virtual ~GSDumpRaw() = default; virtual ~GSDumpRaw() = default;
bool IsEof(); bool IsEof() final;
void Read(void* ptr, size_t size); bool Read(void* ptr, size_t size) final;
}; };