From 40b6351dae305ca3000e76b452693e81a97ee52d Mon Sep 17 00:00:00 2001 From: zeromus Date: Mon, 15 Feb 2010 11:02:49 +0000 Subject: [PATCH] stop letting roms read off the end of the cart and crash the emulator. --- desmume/src/MMU.cpp | 8 +++++++- desmume/src/NDSSystem.cpp | 33 +++++++++------------------------ desmume/src/NDSSystem.h | 26 ++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index cf834112f..13dd46b61 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -1333,7 +1333,6 @@ u32 MMU_readFromGC() case 0x00: case 0xB7: { - // TODO: prevent read if the address is out of range // Make sure any reads below 0x8000 redirect to 0x8000+(adr&0x1FF) as on real cart if((card.command[0] == 0xB7) && (card.address < 0x8000)) { @@ -1342,6 +1341,13 @@ u32 MMU_readFromGC() card.address = (0x8000 + (card.address&0x1FF)); } + + if(card.address >= gameInfo.romsize) + { + INFO("Reading beyond end of cart! ... %08X > %08X\n",card.address, gameInfo.romsize); + } + //but, this is actually handled by the cart rom buffer being oversized and full of 0xFF. + //is this a good idea? We think so. val = T1ReadLong(MMU.CART_ROM, card.address & MMU.CART_ROM_MASK); } break; diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 82a7ecd2d..3c59d2bb9 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -195,7 +195,7 @@ NDS_header * NDS_getROMHeader(void) memcpy(header->logo, MMU.CART_ROM + 192, 156); header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348); header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350); - memcpy(header->reserved, MMU.CART_ROM + 352, min(160, gameInfo.romsize - 352)); + memcpy(header->reserved, MMU.CART_ROM + 352, min(160, (int)gameInfo.romsize - 352)); return header; } @@ -345,15 +345,16 @@ static void loadrom(std::string fname) { gameInfo.resize(size); fread(gameInfo.romdata,1,size,inf); + gameInfo.fillGap(); fclose(inf); } int NDS_LoadROM(const char *filename, const char *logicalFilename) { - int type = ROM_NDS; - u32 mask; - char buf[MAX_PATH]; + int type = ROM_NDS; + u32 mask; + char buf[MAX_PATH]; if (filename == NULL) return -1; @@ -388,15 +389,8 @@ int NDS_LoadROM(const char *filename, const char *logicalFilename) if (gameInfo.romsize < 352) { return -1; } + - //zero 25-dec-08 - this used to yield a mask which was 2x large - //mask = size; - mask = gameInfo.romsize-1; - mask |= (mask >>1); - mask |= (mask >>2); - mask |= (mask >>4); - mask |= (mask >>8); - mask |= (mask >>16); //decrypt if necessary.. //but this is untested and suspected to fail on big endian, so lets not support this on big endian @@ -415,7 +409,7 @@ int NDS_LoadROM(const char *filename, const char *logicalFilename) FCEUI_StopMovie(); MMU_unsetRom(); - NDS_SetROM((u8*)gameInfo.romdata, mask); + NDS_SetROM((u8*)gameInfo.romdata, gameInfo.mask); NDS_Reset(); memset(buf, 0, MAX_PATH); @@ -492,15 +486,6 @@ int NDS_LoadROM(const char *filename, const char *logicalFilename) return -1; } - //zero 25-dec-08 - this used to yield a mask which was 2x large - //mask = size; - mask = size-1; - mask |= (mask >>1); - mask |= (mask >>2); - mask |= (mask >>4); - mask |= (mask >>8); - mask |= (mask >>16); - gameInfo.resize(size); // Make sure old ROM is freed first(at least this way we won't be eating @@ -508,7 +493,7 @@ int NDS_LoadROM(const char *filename, const char *logicalFilename) if(MMU.CART_ROM != MMU.UNUSED_RAM) NDS_FreeROM(); - data = new u8[mask + 1]; + data = new u8[gameInfo.mask + 1]; if (!data) { reader->DeInit(file); @@ -534,7 +519,7 @@ int NDS_LoadROM(const char *filename, const char *logicalFilename) if (cheatSearch) cheatSearch->close(); MMU_unsetRom(); - NDS_SetROM(data, mask); + NDS_SetROM(data, gameInfo.mask); NDS_Reset(); free(noext); diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index afcfe1e1e..068429506 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -280,11 +280,31 @@ struct GameInfo { resize(size); memcpy(romdata,buf,size); + romsize = (u32)size; + fillGap(); + } + + void fillGap() + { + memset(romdata+romsize,0xFF,allocatedSize-romsize); } void resize(int size) { if(romdata != NULL) delete[] romdata; - romdata = new char[size]; + + //calculate the necessary mask for the requested size + mask = size-1; + mask |= (mask >>1); + mask |= (mask >>2); + mask |= (mask >>4); + mask |= (mask >>8); + mask |= (mask >>16); + + //now, we actually need to over-allocate, because bytes from anywhere protected by that mask + //could be read from the rom + allocatedSize = mask+1; + + romdata = new char[allocatedSize]; romsize = size; } u32 crc; @@ -294,7 +314,9 @@ struct GameInfo char ROMfullName[7][0x100]; void populate(); char* romdata; - int romsize; + u32 romsize; + u32 allocatedSize; + u32 mask; }; typedef struct TSCalInfo