Skip to content
Permalink
Browse files
Fixes to variable list in CBot debugger
* fixed stack overflow with circular references (closes #434)
* fixed displaying boolean variables
* fixed buffer overflows with entries longer than 100 characters
* removed hard-limit to 100 entries with at most 100 characters in CList (this also allows you to have more than 100 programs in a robot, up to 999)
  • Loading branch information
krzys-h committed Mar 15, 2016
1 parent 4479a19 commit fef8a8e35517199a46e72806151049142166429b
Showing with 68 additions and 74 deletions.
  1. +45 −51 src/script/script.cpp
  2. +12 −11 src/ui/controls/list.cpp
  3. +5 −6 src/ui/controls/list.h
  4. +6 −6 src/ui/screen/screen_player_select.cpp
@@ -490,79 +490,71 @@ bool CScript::GetCursor(int &cursor1, int &cursor2)

// Put of the variables in a list.

void PutList(const char *baseName, bool bArray, CBot::CBotVar *var, Ui::CList *list, int &rankList)
void PutList(const std::string& baseName, bool bArray, CBot::CBotVar *var, Ui::CList *list, int &rankList, std::set<CBot::CBotVar*>& previous)
{
CBot::CBotVar *svar, *pStatic;
char varName[100];
char buffer[100];
std::string p;
int index, type;

if ( var == nullptr && baseName[0] != 0 )
if ( var == nullptr && !baseName.empty() )
{
sprintf(buffer, "%s = null;", baseName);
list->SetItemName(rankList++, buffer);
list->SetItemName(rankList++, StrUtils::Format("%s = null;", baseName.c_str()).c_str());
return;
}

index = 0;
while ( var != nullptr )
int index = 0;
while (var != nullptr)
{
var->Update(nullptr);
pStatic = var->GetStaticVar(); // finds the static element

p = pStatic->GetName(); // variable name
//? if ( strcmp(p, "this") == 0 )
//? {
//? var = var->GetNext();
//? continue;
//? }
CBot::CBotVar* pStatic = var->GetStaticVar(); // finds the static element

if ( baseName[0] == 0 )
std::string varName;
if (baseName.empty())
{
sprintf(varName, "%s", p.c_str());
varName = StrUtils::Format("%s", pStatic->GetName().c_str());
}
else
{
if ( bArray )
if (bArray)
{
sprintf(varName, "%s[%d]", baseName, index);
varName = StrUtils::Format("%s[%d]", baseName.c_str(), index);
}
else
{
sprintf(varName, "%s.%s", baseName, p.c_str());
varName = StrUtils::Format("%s.%s", baseName.c_str(), pStatic->GetName().c_str());
}
}

type = pStatic->GetType();

if ( type < CBot::CBotTypBoolean )
if (previous.find(pStatic) != previous.end())
{
p = pStatic->GetValString();
sprintf(buffer, "%s = %s;", varName, p.c_str());
list->SetItemName(rankList++, buffer);
}
else if ( type == CBot::CBotTypString )
{
p = pStatic->GetValString();
sprintf(buffer, "%s = \"%s\";", varName, p.c_str());
list->SetItemName(rankList++, buffer);
}
else if ( type == CBot::CBotTypArrayPointer )
{
svar = pStatic->GetItemList();
PutList(varName, true, svar, list, rankList);
}
else if ( type == CBot::CBotTypClass ||
type == CBot::CBotTypPointer )
{
svar = pStatic->GetItemList();
PutList(varName, false, svar, list, rankList);
list->SetItemName(rankList++, StrUtils::Format("%s = [circular reference]", varName.c_str()).c_str());
}
else
{
sprintf(buffer, "%s = ?;", varName);
list->SetItemName(rankList++, buffer);
int type = pStatic->GetType();

if (type <= CBot::CBotTypBoolean)
{
list->SetItemName(rankList++, StrUtils::Format("%s = %s;", varName.c_str(), pStatic->GetValString().c_str()).c_str());
}
else if (type == CBot::CBotTypString)
{
list->SetItemName(rankList++, StrUtils::Format("%s = \"%s\";", varName.c_str(), pStatic->GetValString().c_str()).c_str());
}
else if (type == CBot::CBotTypArrayPointer)
{
previous.insert(pStatic);
PutList(varName, true, pStatic->GetItemList(), list, rankList, previous);
previous.erase(pStatic);
}
else if (type == CBot::CBotTypClass ||
type == CBot::CBotTypPointer)
{
previous.insert(pStatic);
PutList(varName, false, pStatic->GetItemList(), list, rankList, previous);
previous.erase(pStatic);
}
else
{
//list->SetItemName(rankList++, StrUtils::Format("%s = ?;", varName.c_str()).c_str());
assert(false);
}
}

index ++;
@@ -589,13 +581,15 @@ void CScript::UpdateList(Ui::CList* list)

level = 0;
rank = 0;
std::set<CBot::CBotVar*> previous;
while ( true )
{
var = m_botProg->GetStackVars(funcName, level--);
if ( funcName != progName ) break;

PutList("", false, var, list, rank);
PutList("", false, var, list, rank, previous);
}
assert(previous.empty());

if ( total == list->GetTotal() ) // same total?
{
@@ -354,7 +354,7 @@ void CList::Draw()
float dp;
int i;
char text[100];
char *pb, *pe;
const char *pb, *pe;

if ((m_state & STATE_VISIBLE) == 0)
return;
@@ -451,14 +451,14 @@ void CList::Draw()
ppos.y = pos.y + dim.y * 0.5f;
ppos.y -= m_engine->GetText()->GetHeight(m_fontType, m_fontSize) / 2.0f;
ddim.x = dim.x-dim.y;
DrawCase(m_items[i + m_firstLine].text, ppos, ddim.x, Gfx::TEXT_ALIGN_LEFT);
DrawCase(m_items[i + m_firstLine].text.c_str(), ppos, ddim.x, Gfx::TEXT_ALIGN_LEFT);
}
else
{
ppos.x = pos.x + dim.y * 0.5f;
ppos.y = pos.y + dim.y * 0.5f;
ppos.y -= m_engine->GetText()->GetHeight(m_fontType, m_fontSize) / 2.0f;
pb = m_items[i + m_firstLine].text;
pb = m_items[i + m_firstLine].text.c_str();
for (int j = 0; j < 10; j++)
{
pe = strchr(pb, '\t');
@@ -548,7 +548,7 @@ void CList::Draw()

// Displays text in a box.

void CList::DrawCase(char *text, Math::Point pos, float width, Gfx::TextAlign justif)
void CList::DrawCase(const char* text, Math::Point pos, float width, Gfx::TextAlign justif)
{
if (justif == Gfx::TEXT_ALIGN_CENTER)
pos.x += width / 2.0f;
@@ -651,29 +651,30 @@ bool CList::GetBlink()

// Specifies the text of a line.

void CList::SetItemName(int i, const char* name)
void CList::SetItemName(int i, const std::string& name)
{
if ( i < 0 || i >= LISTMAXTOTAL )
if ( i < 0 )
return;

if ( i >= m_totalLine )
m_totalLine = i+1; // expands the list

if ( name[0] == 0 )
strcpy(m_items[i].text, " ");
m_items.resize(m_totalLine);
if ( name.empty() )
m_items[i].text = " ";
else
strcpy(m_items[i].text, name);
m_items[i].text = name;

UpdateButton();
UpdateScroll();
}

// Returns the text of a line.

char* CList::GetItemName(int i)
const std::string& CList::GetItemName(int i)
{
if ( i < 0 || i >= m_totalLine )
return nullptr;
assert(false);

return m_items[i].text;
}
@@ -35,7 +35,6 @@ namespace Ui
{

const int LISTMAXDISPLAY = 20; // maximum number of visible lines
const int LISTMAXTOTAL = 100; // maximum total number of lines



@@ -71,8 +70,8 @@ class CList : public CControl
void SetBlink(bool bEnable);
bool GetBlink();

void SetItemName(int i, const char* name);
char* GetItemName(int i);
void SetItemName(int i, const std::string& name);
const std::string& GetItemName(int i);

void SetCheck(int i, bool bMode);
bool GetCheck(int i);
@@ -93,7 +92,7 @@ class CList : public CControl
void UpdateButton();
void UpdateScroll();
void MoveScroll();
void DrawCase(char *text, Math::Point pos, float width, Gfx::TextAlign justif);
void DrawCase(const char* text, Math::Point pos, float width, Gfx::TextAlign justif);

private:
// Overridden to avoid warning about hiding the virtual function
@@ -116,11 +115,11 @@ class CList : public CControl

struct Item
{
char text[100] = {};
std::string text = "";
bool check = false;
bool enable = true;
};
std::array<Item, LISTMAXTOTAL> m_items;
std::vector<Item> m_items;
};


@@ -153,7 +153,7 @@ bool CScreenPlayerSelect::EventProcess(const Event &event)
CWindow* pw;
CList* pl;
std::string name;
char* gamer;
std::string gamer;

switch( event.type )
{
@@ -289,7 +289,7 @@ void CScreenPlayerSelect::UpdateNameList()
for ( i=0 ; i<total ; i++ )
{
// TODO: stricmp?
if ( strcmp(name, pl->GetItemName(i)) == 0 )
if ( name == pl->GetItemName(i) )
{
pl->SetSelect(i);
pl->ShowSelect(false);
@@ -307,7 +307,7 @@ void CScreenPlayerSelect::UpdateNameEdit()
CWindow* pw;
CList* pl;
CEdit* pe;
char* name;
std::string name;
int sel;

pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
@@ -326,8 +326,8 @@ void CScreenPlayerSelect::UpdateNameEdit()
else
{
name = pl->GetItemName(sel);
pe->SetText(name);
pe->SetCursor(strlen(name), 0);
pe->SetText(name.c_str());
pe->SetCursor(name.length(), 0);
}

UpdateNameControl();
@@ -434,7 +434,7 @@ void CScreenPlayerSelect::NameDelete()
return;
}

char* gamer = pl->GetItemName(sel);
std::string gamer = pl->GetItemName(sel);

m_main->SelectPlayer(gamer);
if (!m_main->GetPlayerProfile()->Delete())

0 comments on commit fef8a8e

Please sign in to comment.