From a738364416119194ef2ef8b6180fdd8c50da8079 Mon Sep 17 00:00:00 2001 From: rogerman Date: Sun, 15 Nov 2015 06:08:32 +0000 Subject: [PATCH] Cocoa Port: - Fix crash when loading invalid ROM header data. --- desmume/src/NDSSystem.cpp | 60 +++++++++++++++++++++++++++++----- desmume/src/NDSSystem.h | 1 + desmume/src/cocoa/cocoa_rom.h | 2 +- desmume/src/cocoa/cocoa_rom.mm | 46 ++++++++++++++++++-------- 4 files changed, 86 insertions(+), 23 deletions(-) diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 5248f07e4..1ebc8f9e4 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -26,6 +26,7 @@ #include "utils/decrypt/decrypt.h" #include "utils/decrypt/crc.h" +#include "utils/decrypt/header.h" #include "utils/advanscene.h" #include "utils/task.h" @@ -308,6 +309,50 @@ const RomBanner& GameInfo::getRomBanner() return banner; } +bool GameInfo::ValidateHeader() +{ + bool isRomValid = false; + + // Validate the ROM type. + int detectedRomType = DetectRomType(*(Header *)&header, (char *)secureArea); + if (detectedRomType == ROMTYPE_INVALID) + { + printf("ROM Validation: Invalid ROM type detected.\n"); + return isRomValid; + } + + // Ensure that the game title and game code are both clean ASCII, but also + // make an exception for homebrew ROMs, which may not always have clean + // headers to begin with. + if (detectedRomType != ROMTYPE_HOMEBREW) + { + for (size_t i = 0; i < 12; i++) + { + char c = (char)header.gameTile[i]; + if (c < 0 || (c > 0 && c < 32) || c == 127) + { + printf("ROM Validation: Invalid character detected in ROM Title.\n"); + printf(" charIndex = %d, charValue = %d\n", (int)i, c); + return isRomValid; + } + } + + for (size_t i = 0; i < 4; i++) + { + char c = (char)header.gameCode[i]; + if (c < 0 || (c > 0 && c < 32) || c == 127) + { + printf("ROM Validation: Invalid character detected in ROM Game Code.\n"); + printf(" charIndex = %d, charValue = %d\n", (int)i, c); + return isRomValid; + } + } + } + + isRomValid = true; + return isRomValid; +} + void GameInfo::populate() { const char regions_index[] = "JPFSEODIRKHXVWUC"; @@ -656,18 +701,15 @@ int NDS_LoadROM(const char *filename, const char *physicalName, const char *logi if (cheatSearch) cheatSearch->close(); FCEUI_StopMovie(); - - - //check whether this rom is any kind of valid - if(!CheckValidRom((u8*)&gameInfo.header, gameInfo.secureArea)) + + if (!gameInfo.ValidateHeader()) { - printf("Specified file is not a valid rom\n"); - return -1; + ret = -1; + return ret; } - + gameInfo.populate(); - - + if (CommonSettings.loadToMemory) gameInfo.crc = crc32(0, (u8*)gameInfo.romdata, gameInfo.romsize); else diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index d72968850..63ddd55af 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -353,6 +353,7 @@ struct GameInfo bool loadROM(std::string fname, u32 type = ROM_NDS); void closeROM(); u32 readROM(u32 pos); + bool ValidateHeader(); void populate(); bool isDSiEnhanced(); bool isHomebrew(); diff --git a/desmume/src/cocoa/cocoa_rom.h b/desmume/src/cocoa/cocoa_rom.h index a5da30c50..2fe25330e 100644 --- a/desmume/src/cocoa/cocoa_rom.h +++ b/desmume/src/cocoa/cocoa_rom.h @@ -46,7 +46,7 @@ - (id) initWithURL:(NSURL *)theURL; - (id) initWithURL:(NSURL *)theURL saveType:(NSInteger)saveTypeID; - (id) initWithURL:(NSURL *)theURL saveType:(NSInteger)saveTypeID streamLoadData:(BOOL)willStreamLoad; -- (void) initHeader; +- (BOOL) initHeader; - (BOOL) loadData:(NSURL *)theURL; - (void) loadDataOnThread:(id)object; - (NSString *) title; diff --git a/desmume/src/cocoa/cocoa_rom.mm b/desmume/src/cocoa/cocoa_rom.mm index faba71830..08d6914c5 100644 --- a/desmume/src/cocoa/cocoa_rom.mm +++ b/desmume/src/cocoa/cocoa_rom.mm @@ -141,14 +141,16 @@ static NSMutableDictionary *saveTypeValues = nil; return (gameInfo.romdata != NULL); } -- (void) initHeader +- (BOOL) initHeader { + BOOL result = NO; + const NDS_header *ndsRomHeader = NDS_getROMHeader(); const RomBanner &ndsRomBanner = gameInfo.getRomBanner(); - if(self.header == nil || self.bindings == nil) + if (self.header == nil || self.bindings == nil) { - return; + return result; } [self.header setValue:[self banner:ndsRomBanner.titles[0]] forKey:@"bannerJapanese"]; @@ -218,20 +220,33 @@ static NSMutableDictionary *saveTypeValues = nil; NSImage *iconImage = [self icon]; if (iconImage != nil) { - [header setObject:iconImage forKey:@"iconImage"]; + [self.header setObject:iconImage forKey:@"iconImage"]; [self.bindings setObject:(NSImage *)[self.header objectForKey:@"iconImage"] forKey:@"iconImage"]; } - [self.header setValue:[self internalName] forKey:@"romInternalName"]; - [self.header setValue:[self serial] forKey:@"romSerial"]; + NSString *internalNameString = [self internalName]; + NSString *serialString = [self serial]; - [self.bindings setValue:[self.header objectForKey:@"romInternalName"] forKey:@"romInternalName"]; - [self.bindings setValue:[self.header objectForKey:@"romSerial"] forKey:@"romSerial"]; + if (internalNameString == nil || serialString == nil) + { + return result; + } + else + { + [self.header setValue:internalNameString forKey:@"romInternalName"]; + [self.header setValue:serialString forKey:@"romSerial"]; + + [self.bindings setValue:[self.header objectForKey:@"romInternalName"] forKey:@"romInternalName"]; + [self.bindings setValue:[self.header objectForKey:@"romSerial"] forKey:@"romSerial"]; + + NSString *romNameAndSerialInfoString = @"Name: "; + romNameAndSerialInfoString = [romNameAndSerialInfoString stringByAppendingString:[self.header objectForKey:@"romInternalName"]]; + romNameAndSerialInfoString = [[romNameAndSerialInfoString stringByAppendingString:@"\nSerial: "] stringByAppendingString:[self.header objectForKey:@"romSerial"]]; + [self.bindings setValue:romNameAndSerialInfoString forKey:@"romNameAndSerialInfo"]; + } - NSString *romNameAndSerialInfoString = @"Name: "; - romNameAndSerialInfoString = [romNameAndSerialInfoString stringByAppendingString:[self.header objectForKey:@"romInternalName"]]; - romNameAndSerialInfoString = [[romNameAndSerialInfoString stringByAppendingString:@"\nSerial: "] stringByAppendingString:[self.header objectForKey:@"romSerial"]]; - [self.bindings setValue:romNameAndSerialInfoString forKey:@"romNameAndSerialInfo"]; + result = YES; + return result; } - (BOOL) loadData:(NSURL *)theURL @@ -239,6 +254,12 @@ static NSMutableDictionary *saveTypeValues = nil; [CocoaDSRom changeRomSaveType:saveType]; BOOL result = [CocoaDSFile loadRom:theURL]; + + if (result) + { + result = [self initHeader]; + } + if (!result) { NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:NO], @"DidLoad", nil]; @@ -248,7 +269,6 @@ static NSMutableDictionary *saveTypeValues = nil; } fileURL = [theURL copy]; - [self initHeader]; NSString *advscDBPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"Advanscene_DatabasePath"]; if (advscDBPath != nil)