Script stack overflow possibility when preparing nested virtual function call

Started by
1 comment, last by WitchLord 9 years, 10 months ago

After encountering some fairly incomprehensible issues with corrupted arguments to system functions, I managed to track down a script stack overflow with some valgrind assistance.

The issue occurs when a context's stack pointer is near the end of its stack block, and the context is prepared for a new nested function call after pushing the state. asCContext::Prepare does the following calculation for checking if a new stack block should be allocated:


// Determine the minimum stack size needed
int stackSize = m_argumentsSize + m_returnValueSize;
if( m_currentFunction->scriptData )
	stackSize += m_currentFunction->scriptData->stackNeeded;

If an asFUNC_VIRTUAL function was passed to Prepare(), it will not have scriptData for obvious reasons, and if the function needs more stack than is remaining in the current block, it will overflow and read/write into invalid memory during execution.

The virtual function is resolved into its real counterpart when asCContext::Execute() hits, so I added a quick fix to ensure enough stack space is available there. I don't know if this is the way you would want it to be solved, but it fixes the encountered problems in our project.


 				}
 
 				if( realFunc && realFunc->signatureId == m_currentFunction->signatureId )
+				{
 					m_currentFunction = realFunc;
+
+					// Make sure our stack is large enough for local variables in this function
+					if( m_currentFunction->scriptData )
+					{
+						asDWORD* oldStack = m_regs.stackPointer;
+
+						int stackSize = m_argumentsSize + m_returnValueSize;
+						if( m_currentFunction->scriptData )
+							stackSize += m_currentFunction->scriptData->stackNeeded;
+						if( !ReserveStackSpace(stackSize) )
+							SetInternalException(TXT_NO_STACK_MEMORY);
+
+						if( oldStack != m_regs.stackPointer )
+						{
+							memcpy(m_regs.stackPointer, m_regs.stackFramePointer, sizeof(asDWORD)*(m_argumentsSize + m_returnValueSize));
+							m_regs.stackFramePointer = m_regs.stackPointer;
+						}
+					}
+				}
 				else
 					SetInternalException(TXT_NULL_POINTER_ACCESS);
 			}

Advertisement

Thanks. I'll review what might be the best solution for this scenario.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I've checked in the fix for this in revision 1967.

I solved it slightly differently: Rather than duplicating the code for reserving the stack space in Execute() I moved this part from the CallScriptFunction() into PrepareScriptFunction().

Regards,

Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement