Fix some bugs and memory leaks in CBOT
* Added CBotStack::StackOver() calls where it was possible to go out-of-bounds when calling CBotStack::AddStack(). * Fixed some bugs in CBotExternalCallClassfix-squashed-planets
parent
993a6adf6e
commit
309f80b25f
|
@ -137,6 +137,7 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
|
|||
while ( p != nullptr )
|
||||
{
|
||||
pile = pile->AddStack();
|
||||
if (pile->StackOver()) return pj->Return(pile);
|
||||
if (pile->GetState() == 1) // already done?
|
||||
{
|
||||
if (ppVars != nullptr && ppVars[i] != nullptr) ++i;
|
||||
|
|
|
@ -82,19 +82,23 @@ int CBotExternalCallList::DoCall(CBotToken* token, CBotVar* thisVar, CBotVar** p
|
|||
|
||||
CBotExternalCall* pt = m_list[token->GetString()].get();
|
||||
|
||||
if (pStack->IsCallFinished()) return true;
|
||||
CBotStack* pile = pStack->AddStackExternalCall(pt);
|
||||
if (thisVar == nullptr && pStack->IsCallFinished()) return true; // only for non-method external call
|
||||
|
||||
// lists the parameters depending on the contents of the stack (pStackVar)
|
||||
CBotVar* pVar = MakeListVars(ppVar, true);
|
||||
// if this is a method call we need to use AddStack()
|
||||
CBotStack* pile = (thisVar != nullptr) ? pStack->AddStack() : pStack->AddStackExternalCall(pt);
|
||||
|
||||
// creates a variable to the result
|
||||
CBotVar* pResult = rettype.Eq(CBotTypVoid) ? nullptr : CBotVar::Create("", rettype);
|
||||
if (pile->GetState() == 0) // the first time?
|
||||
{
|
||||
// lists the parameters depending on the contents of the stack
|
||||
CBotVar* pVar = MakeListVars(ppVar, true);
|
||||
pile->SetVar(pVar);
|
||||
|
||||
pile->SetVar(pVar);
|
||||
|
||||
CBotStack* pile2 = pile->AddStack();
|
||||
pile2->SetVar(pResult);
|
||||
CBotStack* pile2 = pile->AddStack();
|
||||
// creates a variable to the result
|
||||
CBotVar* pResult = rettype.Eq(CBotTypVoid) ? nullptr : CBotVar::Create("", rettype);
|
||||
pile2->SetVar(pResult);
|
||||
pile->IncState(); // increment state to mark this step done
|
||||
}
|
||||
|
||||
pile->SetError(CBotNoErr, token); // save token for the position in case of error
|
||||
return pt->Run(thisVar, pStack);
|
||||
|
@ -107,7 +111,8 @@ bool CBotExternalCallList::RestoreCall(CBotToken* token, CBotVar* thisVar, CBotV
|
|||
|
||||
CBotExternalCall* pt = m_list[token->GetString()].get();
|
||||
|
||||
CBotStack* pile = pStack->RestoreStackEOX(pt);
|
||||
// if this is a method call we need to use RestoreStack()
|
||||
CBotStack* pile = (thisVar != nullptr) ? pStack->RestoreStack() : pStack->RestoreStackEOX(pt);
|
||||
if (pile == nullptr) return true;
|
||||
|
||||
pile->RestoreStack();
|
||||
|
@ -163,8 +168,7 @@ bool CBotExternalCallDefault::Run(CBotVar* thisVar, CBotStack* pStack)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (result != nullptr) pStack->SetCopyVar(result);
|
||||
|
||||
pStack->Return(pile2); // return 'result' and clear extra stack
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -187,8 +191,8 @@ CBotTypResult CBotExternalCallClass::Compile(CBotVar* thisVar, CBotVar* args, vo
|
|||
|
||||
bool CBotExternalCallClass::Run(CBotVar* thisVar, CBotStack* pStack)
|
||||
{
|
||||
if (pStack->IsCallFinished()) return true;
|
||||
CBotStack* pile = pStack->AddStackExternalCall(this);
|
||||
assert(thisVar != nullptr);
|
||||
CBotStack* pile = pStack->AddStack();
|
||||
CBotVar* args = pile->GetVar();
|
||||
|
||||
CBotStack* pile2 = pile->AddStack();
|
||||
|
@ -207,9 +211,8 @@ bool CBotExternalCallClass::Run(CBotVar* thisVar, CBotStack* pStack)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (result != nullptr) pStack->SetCopyVar(result);
|
||||
|
||||
pStack->Return(pile2); // return 'result' and clear extra stack
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace CBot
|
||||
|
|
|
@ -360,6 +360,7 @@ bool CBotDefClass::Execute(CBotStack* &pj)
|
|||
if ( p != nullptr) while ( true )
|
||||
{
|
||||
pile2 = pile2->AddStack(); // place on the stack for the results
|
||||
if (pile2->StackOver()) return pj->Return(pile2);
|
||||
if ( pile2->GetState() == 0 )
|
||||
{
|
||||
if (!p->Execute(pile2)) return false; // interrupted here?
|
||||
|
|
|
@ -445,7 +445,7 @@ bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
|
|||
pile->IncState();
|
||||
}
|
||||
|
||||
if ( !m_block->Execute(pile) )
|
||||
if (!pile->GetRetVar(m_block->Execute(pile)))
|
||||
{
|
||||
if ( pile->GetError() < 0 )
|
||||
pile->SetError( CBotNoErr );
|
||||
|
|
|
@ -138,6 +138,7 @@ bool CBotInstrCall::Execute(CBotStack* &pj)
|
|||
if ( p != nullptr) while ( true )
|
||||
{
|
||||
pile = pile->AddStack(); // place on the stack for the results
|
||||
if (pile->StackOver()) return pj->Return(pile);
|
||||
if ( pile->GetState() == 0 )
|
||||
{
|
||||
if (!p->Execute(pile)) return false; // interrupted here?
|
||||
|
|
|
@ -164,6 +164,7 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre
|
|||
}
|
||||
ppVars[i++] = pile2->GetVar(); // construct the list of pointers
|
||||
pile2 = pile2->AddStack(); // space on the stack for the result
|
||||
if (pile2->StackOver()) return pj->Return(pile2);
|
||||
p = p->GetNext();
|
||||
if ( p == nullptr) break;
|
||||
}
|
||||
|
|
|
@ -189,6 +189,7 @@ bool CBotNew::Execute(CBotStack* &pj)
|
|||
if (p != nullptr) while ( true)
|
||||
{
|
||||
pile2 = pile2->AddStack(); // space on the stack for the result
|
||||
if (pile2->StackOver()) return pj->Return(pile2);
|
||||
if (pile2->GetState() == 0)
|
||||
{
|
||||
if (!p->Execute(pile2)) return false; // interrupted here?
|
||||
|
|
|
@ -357,6 +357,7 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack)
|
|||
|
||||
CBotStack* pStk2 = pStk1->AddStack(); // adds an item to the stack
|
||||
// or return in case of recovery
|
||||
if (pStk2->StackOver()) return pStack->Return(pStk2);
|
||||
|
||||
// 2nd state, evalute right operand
|
||||
if ( pStk2->GetState() == 0 )
|
||||
|
@ -514,7 +515,6 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack)
|
|||
pStk2->SetVar(result); // puts the result on the stack
|
||||
if ( err ) pStk2->SetError(err, &m_token); // and the possible error (division by zero)
|
||||
|
||||
// pStk1->Return(pStk2); // releases the stack
|
||||
return pStack->Return(pStk2); // transmits the result
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
namespace CBot
|
||||
{
|
||||
|
||||
CBotExternalCallList* CBotProgram::m_externalCalls = new CBotExternalCallList();
|
||||
std::unique_ptr<CBotExternalCallList> CBotProgram::m_externalCalls;
|
||||
|
||||
CBotProgram::CBotProgram()
|
||||
{
|
||||
|
@ -395,6 +395,8 @@ int CBotProgram::GetVersion()
|
|||
|
||||
void CBotProgram::Init()
|
||||
{
|
||||
m_externalCalls.reset(new CBotExternalCallList);
|
||||
|
||||
CBotProgram::DefineNum("CBotErrZeroDiv", CBotErrZeroDiv); // division by zero
|
||||
CBotProgram::DefineNum("CBotErrNotInit", CBotErrNotInit); // uninitialized variable
|
||||
CBotProgram::DefineNum("CBotErrBadThrow", CBotErrBadThrow); // throw a negative value
|
||||
|
@ -420,9 +422,10 @@ void CBotProgram::Free()
|
|||
CBotToken::ClearDefineNum();
|
||||
m_externalCalls->Clear();
|
||||
CBotClass::ClearPublic();
|
||||
m_externalCalls.reset();
|
||||
}
|
||||
|
||||
CBotExternalCallList* CBotProgram::GetExternalCalls()
|
||||
const std::unique_ptr<CBotExternalCallList>& CBotProgram::GetExternalCalls()
|
||||
{
|
||||
return m_externalCalls;
|
||||
}
|
||||
|
|
|
@ -19,11 +19,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "CBot/CBotTypResult.h"
|
||||
#include "CBot/CBotEnums.h"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace CBot
|
||||
{
|
||||
|
@ -31,6 +32,7 @@ namespace CBot
|
|||
class CBotFunction;
|
||||
class CBotClass;
|
||||
class CBotStack;
|
||||
class CBotTypResult;
|
||||
class CBotVar;
|
||||
class CBotExternalCallList;
|
||||
|
||||
|
@ -335,11 +337,11 @@ public:
|
|||
/**
|
||||
* \brief Returns static list of all registered external calls
|
||||
*/
|
||||
static CBotExternalCallList* GetExternalCalls();
|
||||
static const std::unique_ptr<CBotExternalCallList>& GetExternalCalls();
|
||||
|
||||
private:
|
||||
//! All external calls
|
||||
static CBotExternalCallList* m_externalCalls;
|
||||
static std::unique_ptr<CBotExternalCallList> m_externalCalls;
|
||||
//! All user-defined functions
|
||||
std::list<CBotFunction*> m_functions{};
|
||||
//! The entry point function
|
||||
|
|
Loading…
Reference in New Issue