mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-03 20:40:35 +00:00
Fix corruption issue with string iterator was using an absolute pointer. Also adds a special relative pointer type for constructed strings on the stack.
This commit is contained in:
parent
97ab694af8
commit
942c7a48f4
7 changed files with 151 additions and 29 deletions
|
|
@ -87,7 +87,7 @@ struct IterStackRecord
|
|||
struct StringPos
|
||||
{
|
||||
/// The raw string data on the string stack.
|
||||
const char* mString;
|
||||
StringStackPtr mString;
|
||||
|
||||
/// Current parsing position.
|
||||
U32 mIndex;
|
||||
|
|
@ -288,6 +288,12 @@ inline void ExprEvalState::setStringVariable(const char *val)
|
|||
currentVariable->setStringValue(val);
|
||||
}
|
||||
|
||||
inline void ExprEvalState::setStringStackPtrVariable(StringStackPtr str)
|
||||
{
|
||||
AssertFatal(currentVariable != NULL, "Invalid evaluator state - trying to set null variable!");
|
||||
currentVariable->setStringStackPtrValue(str);
|
||||
}
|
||||
|
||||
inline void ExprEvalState::setCopyVariable()
|
||||
{
|
||||
if (copyVariable)
|
||||
|
|
@ -493,15 +499,25 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi
|
|||
|
||||
ConsoleValueRef ref = argv[i+1];
|
||||
|
||||
if (argv[i+1].isString())
|
||||
gEvalState.setStringVariable(argv[i+1]);
|
||||
else if (argv[i+1].isInt())
|
||||
switch(argv[i+1].getType())
|
||||
{
|
||||
case ConsoleValue::TypeInternalInt:
|
||||
gEvalState.setIntVariable(argv[i+1]);
|
||||
else if (argv[i+1].isFloat())
|
||||
break;
|
||||
case ConsoleValue::TypeInternalFloat:
|
||||
gEvalState.setFloatVariable(argv[i+1]);
|
||||
else
|
||||
break;
|
||||
case ConsoleValue::TypeInternalStringStackPtr:
|
||||
gEvalState.setStringStackPtrVariable(argv[i+1].getStringStackPtrValue());
|
||||
break;
|
||||
case ConsoleValue::TypeInternalStackString:
|
||||
case ConsoleValue::TypeInternalString:
|
||||
default:
|
||||
gEvalState.setStringVariable(argv[i+1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ip = ip + (fnArgc * 2) + (2 + 6 + 1);
|
||||
curFloatTable = functionFloats;
|
||||
curStringTable = functionStrings;
|
||||
|
|
@ -583,7 +599,7 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi
|
|||
Con::gCurrentRoot = this->modPath;
|
||||
}
|
||||
const char * val;
|
||||
const char *retValue;
|
||||
StringStackPtr retValue;
|
||||
|
||||
// note: anything returned is pushed to CSTK and will be invalidated on the next exec()
|
||||
ConsoleValueRef returnValue;
|
||||
|
|
@ -1137,7 +1153,7 @@ breakContinue:
|
|||
// We're falling thru here on purpose.
|
||||
|
||||
case OP_RETURN:
|
||||
retValue = STR.getStringValue();
|
||||
retValue = STR.getStringValuePtr();
|
||||
|
||||
if( iterDepth > 0 )
|
||||
{
|
||||
|
|
@ -1149,13 +1165,13 @@ breakContinue:
|
|||
}
|
||||
|
||||
STR.rewind();
|
||||
STR.setStringValue( retValue ); // Not nice but works.
|
||||
retValue = STR.getStringValue();
|
||||
STR.setStringValue( StringStackPtrRef(retValue).getPtr(&STR) ); // Not nice but works.
|
||||
retValue = STR.getStringValuePtr();
|
||||
}
|
||||
|
||||
// Previously the return value was on the stack and would be returned using STR.getStringValue().
|
||||
// Now though we need to wrap it in a ConsoleValueRef
|
||||
returnValue.value = CSTK.pushStackString(retValue);
|
||||
returnValue.value = CSTK.pushStringStackPtr(retValue);
|
||||
|
||||
goto execFinished;
|
||||
|
||||
|
|
@ -1992,7 +2008,7 @@ breakContinue:
|
|||
break;
|
||||
case OP_PUSH:
|
||||
STR.push();
|
||||
CSTK.pushString(STR.getPreviousStringValue());
|
||||
CSTK.pushStringStackPtr(STR.getPreviousStringValuePtr());
|
||||
break;
|
||||
case OP_PUSH_UINT:
|
||||
CSTK.pushUINT(intStack[_UINT]);
|
||||
|
|
@ -2073,7 +2089,7 @@ breakContinue:
|
|||
|
||||
if( iter.mIsStringIter )
|
||||
{
|
||||
iter.mData.mStr.mString = STR.getStringValue();
|
||||
iter.mData.mStr.mString = STR.getStringValuePtr();
|
||||
iter.mData.mStr.mIndex = 0;
|
||||
}
|
||||
else
|
||||
|
|
@ -2111,7 +2127,7 @@ breakContinue:
|
|||
|
||||
if( iter.mIsStringIter )
|
||||
{
|
||||
const char* str = iter.mData.mStr.mString;
|
||||
const char* str = StringStackPtrRef(iter.mData.mStr.mString).getPtr(&STR);
|
||||
|
||||
U32 startIndex = iter.mData.mStr.mIndex;
|
||||
U32 endIndex = startIndex;
|
||||
|
|
|
|||
|
|
@ -1756,6 +1756,8 @@ const char *ConsoleValue::getStringValue()
|
|||
{
|
||||
if(type == TypeInternalString || type == TypeInternalStackString)
|
||||
return sval;
|
||||
else if (type == TypeInternalStringStackPtr)
|
||||
return STR.mBuffer + (U32)sval;
|
||||
if(type == TypeInternalFloat)
|
||||
return Con::getData(TypeF32, &fval, 0);
|
||||
else if(type == TypeInternalInt)
|
||||
|
|
@ -1764,10 +1766,18 @@ const char *ConsoleValue::getStringValue()
|
|||
return Con::getData(type, dataPtr, 0, enumTable);
|
||||
}
|
||||
|
||||
StringStackPtr ConsoleValue::getStringStackPtr()
|
||||
{
|
||||
if (type == TypeInternalStringStackPtr)
|
||||
return (U32)sval;
|
||||
else
|
||||
return (U32)-1;
|
||||
}
|
||||
|
||||
bool ConsoleValue::getBoolValue()
|
||||
{
|
||||
if(type == TypeInternalString || type == TypeInternalStackString)
|
||||
return dAtob(sval);
|
||||
if(type == TypeInternalString || type == TypeInternalStackString || type == TypeInternalStringStackPtr)
|
||||
return dAtob(getStringValue());
|
||||
if(type == TypeInternalFloat)
|
||||
return fval > 0;
|
||||
else if(type == TypeInternalInt)
|
||||
|
|
@ -1791,7 +1801,7 @@ void ConsoleValue::setIntValue(U32 val)
|
|||
ival = val;
|
||||
if(sval != typeValueEmpty)
|
||||
{
|
||||
if (type != TypeInternalStackString) dFree(sval);
|
||||
if (type != TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval);
|
||||
sval = typeValueEmpty;
|
||||
}
|
||||
type = TypeInternalInt;
|
||||
|
|
@ -1816,7 +1826,7 @@ void ConsoleValue::setFloatValue(F32 val)
|
|||
ival = static_cast<U32>(val);
|
||||
if(sval != typeValueEmpty)
|
||||
{
|
||||
if (type != TypeInternalStackString) dFree(sval);
|
||||
if (type != TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval);
|
||||
sval = typeValueEmpty;
|
||||
}
|
||||
type = TypeInternalFloat;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ struct ConsoleFunctionHeader;
|
|||
class EngineEnumTable;
|
||||
typedef EngineEnumTable EnumTable;
|
||||
|
||||
typedef U32 StringStackPtr;
|
||||
|
||||
template< typename T > S32 TYPEID();
|
||||
|
||||
|
||||
|
|
@ -121,8 +123,9 @@ public:
|
|||
|
||||
enum
|
||||
{
|
||||
TypeInternalInt = -4,
|
||||
TypeInternalFloat = -3,
|
||||
TypeInternalInt = -5,
|
||||
TypeInternalFloat = -4,
|
||||
TypeInternalStringStackPtr = -3,
|
||||
TypeInternalStackString = -2,
|
||||
TypeInternalString = -1,
|
||||
};
|
||||
|
|
@ -166,6 +169,7 @@ public:
|
|||
S32 getSignedIntValue();
|
||||
F32 getFloatValue();
|
||||
const char *getStringValue();
|
||||
StringStackPtr getStringStackPtr();
|
||||
bool getBoolValue();
|
||||
|
||||
void setIntValue(U32 val);
|
||||
|
|
@ -173,6 +177,7 @@ public:
|
|||
void setFloatValue(F32 val);
|
||||
void setStringValue(const char *value);
|
||||
void setStackStringValue(const char *value);
|
||||
void setStringStackPtrValue(StringStackPtr ptr);
|
||||
void setBoolValue(bool val);
|
||||
|
||||
void init()
|
||||
|
|
@ -187,7 +192,7 @@ public:
|
|||
void cleanup()
|
||||
{
|
||||
if (type <= TypeInternalString &&
|
||||
sval != typeValueEmpty && type != TypeInternalStackString )
|
||||
sval != typeValueEmpty && type != TypeInternalStackString && type != TypeInternalStringStackPtr)
|
||||
dFree(sval);
|
||||
sval = typeValueEmpty;
|
||||
type = ConsoleValue::TypeInternalString;
|
||||
|
|
@ -219,6 +224,7 @@ public:
|
|||
static ConsoleValueRef fromValue(ConsoleValue *value) { ConsoleValueRef ref; ref.value = value; return ref; }
|
||||
|
||||
const char *getStringValue() { return value ? value->getStringValue() : ""; }
|
||||
StringStackPtr getStringStackPtrValue() { return value ? value->getStringStackPtr() : 0; }
|
||||
|
||||
inline U32 getIntValue() { return value ? value->getIntValue() : 0; }
|
||||
inline S32 getSignedIntValue() { return value ? value->getSignedIntValue() : 0; }
|
||||
|
|
@ -231,10 +237,12 @@ public:
|
|||
inline operator S32() { return getSignedIntValue(); }
|
||||
inline operator F32() { return getFloatValue(); }
|
||||
inline operator bool() { return getBoolValue(); }
|
||||
|
||||
inline bool isString() { return value ? value->type >= ConsoleValue::TypeInternalStackString : true; }
|
||||
|
||||
inline bool isStringStackPtr() { return value ? value->type == ConsoleValue::TypeInternalStringStackPtr : false; }
|
||||
inline bool isString() { return value ? value->type >= ConsoleValue::TypeInternalStringStackPtr : true; }
|
||||
inline bool isInt() { return value ? value->type == ConsoleValue::TypeInternalInt : false; }
|
||||
inline bool isFloat() { return value ? value->type == ConsoleValue::TypeInternalFloat : false; }
|
||||
inline S32 getType() { return value ? value->type : -1; }
|
||||
|
||||
// Note: operators replace value
|
||||
ConsoleValueRef& operator=(const ConsoleValueRef &other);
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ void ConsoleValue::setStringValue(const char * value)
|
|||
*/
|
||||
if (value == typeValueEmpty)
|
||||
{
|
||||
if (sval && sval != typeValueEmpty && type != TypeInternalStackString) dFree(sval);
|
||||
if (sval && sval != typeValueEmpty && type != TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval);
|
||||
sval = typeValueEmpty;
|
||||
bufferLen = 0;
|
||||
fval = 0.f;
|
||||
|
|
@ -541,7 +541,7 @@ void ConsoleValue::setStringValue(const char * value)
|
|||
// may as well pad to the next cache line
|
||||
U32 newLen = ((stringLen + 1) + 15) & ~15;
|
||||
|
||||
if(sval == typeValueEmpty || type == TypeInternalStackString)
|
||||
if(sval == typeValueEmpty || type == TypeInternalStackString || type == TypeInternalStringStackPtr)
|
||||
sval = (char *) dMalloc(newLen);
|
||||
else if(newLen > bufferLen)
|
||||
sval = (char *) dRealloc(sval, newLen);
|
||||
|
|
@ -556,7 +556,7 @@ void ConsoleValue::setStringValue(const char * value)
|
|||
}
|
||||
|
||||
|
||||
void ConsoleValue::setStackStringValue(const char * value)
|
||||
void ConsoleValue::setStackStringValue(const char *value)
|
||||
{
|
||||
if (value == NULL) value = typeValueEmpty;
|
||||
|
||||
|
|
@ -564,7 +564,7 @@ void ConsoleValue::setStackStringValue(const char * value)
|
|||
{
|
||||
if (value == typeValueEmpty)
|
||||
{
|
||||
if (sval && sval != typeValueEmpty && type != ConsoleValue::TypeInternalStackString) dFree(sval);
|
||||
if (sval && sval != typeValueEmpty && type != ConsoleValue::TypeInternalStackString && type != ConsoleValue::TypeInternalStringStackPtr) dFree(sval);
|
||||
sval = typeValueEmpty;
|
||||
bufferLen = 0;
|
||||
fval = 0.f;
|
||||
|
|
@ -586,13 +586,42 @@ void ConsoleValue::setStackStringValue(const char * value)
|
|||
}
|
||||
|
||||
type = TypeInternalStackString;
|
||||
sval = (char*)value;
|
||||
sval = (char*)value;
|
||||
bufferLen = stringLen;
|
||||
}
|
||||
else
|
||||
Con::setData(type, dataPtr, 0, 1, &value, enumTable);
|
||||
}
|
||||
|
||||
void ConsoleValue::setStringStackPtrValue(StringStackPtr ptrValue)
|
||||
{
|
||||
if(type <= ConsoleValue::TypeInternalString)
|
||||
{
|
||||
const char *value = StringStackPtrRef(ptrValue).getPtr(&STR);
|
||||
if (sval && sval != typeValueEmpty && type != ConsoleValue::TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval);
|
||||
|
||||
U32 stringLen = dStrlen(value);
|
||||
if(stringLen < 256)
|
||||
{
|
||||
fval = dAtof(value);
|
||||
ival = dAtoi(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
fval = 0.f;
|
||||
ival = 0;
|
||||
}
|
||||
|
||||
type = TypeInternalStringStackPtr;
|
||||
sval = (char*)(value - STR.mBuffer);
|
||||
bufferLen = stringLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *value = StringStackPtrRef(ptrValue).getPtr(&STR);
|
||||
Con::setData(type, dataPtr, 0, 1, &value, enumTable);
|
||||
}
|
||||
}
|
||||
|
||||
S32 Dictionary::getIntVariable(StringTableEntry name, bool *entValid)
|
||||
{
|
||||
|
|
@ -651,7 +680,8 @@ Dictionary::Entry* Dictionary::addVariable( const char *name,
|
|||
Entry *ent = add(StringTable->insert(name));
|
||||
|
||||
if ( ent->value.type <= ConsoleValue::TypeInternalString &&
|
||||
ent->value.sval != typeValueEmpty && ent->value.type != ConsoleValue::TypeInternalStackString )
|
||||
ent->value.sval != typeValueEmpty &&
|
||||
ent->value.type != ConsoleValue::TypeInternalStackString && ent->value.type != ConsoleValue::TypeInternalStringStackPtr )
|
||||
dFree(ent->value.sval);
|
||||
|
||||
ent->value.type = type;
|
||||
|
|
|
|||
|
|
@ -367,6 +367,22 @@ public:
|
|||
notify->trigger();
|
||||
}
|
||||
|
||||
void setStringStackPtrValue(StringStackPtr newValue)
|
||||
{
|
||||
if( mIsConstant )
|
||||
{
|
||||
Con::errorf( "Cannot assign value to constant '%s'.", name );
|
||||
return;
|
||||
}
|
||||
|
||||
value.setStringStackPtrValue(newValue);
|
||||
|
||||
|
||||
// Fire off the notification if we have one.
|
||||
if ( notify )
|
||||
notify->trigger();
|
||||
}
|
||||
|
||||
void setStringValue(const char *newValue)
|
||||
{
|
||||
if( mIsConstant )
|
||||
|
|
@ -495,6 +511,7 @@ public:
|
|||
void setIntVariable(S32 val);
|
||||
void setFloatVariable(F64 val);
|
||||
void setStringVariable(const char *str);
|
||||
void setStringStackPtrVariable(StringStackPtr str);
|
||||
void setCopyVariable();
|
||||
|
||||
void pushFrame(StringTableEntry frameName, Namespace *ns);
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ void ConsoleValueStack::pushValue(ConsoleValue &variable)
|
|||
mStack[mStackPos++].setIntValue((S32)variable.getIntValue());
|
||||
case ConsoleValue::TypeInternalFloat:
|
||||
mStack[mStackPos++].setFloatValue((F32)variable.getFloatValue());
|
||||
case ConsoleValue::TypeInternalStringStackPtr:
|
||||
mStack[mStackPos++].setStringStackPtrValue(variable.getStringStackPtr());
|
||||
default:
|
||||
mStack[mStackPos++].setStringValue(variable.getStringValue());
|
||||
}
|
||||
|
|
@ -151,6 +153,19 @@ ConsoleValue *ConsoleValueStack::pushStackString(const char *value)
|
|||
return &mStack[mStackPos-1];
|
||||
}
|
||||
|
||||
ConsoleValue *ConsoleValueStack::pushStringStackPtr(StringStackPtr value)
|
||||
{
|
||||
if (mStackPos == ConsoleValueStack::MaxStackDepth) {
|
||||
AssertFatal(false, "Console Value Stack is empty");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Con::printf("[%i]CSTK pushStringStackPtr %s", mStackPos, StringStackPtrRef(value).getPtr(&STR));
|
||||
|
||||
mStack[mStackPos++].setStringStackPtrValue(value);
|
||||
return &mStack[mStackPos-1];
|
||||
}
|
||||
|
||||
ConsoleValue *ConsoleValueStack::pushUINT(U32 value)
|
||||
{
|
||||
if (mStackPos == ConsoleValueStack::MaxStackDepth) {
|
||||
|
|
|
|||
|
|
@ -35,8 +35,21 @@
|
|||
#include "console/console.h"
|
||||
#endif
|
||||
|
||||
typedef U32 StringStackPtr;
|
||||
struct StringStack;
|
||||
|
||||
/// Helper class which stores a relative pointer in the StringStack buffer
|
||||
class StringStackPtrRef
|
||||
{
|
||||
public:
|
||||
StringStackPtrRef() : mOffset(0) {;}
|
||||
StringStackPtrRef(StringStackPtr offset) : mOffset(offset) {;}
|
||||
|
||||
StringStackPtr mOffset;
|
||||
|
||||
/// Get pointer to string in stack stk
|
||||
inline char *getPtr(StringStack *stk);
|
||||
};
|
||||
|
||||
/// Core stack for interpreter operations.
|
||||
///
|
||||
|
|
@ -199,6 +212,16 @@ struct StringStack
|
|||
return mBuffer + mStartOffsets[mStartStackSize-1];
|
||||
}
|
||||
|
||||
inline StringStackPtr getStringValuePtr()
|
||||
{
|
||||
return (getStringValue() - mBuffer);
|
||||
}
|
||||
|
||||
inline StringStackPtr getPreviousStringValuePtr()
|
||||
{
|
||||
return (getPreviousStringValue() - mBuffer);
|
||||
}
|
||||
|
||||
/// Advance the start stack, placing a zero length string on the top.
|
||||
///
|
||||
/// @note You should use StringStack::push, not this, if you want to
|
||||
|
|
@ -322,6 +345,7 @@ public:
|
|||
|
||||
ConsoleValue *pushString(const char *value);
|
||||
ConsoleValue *pushStackString(const char *value);
|
||||
ConsoleValue *pushStringStackPtr(StringStackPtr ptr);
|
||||
ConsoleValue *pushUINT(U32 value);
|
||||
ConsoleValue *pushFLT(float value);
|
||||
|
||||
|
|
@ -345,4 +369,6 @@ public:
|
|||
extern StringStack STR;
|
||||
extern ConsoleValueStack CSTK;
|
||||
|
||||
inline char* StringStackPtrRef::getPtr(StringStack *stk) { return stk->mBuffer + mOffset; }
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue