From af46362f3413e2f90f36b1b86968dac05bbf4b3a Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Thu, 27 Nov 2008 05:30:18 +0000 Subject: [PATCH] Fixes for crashes if firstblock or numblocks is > 2049 Fixes some memory leaks, removes duplicate function some information about hdr added git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1311 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DolphinWX/Src/MemcardManager.cpp | 6 +- .../DolphinWX/Src/MemoryCards/GCMemcard.cpp | 81 +++++++++++-------- .../DolphinWX/Src/MemoryCards/GCMemcard.h | 20 ++--- 3 files changed, 62 insertions(+), 45 deletions(-) diff --git a/Source/Core/DolphinWX/Src/MemcardManager.cpp b/Source/Core/DolphinWX/Src/MemcardManager.cpp index 561a507df8..0446ec284c 100644 --- a/Source/Core/DolphinWX/Src/MemcardManager.cpp +++ b/Source/Core/DolphinWX/Src/MemcardManager.cpp @@ -664,9 +664,11 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card, int page) m_MemcardList[card]->SetItem(index, COLUMN_BANNER, wxEmptyString); m_MemcardList[card]->SetItem(index, COLUMN_TITLE, wxString::FromAscii(title)); m_MemcardList[card]->SetItem(index, COLUMN_COMMENT, wxString::FromAscii(comment)); - if (!memoryCard[card]->GetNumBlocks(j, &blocks)) blocks = 0; + blocks = memoryCard[card]->GetFileSize(j); + if (blocks == 0xFFFF) blocks = 0; wxBlock.Printf(wxT("%10d"), blocks); - if (!memoryCard[card]->GetFirstBlock(j,&firstblock)) firstblock = 0; + firstblock = memoryCard[card]->GetFirstBlock(j); + if (firstblock == 0xFFFF) firstblock = 3; // to make firstblock -1 wxFirstBlock.Printf(wxT("%10d"), firstblock-4); m_MemcardList[card]->SetItem(index,COLUMN_BLOCKS, wxBlock); m_MemcardList[card]->SetItem(index,COLUMN_FIRSTBLOCK, wxFirstBlock); diff --git a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp index f284ee1e37..18d5932436 100644 --- a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp +++ b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp @@ -70,7 +70,7 @@ void GCMemcard::calc_checksumsBE(u16 *buf, u32 num, u16 *c1, u16 *c2) } } -u16 GCMemcard::GetFreeBlocks(void) +u16 GCMemcard::GetFreeBlocks() { if (!mcdFile) return 0; return BE16(bat.FreeBlocks); @@ -119,18 +119,12 @@ bool GCMemcard::TitlePresent(DEntry d) return false; } -bool GCMemcard::GetNumBlocks(u32 index, u16* buffer) +u16 GCMemcard::GetFirstBlock(u32 index) { - if (!mcdFile) return false; - *buffer = BE16(dir.Dir[index].BlockCount); - return true; -} - -bool GCMemcard::GetFirstBlock(u32 index, u16* buffer) -{ - if (!mcdFile) return false; - *buffer = BE16(dir.Dir[index].FirstBlock); - return true; + if (!mcdFile) return 0xFFFF; + u16 block = BE16(dir.Dir[index].FirstBlock); + if (block > MAXBLOCK) return 0xFFFF; + return block; } u32 GCMemcard::RemoveFile(u32 index) //index in the directory array @@ -161,15 +155,21 @@ u32 GCMemcard::RemoveFile(u32 index) //index in the directory array u16 freeBlock= BE16(bat.FreeBlocks) - BE16(d->BlockCount); bat.FreeBlocks[0] = u8(freeBlock >> 8); bat.FreeBlocks[1] = u8(freeBlock); - t = new u8[GetFileSize(i) * 0x2000]; - switch (GetFileData(i, t, true)) + + u16 size = GetFileSize(i); + if (size != 0xFFFF) { - case NOMEMCARD: - delete[] t; - break; - case FAIL: - return FAIL; - break; + t = new u8[size * 0x2000]; + switch (GetFileData(i, t, true)) + { + case NOMEMCARD: + delete[] t; + break; + case FAIL: + delete[] t; + return FAIL; + break; + } } } memset(&(dir.Dir[i]), 0xFF, 0x40); @@ -308,7 +308,7 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents, int remove) return fileBlocks; } -u32 GCMemcard::GetFileData(u32 index, u8*dest, bool old) //index in the directory array +u32 GCMemcard::GetFileData(u32 index, u8* dest, bool old) //index in the directory array { if (!mcdFile) return NOMEMCARD; @@ -316,7 +316,8 @@ u32 GCMemcard::GetFileData(u32 index, u8*dest, bool old) //index in the director u16 saveLength = BE16(dir.Dir[index].BlockCount); u16 memcardSize = BE16(hdr.Size) * 0x0010; - if (block + saveLength > memcardSize) + if ((block == 0xFFFF) || (saveLength == 0xFFFF) + || (block + saveLength > memcardSize)) { return FAIL; } @@ -344,11 +345,13 @@ u32 GCMemcard::GetFileData(u32 index, u8*dest, bool old) //index in the director return SUCCESS; } -u32 GCMemcard::GetFileSize(u32 index) //index in the directory array +u16 GCMemcard::GetFileSize(u32 index) //index in the directory array { - if (!mcdFile) return 0; + if (!mcdFile) return 0xFFFF; - return BE16(dir.Dir[index].BlockCount); + u16 blocks = BE16(dir.Dir[index].BlockCount); + if (blocks > (u16) MAXBLOCK) return 0xFFFF; + return blocks; } bool GCMemcard::GetFileInfo(u32 index, GCMemcard::DEntry& info) //index in the directory array @@ -374,7 +377,7 @@ bool GCMemcard::GetComment1(u32 index, char *fn) //index in the directory array u32 Comment1 = BE32(dir.Dir[index].CommentsAddr); u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - 5; - if (Comment1 == 0xFFFFFFFF) + if ((DataBlock > MAXBLOCK) || (Comment1 == 0xFFFFFFFF)) { fn[0] = 0; return false; @@ -391,7 +394,7 @@ bool GCMemcard::GetComment2(u32 index, char *fn) //index in the directory array u32 Comment1 = BE32(dir.Dir[index].CommentsAddr); u32 Comment2 = Comment1 + 32; u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - 5; - if (Comment1 == 0xFFFFFFFF) + if ((DataBlock > MAXBLOCK) || (Comment1 == 0xFFFFFFFF)) { fn[0] = 0; return false; @@ -479,7 +482,7 @@ bool GCMemcard::ReadBannerRGBA8(u32 index, u32* buffer) u32 DataOffset = BE32(dir.Dir[index].ImageOffset); u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - 5; - if (DataOffset == 0xFFFFFFFF) + if ((DataBlock > MAXBLOCK) || (DataOffset == 0xFFFFFFFF)) { return false; } @@ -516,7 +519,7 @@ u32 GCMemcard::ReadAnimRGBA8(u32 index, u32* buffer, u8 *delays) u32 DataOffset = BE32(dir.Dir[index].ImageOffset); u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - 5; - if (DataOffset == 0xFFFFFFFF) + if ((DataBlock > MAXBLOCK) || (DataOffset == 0xFFFFFFFF)) { return 0; } @@ -663,14 +666,18 @@ u32 GCMemcard::CopyFrom(GCMemcard& source, u32 index) DEntry d; if (!source.GetFileInfo(index, d)) return 0; - - u8 *t = new u8[source.GetFileSize(index) * 0x2000]; + + u32 size = source.GetFileSize(index); + if (size == 0xFFFF) return 0; + u8 *t = new u8[size * 0x2000]; switch (source.GetFileData(index, t, true)) { case FAIL: + delete[] t; return FAIL; case NOMEMCARD: + delete[] t; return NOMEMCARD; default: break; @@ -806,16 +813,22 @@ u32 GCMemcard::ExportGci(u32 index, const char *fileName) fseek(gci, 0, SEEK_SET); DEntry d; - if (!this->GetFileInfo(index, d)) return NOMEMCARD; + if (!GetFileInfo(index, d)) return NOMEMCARD; assert(fwrite(&d, 1, 0x40, gci) == 0x40); - - u8 *t = new u8[this->GetFileSize(index) * 0x2000]; + + u32 size = GetFileSize(index); + if (size == 0xFFFF)return FAIL; + u8 *t = new u8[size * 0x2000]; switch(GetFileData(index, t, true)) { case FAIL: + fclose(gci); + delete []t; return FAIL; case NOMEMCARD: + fclose(gci); + delete []t; return NOMEMCARD; default: break; diff --git a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h index dc0ee0664f..c66c25dec8 100644 --- a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h +++ b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h @@ -46,7 +46,8 @@ enum NOFILE, TITLEPRESENT, SUCCESS = 0x2000, - FAIL + FAIL, + MAXBLOCK = 0x2049 }; class GCMemcard @@ -66,9 +67,10 @@ private: }; struct Header { //Offset Size Description - u8 Unk[12]; //0x0000 12 ? + u8 Unk1[12]; //0x0000 12 ? OSTime fmtTime; //0x000c 8 time of format (OSTime value) - u8 UID[12]; //0x0014 12 unique card id (?) + u8 SramBias[4]; //0x0014 4 sram bias at time of format + u8 Unk2[8]; //0x0018 8 ? almost always 0 or 1 u8 Pad1[2]; //0x0020 2 padding zeroes u8 Size[2]; //0x0022 2 size of memcard in Mbits u8 Encoding[2]; //0x0024 2 encoding (ASCII or japanese) @@ -168,21 +170,21 @@ public: // buffer needs to be a char[32] or bigger bool GetFileName(u32 index, char* buffer); - bool GetNumBlocks(u32 index, u16* buffer); + // get file length in blocks + u16 GetFileSize(u32 index); + // get first block for file + u16 GetFirstBlock(u32 index); + + // get the free blocks from bat u16 GetFreeBlocks(void); - bool GetFirstBlock(u32 index, u16* buffer); - // buffer needs to be a char[32] or bigger bool GetComment1(u32 index, char* buffer); // buffer needs to be a char[32] or bigger bool GetComment2(u32 index, char* buffer); - // get file length un bytes - u32 GetFileSize(u32 index); - // assumes there's enough space in buffer // old determines if function uses old or new method of copying data // some functions only work with old way, some only work with new way