diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index 97072fdc..ccbbf46f 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -89,6 +89,7 @@ public: inline s32 Offset() const { return mOffset; } inline bool EoF() const { return mOffset >= mSize; } inline void SetOffset(s32 aOffset) const { mOffset = aOffset; } + inline const char *GetFilename() const { return mFilename; } public: static BinFile *OpenR(const char *aFilename) { diff --git a/data/dynos_bin_behavior.cpp b/data/dynos_bin_behavior.cpp index 0d8b8454..a93d283f 100644 --- a/data/dynos_bin_behavior.cpp +++ b/data/dynos_bin_behavior.cpp @@ -44,7 +44,7 @@ extern "C" { // Current Behavior Version #define BEHAVIOR_MAJOR_VER 1 #define BEHAVIOR_MINOR_VER 0 -#define BEHAVIOR_PATCH_VER 0 +#define BEHAVIOR_PATCH_VER 1 // Minimum Behavior Version (That can be read) #define BEHAVIOR_MIN_MAJOR_VER 1 @@ -2485,6 +2485,15 @@ static bool DynOS_Bhv_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxD ///////////// static DataNode *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxData) { + // Sanity check the files size. The minimum valid size is 9 bytes. + // 1 byte for the type, 1 bytes for the name length, 3 bytes for the version, And 4 bytes for the behaviors size. + if (aFile->Size() < 9) { + PrintError(" ERROR: Behavior file is smaller then it should be, Rejecting '%s'.", aFile->GetFilename()); + // We have nothing to return, So return NULL. + return NULL; + } + + // Allocate our node. DataNode *_Node = New>(); // Name @@ -2500,12 +2509,19 @@ static DataNode *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat // If the major version doesn't match, then a drasitc change has happened and // we can't read it no matter what. If it's just minor or patch. We might have // code to support it. - u32 dataSize = aFile->Read(); if (majorVersion != BEHAVIOR_MIN_MAJOR_VER || (minorVersion < BEHAVIOR_MIN_MINOR_VER || patchVersion < BEHAVIOR_MIN_PATCH_VER)) { - PrintError(" ERROR: Behavior version is %u.%u.%u, but reading behaviors under %u.%u.%u is not supported!", majorVersion, minorVersion, patchVersion, BEHAVIOR_MIN_MAJOR_VER, BEHAVIOR_MIN_MINOR_VER, BEHAVIOR_MIN_PATCH_VER); - - // Skip the rest of the bytes saved for this behavior. - aFile->Skip(dataSize); + PrintError(" ERROR: Behavior file is version %u.%u.%u, which is not supported! Rejecting '%s'.", majorVersion, minorVersion, patchVersion, aFile->GetFilename()); + // We don't return this since we failed to read the behavior. + Delete(_Node); + // We have nothing to return, So return NULL. + return NULL; + } + + // If we have nothing in the .bhv file, It compiled incorrectly or is maliciously crafted. + // We also check if the specified behavior size is valid for the file. + u32 dataSize = aFile->Read(); + if (dataSize == 0 || (dataSize > (aFile->Size() - aFile->Offset()))) { + PrintError(" ERROR: Behavior file has a invalid behavior in it! Rejecting '%s'.", aFile->GetFilename()); // We don't return this since we failed to read the behavior. Delete(_Node); // We have nothing to return, So return NULL. @@ -2516,11 +2532,6 @@ static DataNode *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat _Node->mSize = dataSize; _Node->mData = New(_Node->mSize); - // Add it - if (aGfxData != NULL) { - aGfxData->mBehaviorScripts.Add(_Node); - } - // Read it for (u32 i = 0; i != _Node->mSize; ++i) { if (aFile->EoF()) { @@ -2535,6 +2546,11 @@ static DataNode *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat _Node->mData[i] = (uintptr_t) _Value; } } + + // Add it + if (aGfxData != NULL) { + aGfxData->mBehaviorScripts.Add(_Node); + } return _Node; } diff --git a/data/dynos_mgr_bhv.cpp b/data/dynos_mgr_bhv.cpp index 3ea85784..061c864d 100644 --- a/data/dynos_mgr_bhv.cpp +++ b/data/dynos_mgr_bhv.cpp @@ -54,6 +54,7 @@ GfxData *DynOS_Bhv_GetActiveGfx(BehaviorScript *bhvScript) { for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) { auto &gfxData = _CustomBehaviorScripts[i].second; auto &scripts = gfxData->mBehaviorScripts; + if (scripts.Count() == 0) { continue; } if (bhvScript == scripts[scripts.Count() - 1]->mData) { return gfxData; } @@ -67,6 +68,7 @@ s32 DynOS_Bhv_GetActiveModIndex(BehaviorScript *bhvScript) { for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) { auto &gfxData = _CustomBehaviorScripts[i].second; auto &scripts = gfxData->mBehaviorScripts; + if (scripts.Count() == 0) { continue; } if (bhvScript == scripts[scripts.Count() - 1]->mData) { return gfxData->mModIndex; } @@ -96,7 +98,10 @@ void DynOS_Bhv_HookAllCustomBehaviors() { for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) { auto &scriptName = _CustomBehaviorScripts[i].first; auto &aGfxData = _CustomBehaviorScripts[i].second; - auto &script = aGfxData->mBehaviorScripts[aGfxData->mBehaviorScripts.Count() - 1]->mData; + if (aGfxData->mBehaviorScripts.Count() == 0) { continue; } + auto *node = aGfxData->mBehaviorScripts[aGfxData->mBehaviorScripts.Count() - 1]; + if (node == nullptr) { continue; } + auto &script = node->mData; // Theres currently no better place but to do this here. if (smlua_hook_custom_bhv(script, scriptName) == 0) {