Merge pull request #1015 from Azaezel/alpha41/consoleCleanups

fix warn reports for buffer over-runs
This commit is contained in:
Brian Roberts 2023-05-09 14:44:01 -05:00 committed by GitHub
commit 0d981b62cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 93 additions and 74 deletions

View file

@ -309,7 +309,7 @@ void CodeBlock::calcBreakList()
if (seqCount) if (seqCount)
size++; size++;
breakList = new U32[size]; breakList = new U32[size+3]; //lineBreakPairs plus pad
breakListSize = size; breakListSize = size;
line = -1; line = -1;
seqCount = 0; seqCount = 0;
@ -434,7 +434,7 @@ bool CodeBlock::read(StringTableEntry fileName, Stream &st)
st.read(&lineBreakPairCount); st.read(&lineBreakPairCount);
U32 totSize = codeLength + lineBreakPairCount * 2; U32 totSize = codeLength + lineBreakPairCount * 2;
code = new U32[totSize]; code = new U32[totSize+1];
// 0xFF is used as a flag to help compress the bytecode. // 0xFF is used as a flag to help compress the bytecode.
// If detected, the bytecode is only a U8. // If detected, the bytecode is only a U8.
@ -1301,6 +1301,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
case FuncCallExprNode::MethodCall: callTypeName = "MethodCall"; break; case FuncCallExprNode::MethodCall: callTypeName = "MethodCall"; break;
case FuncCallExprNode::ParentCall: callTypeName = "ParentCall"; break; case FuncCallExprNode::ParentCall: callTypeName = "ParentCall"; break;
case FuncCallExprNode::StaticCall: callTypeName = "StaticCall"; break; case FuncCallExprNode::StaticCall: callTypeName = "StaticCall"; break;
default: callTypeName = "INVALID"; break;
} }
Con::printf("%i: OP_CALLFUNC stk=+1 name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, callTypeName); Con::printf("%i: OP_CALLFUNC stk=+1 name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, callTypeName);

View file

@ -116,9 +116,6 @@ U32 _ITER = 0; ///< Stack pointer for iterStack.
ConsoleValue stack[MaxStackSize]; ConsoleValue stack[MaxStackSize];
S32 _STK = 0; S32 _STK = 0;
char curFieldArray[256];
char prevFieldArray[256];
const char* tsconcat(const char* strA, const char* strB, S32& outputLen) const char* tsconcat(const char* strA, const char* strB, S32& outputLen)
{ {
S32 lenA = dStrlen(strA); S32 lenA = dStrlen(strA);
@ -726,7 +723,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
struct { struct {
SimObject* newObject; SimObject* newObject;
U32 failJump; U32 failJump;
} objectCreationStack[objectCreationStackSize]; } objectCreationStack[objectCreationStackSize] = {};
SimObject* currentNewObject = 0; SimObject* currentNewObject = 0;
StringTableEntry prevField = NULL; StringTableEntry prevField = NULL;
@ -2349,7 +2346,7 @@ execFinished:
AssertFatal(!(_STK < stackStart), "String stack popped too much in script exec"); AssertFatal(!(_STK < stackStart), "String stack popped too much in script exec");
#endif #endif
return std::move(returnValue); return returnValue;
} }
//------------------------------------------------------------ //------------------------------------------------------------

View file

@ -91,7 +91,7 @@ static const char * prependDollar ( const char * name )
{ {
if(name[0] != '$') if(name[0] != '$')
{ {
S32 len = dStrlen(name); U64 len = dStrlen(name);
AssertFatal(len < sizeof(scratchBuffer)-2, "CONSOLE: name too long"); AssertFatal(len < sizeof(scratchBuffer)-2, "CONSOLE: name too long");
scratchBuffer[0] = '$'; scratchBuffer[0] = '$';
dMemcpy(scratchBuffer + 1, name, len + 1); dMemcpy(scratchBuffer + 1, name, len + 1);
@ -104,7 +104,7 @@ static const char * prependPercent ( const char * name )
{ {
if(name[0] != '%') if(name[0] != '%')
{ {
S32 len = dStrlen(name); U64 len = dStrlen(name);
AssertFatal(len < sizeof(scratchBuffer)-2, "CONSOLE: name too long"); AssertFatal(len < sizeof(scratchBuffer)-2, "CONSOLE: name too long");
scratchBuffer[0] = '%'; scratchBuffer[0] = '%';
dMemcpy(scratchBuffer + 1, name, len + 1); dMemcpy(scratchBuffer + 1, name, len + 1);
@ -504,7 +504,7 @@ U32 tabComplete(char* inputBuffer, U32 cursorPos, U32 maxResultLength, bool forw
} }
// Find the object identifier. // Find the object identifier.
S32 objLast = --p; U64 objLast = --p;
while ((p > 0) && (inputBuffer[p - 1] != ' ') && (inputBuffer[p - 1] != '(')) while ((p > 0) && (inputBuffer[p - 1] != ' ') && (inputBuffer[p - 1] != '('))
{ {
p--; p--;
@ -646,7 +646,7 @@ static void _printf(ConsoleLogEntry::Level level, ConsoleLogEntry::Type type, co
return; return;
Con::active = false; Con::active = false;
char buffer[8192]; char buffer[8192] = {};
U32 offset = 0; U32 offset = 0;
if( gEvalState.traceOn && gEvalState.getStackDepth() > 0 ) if( gEvalState.traceOn && gEvalState.getStackDepth() > 0 )
{ {
@ -703,7 +703,7 @@ static void _printf(ConsoleLogEntry::Level level, ConsoleLogEntry::Type type, co
entry.mLevel = level; entry.mLevel = level;
entry.mType = type; entry.mType = type;
#ifndef TORQUE_SHIPPING // this is equivalent to a memory leak, turn it off in ship build #ifndef TORQUE_SHIPPING // this is equivalent to a memory leak, turn it off in ship build
dsize_t logStringLen = dStrlen(pos) + 1; U64 logStringLen = dStrlen(pos) + 1;
entry.mString = (const char *)consoleLogChunker.alloc(logStringLen); entry.mString = (const char *)consoleLogChunker.alloc(logStringLen);
dStrcpy(const_cast<char*>(entry.mString), pos, logStringLen); dStrcpy(const_cast<char*>(entry.mString), pos, logStringLen);
@ -776,7 +776,7 @@ bool getVariableObjectField(const char *name, SimObject **object, const char **f
const char *dot = dStrchr(name, '.'); const char *dot = dStrchr(name, '.');
if(name[0] != '$' && dot) if(name[0] != '$' && dot)
{ {
S32 len = dStrlen(name); U64 len = dStrlen(name);
AssertFatal(len < sizeof(scratchBuffer)-1, "Sim::getVariable - name too long"); AssertFatal(len < sizeof(scratchBuffer)-1, "Sim::getVariable - name too long");
dMemcpy(scratchBuffer, name, len+1); dMemcpy(scratchBuffer, name, len+1);
@ -978,7 +978,7 @@ const char *getObjectTokenField(const char *name)
const char *dot = dStrchr(name, '.'); const char *dot = dStrchr(name, '.');
if(name[0] != '$' && dot) if(name[0] != '$' && dot)
{ {
S32 len = dStrlen(name); U64 len = dStrlen(name);
AssertFatal(len < sizeof(scratchBuffer)-1, "Sim::getVariable - object name too long"); AssertFatal(len < sizeof(scratchBuffer)-1, "Sim::getVariable - object name too long");
dMemcpy(scratchBuffer, name, len+1); dMemcpy(scratchBuffer, name, len+1);
@ -1549,22 +1549,27 @@ ConsoleValue evaluatef(const char* string, ...)
ConsoleValue _internalExecute(S32 argc, ConsoleValue argv[]) ConsoleValue _internalExecute(S32 argc, ConsoleValue argv[])
{ {
StringTableEntry funcName = StringTable->insert(argv[0].getString()); StringTableEntry funcName = StringTable->insert(argv[0].getString());
if (argc > 1)
{
const char** argv_str = static_cast<const char**>(malloc(size_t(argc) * sizeof(char*)));
if (argv_str)
{
for (int i = 0; i < argc - 1; i++)
{
argv_str[i] = argv[i + 1].getString();
}
}
bool result;
const char* methodRes = CInterface::CallFunction(NULL, funcName, argv_str, argc - 1, &result);
const char** argv_str = static_cast<const char**>(malloc((argc - 1) * sizeof(char *))); free(argv_str);
for (int i = 0; i < argc - 1; i++) if (result)
{ {
argv_str[i] = argv[i + 1].getString(); ConsoleValue ret;
ret.setString(methodRes);
return ret;
}
} }
bool result;
const char* methodRes = CInterface::CallFunction(NULL, funcName, argv_str, argc - 1, &result);
free(argv_str);
if (result)
{
ConsoleValue ret;
ret.setString(methodRes);
return std::move(ret);
}
Namespace::Entry *ent; Namespace::Entry *ent;
ent = Namespace::global()->lookup(funcName); ent = Namespace::global()->lookup(funcName);
@ -1615,6 +1620,9 @@ ConsoleValue execute(S32 argc, const char *argv[])
// Internal execute for object method which does not save the stack // Internal execute for object method which does not save the stack
static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly) static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly)
{ {
if (object == NULL)
return std::move(ConsoleValue());
if(argc < 2) if(argc < 2)
{ {
STR.clearFunctionOffset(); STR.clearFunctionOffset();
@ -1636,22 +1644,27 @@ static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue a
} }
StringTableEntry funcName = StringTable->insert(argv[0].getString()); StringTableEntry funcName = StringTable->insert(argv[0].getString());
if (argc > 2)
const char** argv_str = static_cast<const char**>(malloc((argc - 2) * sizeof(char *)));
for (int i = 0; i < argc - 2; i++)
{ {
argv_str[i] = argv[i + 2].getString(); const char** argv_str = static_cast<const char**>(malloc(size_t(argc - 1) * sizeof(char*)));
} if (argv_str)
bool result; {
const char* methodRes = CInterface::CallMethod(object, funcName, argv_str, argc - 2, &result); for (int i = 0; i < argc - 2; i++)
{
argv_str[i] = argv[i + 2].getString();
}
}
bool result;
const char* methodRes = CInterface::CallMethod(object, funcName, argv_str, argc - 2, &result);
free(argv_str); free(argv_str);
if (result) if (result)
{ {
ConsoleValue val; ConsoleValue val;
val.setString(methodRes); val.setString(methodRes);
return val; return val;
}
} }
if(object->getNamespace()) if(object->getNamespace())
@ -1898,7 +1911,7 @@ StringTableEntry getModNameFromPath(const char *path)
if(path == NULL || *path == 0) if(path == NULL || *path == 0)
return NULL; return NULL;
char buf[1024]; char buf[1024] = {};
buf[0] = 0; buf[0] = 0;
if(path[0] == '/' || path[1] == ':') if(path[0] == '/' || path[1] == ':')
@ -2145,7 +2158,7 @@ StringTableEntry getPathExpandoValue(U32 expandoIndex)
bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWorkingDirectoryHint, const bool ensureTrailingSlash) bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWorkingDirectoryHint, const bool ensureTrailingSlash)
{ {
char pathBuffer[2048]; char pathBuffer[2048] = {};
const char* pSrc = pSrcPath; const char* pSrc = pSrcPath;
char* pSlash; char* pSlash;
@ -2604,7 +2617,7 @@ ConsoleValue _BaseEngineConsoleCallbackHelper::_exec()
{ {
ConsoleValue returnValue = Con::_internalExecute( mThis, mArgc, mArgv, false ); ConsoleValue returnValue = Con::_internalExecute( mThis, mArgc, mArgv, false );
mArgc = mInitialArgc; // reset mArgc = mInitialArgc; // reset
return std::move(returnValue); return returnValue;
} }
STR.clearFunctionOffset(); STR.clearFunctionOffset();
@ -2614,7 +2627,7 @@ ConsoleValue _BaseEngineConsoleCallbackHelper::_exec()
ConsoleValue returnValue = std::move(Con::_internalExecute( mArgc, mArgv )); ConsoleValue returnValue = std::move(Con::_internalExecute( mArgc, mArgv ));
mArgc = mInitialArgc; // reset args mArgc = mInitialArgc; // reset args
return std::move(returnValue); return returnValue;
} }
ConsoleValue _BaseEngineConsoleCallbackHelper::_execLater(SimConsoleThreadExecEvent *evt) ConsoleValue _BaseEngineConsoleCallbackHelper::_execLater(SimConsoleThreadExecEvent *evt)

View file

@ -146,7 +146,7 @@ bool isFloat(const char* str, bool sciOk = false)
} }
break; break;
case '.': case '.':
if(seenDot | (sciOk && eLoc != -1)) if(seenDot || (sciOk && eLoc != -1))
return false; return false;
seenDot = true; seenDot = true;
break; break;
@ -562,7 +562,7 @@ DefineEngineFunction( stripChars, const char*, ( const char* str, const char* ch
"@endtsexample\n" "@endtsexample\n"
"@ingroup Strings" ) "@ingroup Strings" )
{ {
S32 len = dStrlen(str) + 1; U64 len = dStrlen(str) + 1;
char* ret = Con::getReturnBuffer( len ); char* ret = Con::getReturnBuffer( len );
dStrcpy( ret, str, len ); dStrcpy( ret, str, len );
U32 pos = dStrcspn( ret, chars ); U32 pos = dStrcspn( ret, chars );
@ -599,11 +599,11 @@ DefineEngineFunction(sanitizeString, const char*, (const char* str), ,
char* ret = Con::getReturnBuffer(len); char* ret = Con::getReturnBuffer(len);
dStrcpy(ret, processedString.c_str(), len); dStrcpy(ret, processedString.c_str(), len);
U32 pos = dStrcspn(ret, "-+*/%$&<EFBFBD>=()[].?\\\"#,;!~<>|<EFBFBD>^{}"); U64 pos = dStrcspn(ret, "-+*/%$&=:()[].?\\\"#,;!~<>|^{}");
while (pos < dStrlen(ret)) while (pos < dStrlen(ret))
{ {
dStrcpy(ret + pos, ret + pos + 1, len - pos); dStrcpy(ret + pos, ret + pos + 1, len - pos);
pos = dStrcspn(ret, "-+*/%$&<EFBFBD>=()[].?\\\"#,;!~<>|<EFBFBD>^{}"); pos = dStrcspn(ret, "-+*/%$&=:()[].?\\\"#,;!~<>|^{}");
} }
return(ret); return(ret);
} }
@ -620,7 +620,7 @@ DefineEngineFunction( strlwr, const char*, ( const char* str ),,
"@see strupr\n" "@see strupr\n"
"@ingroup Strings" ) "@ingroup Strings" )
{ {
dsize_t retLen = dStrlen(str) + 1; U64 retLen = dStrlen(str) + 1;
char *ret = Con::getReturnBuffer(retLen); char *ret = Con::getReturnBuffer(retLen);
dStrcpy(ret, str, retLen); dStrcpy(ret, str, retLen);
return dStrlwr(ret); return dStrlwr(ret);
@ -638,7 +638,7 @@ DefineEngineFunction( strupr, const char*, ( const char* str ),,
"@see strlwr\n" "@see strlwr\n"
"@ingroup Strings" ) "@ingroup Strings" )
{ {
dsize_t retLen = dStrlen(str) + 1; U64 retLen = dStrlen(str) + 1;
char *ret = Con::getReturnBuffer(retLen); char *ret = Con::getReturnBuffer(retLen);
dStrcpy(ret, str, retLen); dStrcpy(ret, str, retLen);
return dStrupr(ret); return dStrupr(ret);
@ -701,7 +701,7 @@ DefineEngineFunction( strreplace, const char*, ( const char* source, const char*
count++; count++;
} }
} }
S32 retLen = dStrlen(source) + 1 + (toLen - fromLen) * count; U64 retLen = dStrlen(source) + 1 + U64(toLen - fromLen) * count;
char *ret = Con::getReturnBuffer(retLen); char *ret = Con::getReturnBuffer(retLen);
U32 scanp = 0; U32 scanp = 0;
U32 dstp = 0; U32 dstp = 0;
@ -714,7 +714,7 @@ DefineEngineFunction( strreplace, const char*, ( const char* source, const char*
return ret; return ret;
} }
U32 len = subScan - (source + scanp); U32 len = subScan - (source + scanp);
dStrncpy(ret + dstp, source + scanp, getMin(len, retLen - dstp)); dStrncpy(ret + dstp, source + scanp, (U64)getMin(len, retLen - dstp));
dstp += len; dstp += len;
dStrcpy(ret + dstp, to, retLen - dstp); dStrcpy(ret + dstp, to, retLen - dstp);
dstp += toLen; dstp += toLen;
@ -940,8 +940,8 @@ DefineEngineFunction( startsWith, bool, ( const char* str, const char* prefix, b
char* targetBuf = new char[ targetLen + 1 ]; char* targetBuf = new char[ targetLen + 1 ];
// copy src and target into buffers // copy src and target into buffers
dStrcpy( srcBuf, str, srcLen + 1 ); dStrcpy( srcBuf, str, (U64)(srcLen + 1) );
dStrcpy( targetBuf, prefix, targetLen + 1 ); dStrcpy( targetBuf, prefix, (U64)(targetLen + 1) );
// reassign src/target pointers to lowercase versions // reassign src/target pointers to lowercase versions
str = dStrlwr( srcBuf ); str = dStrlwr( srcBuf );
@ -991,8 +991,8 @@ DefineEngineFunction( endsWith, bool, ( const char* str, const char* suffix, boo
char* targetBuf = new char[ targetLen + 1 ]; char* targetBuf = new char[ targetLen + 1 ];
// copy src and target into buffers // copy src and target into buffers
dStrcpy( srcBuf, str, srcLen + 1 ); dStrcpy( srcBuf, str, (U64)(srcLen + 1) );
dStrcpy( targetBuf, suffix, targetLen + 1 ); dStrcpy( targetBuf, suffix, (U64)(targetLen + 1 ));
// reassign src/target pointers to lowercase versions // reassign src/target pointers to lowercase versions
str = dStrlwr( srcBuf ); str = dStrlwr( srcBuf );
@ -1858,7 +1858,7 @@ DefineEngineFunction( detag, const char*, ( const char* str ),,
if( word == NULL ) if( word == NULL )
return ""; return "";
dsize_t retLen = dStrlen(word + 1) + 1; U64 retLen = dStrlen(word + 1) + 1;
char* ret = Con::getReturnBuffer(retLen); char* ret = Con::getReturnBuffer(retLen);
dStrcpy( ret, word + 1, retLen ); dStrcpy( ret, word + 1, retLen );
return ret; return ret;
@ -1924,7 +1924,7 @@ DefineEngineStringlyVariadicFunction( echo, void, 2, 0, "( string message... ) "
char *ret = Con::getReturnBuffer(len + 1); char *ret = Con::getReturnBuffer(len + 1);
ret[0] = 0; ret[0] = 0;
for(i = 1; i < argc; i++) for(i = 1; i < argc; i++)
dStrcat(ret, argv[i], len + 1); dStrcat(ret, argv[i], (U64)(len + 1));
Con::printf("%s", ret); Con::printf("%s", ret);
ret[0] = 0; ret[0] = 0;
@ -1948,7 +1948,7 @@ DefineEngineStringlyVariadicFunction( warn, void, 2, 0, "( string message... ) "
char *ret = Con::getReturnBuffer(len + 1); char *ret = Con::getReturnBuffer(len + 1);
ret[0] = 0; ret[0] = 0;
for(i = 1; i < argc; i++) for(i = 1; i < argc; i++)
dStrcat(ret, argv[i], len + 1); dStrcat(ret, argv[i], (U64)(len + 1));
Con::warnf(ConsoleLogEntry::General, "%s", ret); Con::warnf(ConsoleLogEntry::General, "%s", ret);
ret[0] = 0; ret[0] = 0;
@ -1972,7 +1972,7 @@ DefineEngineStringlyVariadicFunction( error, void, 2, 0, "( string message... )
char *ret = Con::getReturnBuffer(len + 1); char *ret = Con::getReturnBuffer(len + 1);
ret[0] = 0; ret[0] = 0;
for(i = 1; i < argc; i++) for(i = 1; i < argc; i++)
dStrcat(ret, argv[i], len + 1); dStrcat(ret, argv[i], (U64)(len + 1));
Con::errorf(ConsoleLogEntry::General, "%s", ret); Con::errorf(ConsoleLogEntry::General, "%s", ret);
ret[0] = 0; ret[0] = 0;
@ -2517,7 +2517,7 @@ DefineEngineFunction( isDefined, bool, ( const char* varName, const char* varVal
S32 len = dStrlen(name); S32 len = dStrlen(name);
AssertFatal(len < sizeof(scratchBuffer)-1, "isDefined() - name too long"); AssertFatal(len < sizeof(scratchBuffer)-1, "isDefined() - name too long");
dMemcpy(scratchBuffer, name, len+1); dMemcpy(scratchBuffer, name, (U64)(len+1));
char * token = dStrtok(scratchBuffer, "."); char * token = dStrtok(scratchBuffer, ".");

View file

@ -476,6 +476,8 @@ Dictionary::Entry::Entry(StringTableEntry in_name)
fval = 0; fval = 0;
sval = NULL; sval = NULL;
bufferLen = 0; bufferLen = 0;
dataPtr = NULL;
enumTable = NULL;
} }
Dictionary::Entry::~Entry() Dictionary::Entry::~Entry()
@ -809,6 +811,7 @@ ExprEvalState::ExprEvalState()
mShouldReset = false; mShouldReset = false;
mResetLocked = false; mResetLocked = false;
copyVariable = NULL; copyVariable = NULL;
currentRegisterArray = NULL;
} }
ExprEvalState::~ExprEvalState() ExprEvalState::~ExprEvalState()

View file

@ -359,6 +359,8 @@ public:
fval = 0; fval = 0;
sval = NULL; sval = NULL;
bufferLen = 0; bufferLen = 0;
dataPtr = NULL;
enumTable = NULL;
} }
Entry(StringTableEntry name); Entry(StringTableEntry name);

View file

@ -682,7 +682,7 @@ public:
T::initPersistFields(); T::initPersistFields();
T::consoleInit(); T::consoleInit();
EnginePropertyTable::Property* props = new EnginePropertyTable::Property[sg_tempFieldList.size()]; EnginePropertyTable::Property* props = new EnginePropertyTable::Property[sg_tempFieldList.size() + 1];
for (int i = 0; i < sg_tempFieldList.size(); ++i) for (int i = 0; i < sg_tempFieldList.size(); ++i)
{ {
@ -825,7 +825,7 @@ class ConsoleObject : public EngineObject
protected: protected:
/// @deprecated This is disallowed. /// @deprecated This is disallowed.
ConsoleObject(const ConsoleObject&); ConsoleObject(const ConsoleObject&) { mDocsClick = false; };
public: public:
/// <summary> /// <summary>
@ -863,7 +863,7 @@ public:
public: public:
/// Get the classname from a class tag. /// Get the classname from a class tag.
static const char* lookupClassName(const U32 in_classTag); static const char* lookupClassName(const U32 in_classTag) { return ""; };
/// @name Fields /// @name Fields
/// @{ /// @{

View file

@ -166,7 +166,7 @@ class EngineExportScope : public EngineExport
private: private:
/// Constructor for the global scope. /// Constructor for the global scope.
EngineExportScope(){} EngineExportScope():mExports(nullptr){}
}; };

View file

@ -890,6 +890,7 @@ DefineEngineMethod( SimSet, listObjects, void, (),,
for(itr = object->begin(); itr != object->end(); itr++) for(itr = object->begin(); itr != object->end(); itr++)
{ {
SimObject *obj = *itr; SimObject *obj = *itr;
if (obj == nullptr) continue;
bool isSet = dynamic_cast<SimSet *>(obj) != 0; bool isSet = dynamic_cast<SimSet *>(obj) != 0;
const char *name = obj->getName(); const char *name = obj->getName();
if(name) if(name)

View file

@ -352,8 +352,8 @@ class Journal
template<typename T> template<typename T>
struct MethodRep: public FuncDecl { struct MethodRep: public FuncDecl {
typename T::ObjPtr obj; typename T::ObjPtr obj = NULL;
typename T::MethodPtr method; typename T::MethodPtr method = NULL;
virtual bool match(VoidPtr ptr,VoidMethod func) const { virtual bool match(VoidPtr ptr,VoidMethod func) const {
return obj == (typename T::ObjPtr)ptr && method == (typename T::MethodPtr)func; return obj == (typename T::ObjPtr)ptr && method == (typename T::MethodPtr)func;
} }

View file

@ -644,18 +644,20 @@ ImplementEnumType(_TamlFormatMode,
// Fetch field count. // Fetch field count.
const U32 fieldCount = fieldList.size(); const U32 fieldCount = fieldList.size();
ConsoleObject* defaultConObject; ConsoleObject* defaultConObject = NULL;
SimObject* defaultObject; SimObject* defaultObject = NULL;
if (!getWriteDefaults()) if (!getWriteDefaults())
{ {
// Create a default object of the same type // Create a default object of the same type
defaultConObject = ConsoleObject::create(pSimObject->getClassName()); defaultConObject = ConsoleObject::create(pSimObject->getClassName());
if (!defaultConObject)
return;
defaultObject = dynamic_cast<SimObject*>(defaultConObject); defaultObject = dynamic_cast<SimObject*>(defaultConObject);
// ***Really*** shouldn't happen
if (!defaultObject)
return;
} }
// ***Really*** shouldn't happen
if (!defaultConObject || !defaultObject)
return;
// Iterate fields. // Iterate fields.
U8 arrayDepth = 0; U8 arrayDepth = 0;
@ -754,7 +756,7 @@ ImplementEnumType(_TamlFormatMode,
} }
// Save field/value. // Save field/value.
if (arrayDepth > 0 || pField->elementCount > 1) if (currentArrayNode && (arrayDepth > 0 || pField->elementCount > 1))
currentArrayNode->getChildren()[elementIndex]->addField(fieldName, pFieldValue); currentArrayNode->getChildren()[elementIndex]->addField(fieldName, pFieldValue);
else else
{ {