Sanity checks for the .bhv system (#293)

* Barebones fix.

* Sanity checks for the .bhv system.

* Two more sanity checks.
This commit is contained in:
Prince Frizzy 2023-02-22 15:12:09 -05:00 committed by GitHub
parent 463c92b774
commit 5e95fb14f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 12 deletions

View File

@ -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) {

View File

@ -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<BehaviorScript> *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<BehaviorScript> *_Node = New<DataNode<BehaviorScript>>();
// Name
@ -2500,12 +2509,19 @@ static DataNode<BehaviorScript> *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<u32>();
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);
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;
}
// Skip the rest of the bytes saved for this behavior.
aFile->Skip(dataSize);
// 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<u32>();
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<BehaviorScript> *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat
_Node->mSize = dataSize;
_Node->mData = New<BehaviorScript>(_Node->mSize);
// Add it
if (aGfxData != NULL) {
aGfxData->mBehaviorScripts.Add(_Node);
}
// Read it
for (u32 i = 0; i != _Node->mSize; ++i) {
if (aFile->EoF()) {
@ -2536,6 +2547,11 @@ static DataNode<BehaviorScript> *DynOS_Bhv_Load(BinFile *aFile, GfxData *aGfxDat
}
}
// Add it
if (aGfxData != NULL) {
aGfxData->mBehaviorScripts.Add(_Node);
}
return _Node;
}

View File

@ -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) {