Quellcode durchsuchen

Fix issue where console stack values were getting overwritten inside a C++ function

James Urquhart vor 10 Jahren
Ursprung
Commit
82fd1794e6

+ 23 - 17
Engine/source/console/compiledEval.cpp

@@ -470,11 +470,11 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi
             dSprintf(traceBuffer + dStrlen(traceBuffer), sizeof(traceBuffer) - dStrlen(traceBuffer),
                "%s(", thisFunctionName);
          }
-         for (i = 0; i < wantedArgc; i++)
+         for(i = 0; i < wantedArgc; i++)
          {
-             dStrcat(traceBuffer, argv[i + 1]);
-             if (i != wantedArgc - 1)
-                 dStrcat(traceBuffer, ", ");
+            dStrcat(traceBuffer, argv[i+1]);
+            if(i != wantedArgc - 1)
+               dStrcat(traceBuffer, ", ");
          }
          dStrcat(traceBuffer, ")");
          Con::printf("%s", traceBuffer);
@@ -533,9 +533,16 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi
       }
    }
 
-   // Reset the console stack frame which at this point will contain 
-   // either nothing or argv[] which we just copied
-   CSTK.resetFrame();
+   bool doResetValueStack = !gEvalState.mResetLocked;
+   gEvalState.mResetLocked = true;
+   
+   if (gEvalState.mShouldReset)
+   {
+      // Ensure all stacks are clean in case anything became unbalanced during the previous execution
+      STR.clearFrames();
+      CSTK.clearFrames();
+      gEvalState.mShouldReset = false;
+   }
 
    // Grab the state of the telenet debugger here once
    // so that the push and pop frames are always balanced.
@@ -1817,7 +1824,7 @@ breakContinue:
                ConsoleValueRef ret;
                if(nsEntry->mFunctionOffset)
                   ret = nsEntry->mCode->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage);
- 
+
                STR.popFrame();
                // Functions are assumed to return strings, so look ahead to see if we can skip the conversion
                if(code[ip] == OP_STR_TO_UINT)
@@ -1837,7 +1844,7 @@ breakContinue:
                }
                else
                   STR.setStringValue((const char*)ret);
-               
+
                // This will clear everything including returnValue
                CSTK.popFrame();
                STR.clearFunctionOffset();
@@ -2219,15 +2226,7 @@ execFinished:
          Con::printf("%s", traceBuffer);
       }
    }
-   else
-   {
-      delete[] globalStrings;
-      globalStringsMaxLen = 0;
 
-      delete[] globalFloats;
-      globalStrings = NULL;
-      globalFloats = NULL;
-   }
    smCurrentCodeBlock = saveCodeBlock;
    if(saveCodeBlock && saveCodeBlock->name)
    {
@@ -2235,6 +2234,13 @@ execFinished:
       Con::gCurrentRoot = saveCodeBlock->modPath;
    }
 
+   // Mark the reset flag for the next run if we've finished execution
+   if (doResetValueStack)
+   {
+      gEvalState.mShouldReset = true;
+      gEvalState.mResetLocked = false;
+   }
+
    decRefCount();
 
 #ifdef TORQUE_DEBUG

+ 1 - 0
Engine/source/console/consoleInternal.cpp

@@ -796,6 +796,7 @@ ExprEvalState::ExprEvalState()
    currentVariable = NULL;
    mStackDepth = 0;
    stack.reserve( 64 );
+   mShouldReset = false;
 }
 
 ExprEvalState::~ExprEvalState()

+ 2 - 0
Engine/source/console/consoleInternal.h

@@ -468,6 +468,8 @@ public:
    bool traceOn;
 
    U32 mStackDepth;
+   bool mShouldReset; ///< Designates if the value stack should be reset
+   bool mResetLocked; ///< mShouldReset will be set at the end
 
    ExprEvalState();
    ~ExprEvalState();

+ 7 - 1
Engine/source/console/stringStack.cpp

@@ -162,7 +162,7 @@ ConsoleValue* ConsoleValueStack::pop()
 
 void ConsoleValueStack::pushFrame()
 {
-   //Con::printf("CSTK pushFrame");
+   //Con::printf("CSTK pushFrame[%i] (%i)", mFrame, mStackPos);
    mStackFrames[mFrame++] = mStackPos;
 }
 
@@ -181,6 +181,12 @@ void ConsoleValueStack::resetFrame()
    //Con::printf("CSTK resetFrame to %i", mStackPos);
 }
 
+void ConsoleValueStack::clearFrames()
+{
+   mStackPos = 0;
+   mFrame = 0;
+}
+
 void ConsoleValueStack::popFrame()
 {
    //Con::printf("CSTK popFrame");

+ 18 - 1
Engine/source/console/stringStack.h

@@ -74,6 +74,7 @@ struct StringStack
          mBuffer = (char *) dRealloc(mBuffer, mBufferSize);
       }
    }
+
    void validateArgBufferSize(U32 size)
    {
       if(size > mArgBufferSize)
@@ -82,6 +83,7 @@ struct StringStack
          mArgBuffer = (char *) dRealloc(mArgBuffer, mArgBufferSize);
       }
    }
+
    StringStack()
    {
       mBufferSize = 0;
@@ -95,6 +97,8 @@ struct StringStack
       mFunctionOffset = 0;
       validateBufferSize(8192);
       validateArgBufferSize(2048);
+      dMemset(mBuffer, '\0', mBufferSize);
+      dMemset(mArgBuffer, '\0', mArgBufferSize);
    }
    ~StringStack()
    {
@@ -141,6 +145,7 @@ struct StringStack
    /// Clear the function offset.
    void clearFunctionOffset()
    {
+      //Con::printf("StringStack mFunctionOffset = 0 (from %i)", mFunctionOffset);
       mFunctionOffset = 0;
    }
 
@@ -262,9 +267,9 @@ struct StringStack
       return ret;
    }
 
-   
    void pushFrame()
    {
+      //Con::printf("StringStack pushFrame [frame=%i, start=%i]", mNumFrames, mStartStackSize);
       mFrameOffsets[mNumFrames++] = mStartStackSize;
       mStartOffsets[mStartStackSize++] = mStart;
       mStart += ReturnBufferSpace;
@@ -273,11 +278,22 @@ struct StringStack
 
    void popFrame()
    {
+      //Con::printf("StringStack popFrame [frame=%i, start=%i]", mNumFrames, mStartStackSize);
       mStartStackSize = mFrameOffsets[--mNumFrames];
       mStart = mStartOffsets[mStartStackSize];
       mLen = 0;
    }
 
+   void clearFrames()
+   {
+      //Con::printf("StringStack clearFrames");
+      mNumFrames = 0;
+      mStart = 0;
+      mLen = 0;
+      mStartStackSize = 0;
+      mFunctionOffset = 0;
+   }
+
    /// Get the arguments for a function call from the stack.
    void getArgcArgv(StringTableEntry name, U32 *argc, const char ***in_argv, bool popStackFrame = false);
 };
@@ -309,6 +325,7 @@ public:
    void popFrame();
 
    void resetFrame();
+   void clearFrames();
 
    void getArgcArgv(StringTableEntry name, U32 *argc, ConsoleValueRef **in_argv, bool popStackFrame = false);