Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Don't forget to read Tuesday's email newsletter for your chance to win a free copy of Construct 2!


- - - - -

Script stack overflow possibility when preparing nested virtual function call


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 GGLucas   Members   -  Reputation: 140

Like
0Likes
Like

Posted 17 June 2014 - 12:31 PM

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);
 			}



Sponsor:

#2 Andreas Jonsson   Moderators   -  Reputation: 3416

Like
0Likes
Like

Posted 19 June 2014 - 09:32 AM

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

#3 Andreas Jonsson   Moderators   -  Reputation: 3416

Like
0Likes
Like

Posted 24 June 2014 - 07:36 PM

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


Edited by Andreas Jonsson, 24 June 2014 - 07:36 PM.

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




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS