[colobot] 44/100: Fix game crashing with syntax errors
Didier Raboud
odyx at moszumanska.debian.org
Thu Jun 1 18:10:17 UTC 2017
This is an automated email from the git hooks/post-receive script.
odyx pushed a commit to branch debian/master
in repository colobot.
commit 2ff8251a811b6da93062bb885b8978afade0ef12
Author: melex750 <melex750 at users.noreply.github.com>
Date: Tue Jan 24 13:47:00 2017 -0500
Fix game crashing with syntax errors
---
po/colobot.pot | 3 ++
po/de.po | 3 ++
po/fr.po | 3 ++
po/pl.po | 3 ++
po/ru.po | 3 ++
src/CBot/CBotClass.cpp | 25 ++++++----
src/CBot/CBotDefParam.cpp | 10 ++--
src/CBot/CBotEnums.h | 1 +
src/CBot/CBotInstr/CBotFunction.cpp | 15 +++---
src/CBot/CBotInstr/CBotListInstr.cpp | 2 +-
src/CBot/CBotToken.cpp | 7 +++
src/common/restext.cpp | 1 +
test/unit/CBot/CBotToken_test.cpp | 2 +-
test/unit/CBot/CBot_test.cpp | 90 ++++++++++++++++++++++++++++++++++++
14 files changed, 144 insertions(+), 24 deletions(-)
diff --git a/po/colobot.pot b/po/colobot.pot
index fd5c3de..04eda13 100644
--- a/po/colobot.pot
+++ b/po/colobot.pot
@@ -1739,6 +1739,9 @@ msgstr ""
msgid "Function needs return type \"void\""
msgstr ""
+msgid "Class name expected"
+msgstr ""
+
msgid "Dividing by zero"
msgstr ""
diff --git a/po/de.po b/po/de.po
index e4c105a..440febf 100644
--- a/po/de.po
+++ b/po/de.po
@@ -356,6 +356,9 @@ msgstr ""
msgid "Checkpoint"
msgstr "Checkpoint"
+msgid "Class name expected"
+msgstr ""
+
msgid "Climb\\Increases the power of the jet"
msgstr "Steigen\\Leistung des Triebwerks steigern"
diff --git a/po/fr.po b/po/fr.po
index 905a016..98c7549 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -346,6 +346,9 @@ msgstr "Console de triche\\Montre la console de triche"
msgid "Checkpoint"
msgstr "Indicateur"
+msgid "Class name expected"
+msgstr ""
+
msgid "Climb\\Increases the power of the jet"
msgstr "Monter\\Augmenter la puissance du réacteur"
diff --git a/po/pl.po b/po/pl.po
index cd9f37c..f298098 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -348,6 +348,9 @@ msgstr "Konsola komend\\Pokaż konsolę komend"
msgid "Checkpoint"
msgstr "Punkt kontrolny"
+msgid "Class name expected"
+msgstr ""
+
msgid "Climb\\Increases the power of the jet"
msgstr "W górę\\Zwiększa moc silnika"
diff --git a/po/ru.po b/po/ru.po
index 233cb30..4042a18 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -353,6 +353,9 @@ msgstr "Консоль чит-кодов\\Показать консоль для
msgid "Checkpoint"
msgstr "Контрольная точка"
+msgid "Class name expected"
+msgstr ""
+
msgid "Climb\\Increases the power of the jet"
msgstr "Взлет и подъем\\Увеличивает мощность реактивного двигателя"
diff --git a/src/CBot/CBotClass.cpp b/src/CBot/CBotClass.cpp
index c19cbf4..d787eb7 100644
--- a/src/CBot/CBotClass.cpp
+++ b/src/CBot/CBotClass.cpp
@@ -471,26 +471,27 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
std::string name = p->GetString();
- CBotClass* pOld = CBotClass::Find(name);
- if ( (pOld != nullptr && pOld->m_IsDef) || /* public class exists in different program */
- pStack->GetProgram()->ClassExists(name)) /* class exists in this program */
- {
- pStack->SetError( CBotErrRedefClass, p );
- return nullptr;
- }
-
// a name of the class is there?
if (IsOfType(p, TokenTypVar))
{
+ CBotClass* pOld = CBotClass::Find(name);
+ if ((pOld != nullptr && pOld->m_IsDef) || /* public class exists in different program */
+ pStack->GetProgram()->ClassExists(name)) /* class exists in this program */
+ {
+ pStack->SetError(CBotErrRedefClass, p->GetPrev());
+ return nullptr;
+ }
+
CBotClass* pPapa = nullptr;
if ( IsOfType( p, ID_EXTENDS ) )
{
std::string name = p->GetString();
pPapa = CBotClass::Find(name);
+ CBotToken* pp = p;
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr )
{
- pStack->SetError( CBotErrNotClass, p );
+ pStack->SetError(CBotErrNoClassName, pp);
return nullptr;
}
}
@@ -519,6 +520,9 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
if (pStack->IsOk()) return classe;
}
+ else
+ pStack->SetError(CBotErrNoClassName, p);
+
pStack->SetError(CBotErrNoTerminator, p);
return nullptr;
}
@@ -810,10 +814,11 @@ CBotClass* CBotClass::Compile(CBotToken* &p, CBotCStack* pStack)
// TODO: Not sure how correct is that - I have no idea how the precompilation (Compile1 method) works ~krzys_h
std::string name = p->GetString();
CBotClass* pPapa = CBotClass::Find(name);
+ CBotToken* pp = p;
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr)
{
- pStack->SetError( CBotErrNotClass, p );
+ pStack->SetError(CBotErrNoClassName, pp);
return nullptr;
}
pOld->m_parent = pPapa;
diff --git a/src/CBot/CBotDefParam.cpp b/src/CBot/CBotDefParam.cpp
index ff4acf1..e66c862 100644
--- a/src/CBot/CBotDefParam.cpp
+++ b/src/CBot/CBotDefParam.cpp
@@ -52,7 +52,7 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
{
CBotDefParam* list = nullptr;
- while (!IsOfType(p, ID_CLOSEPAR))
+ if (!IsOfType(p, ID_CLOSEPAR)) while (true)
{
CBotDefParam* param = new CBotDefParam();
if (list == nullptr) list = param;
@@ -85,10 +85,12 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
var->SetUniqNum(param->m_nIdent);
pStack->AddVar(var); // place on the stack
- if (IsOfType(p, ID_COMMA) || p->GetType() == ID_CLOSEPAR)
- continue;
+ if (IsOfType(p, ID_COMMA)) continue;
+ if (IsOfType(p, ID_CLOSEPAR)) break;
+
+ pStack->SetError(CBotErrClosePar, p->GetStart());
}
- pStack->SetError(CBotErrClosePar, p->GetStart());
+ pStack->SetError(CBotErrNoVar, p->GetStart());
}
pStack->SetError(CBotErrNoType, p);
delete list;
diff --git a/src/CBot/CBotEnums.h b/src/CBot/CBotEnums.h
index b7453e5..a34c9e7 100644
--- a/src/CBot/CBotEnums.h
+++ b/src/CBot/CBotEnums.h
@@ -238,6 +238,7 @@ enum CBotError : int
CBotErrNoExpression = 5043, //!< expression expected after =
CBotErrAmbiguousCall = 5044, //!< ambiguous call to overloaded function
CBotErrFuncNotVoid = 5045, //!< function needs return type "void"
+ CBotErrNoClassName = 5046, //!< class name expected
// Runtime errors
CBotErrZeroDiv = 6000, //!< division by zero
diff --git a/src/CBot/CBotInstr/CBotFunction.cpp b/src/CBot/CBotInstr/CBotFunction.cpp
index ddbd366..f08ddd9 100644
--- a/src/CBot/CBotInstr/CBotFunction.cpp
+++ b/src/CBot/CBotInstr/CBotFunction.cpp
@@ -177,7 +177,11 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
func->m_MasterClass = pp->GetString();
func->m_classToken = *pp;
CBotClass* pClass = CBotClass::Find(pp);
- if ( pClass == nullptr ) goto bad;
+ if ( pClass == nullptr )
+ {
+ pStk->SetError(CBotErrNoClassName, pp);
+ goto bad;
+ }
// pp = p;
func->m_token = *p;
@@ -280,13 +284,8 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class
{
func->m_MasterClass = pp->GetString();
- CBotClass* pClass = CBotClass::Find(pp);
- if ( pClass == nullptr )
- {
- pStk->SetError(CBotErrNotClass, pp);
- goto bad;
- }
-
+ // existence of the class is checked
+ // later in CBotFunction::Compile()
pp = p;
func->m_token = *p;
if (!IsOfType(p, TokenTypVar)) goto bad;
diff --git a/src/CBot/CBotInstr/CBotListInstr.cpp b/src/CBot/CBotInstr/CBotListInstr.cpp
index 58413a4..0ae396f 100644
--- a/src/CBot/CBotInstr/CBotListInstr.cpp
+++ b/src/CBot/CBotInstr/CBotListInstr.cpp
@@ -52,7 +52,7 @@ CBotInstr* CBotListInstr::Compile(CBotToken* &p, CBotCStack* pStack, bool bLocal
if (IsOfType(p, ID_SEP)) continue; // empty statement ignored
if (p->GetType() == ID_CLBLK) break;
- if (IsOfType(p, 0))
+ if (p->GetType() == TokenTypNone)
{
pStack->SetError(CBotErrCloseBlock, p->GetStart());
delete inst;
diff --git a/src/CBot/CBotToken.cpp b/src/CBot/CBotToken.cpp
index 28e6690..e10901e 100644
--- a/src/CBot/CBotToken.cpp
+++ b/src/CBot/CBotToken.cpp
@@ -439,6 +439,13 @@ std::unique_ptr<CBotToken> CBotToken::CompileTokens(const std::string& program)
pp = p;
}
+ // terminator token
+ nxt = new CBotToken();
+ nxt->m_type = TokenTypNone;
+ nxt->m_end = nxt->m_start = pos;
+ prv->m_next = nxt;
+ nxt->m_prev = prv;
+
return std::unique_ptr<CBotToken>(tokenbase);
}
diff --git a/src/common/restext.cpp b/src/common/restext.cpp
index 789c68a..93bab6c 100644
--- a/src/common/restext.cpp
+++ b/src/common/restext.cpp
@@ -720,6 +720,7 @@ void InitializeRestext()
stringsCbot[CBot::CBotErrNoExpression] = TR("Expression expected after =");
stringsCbot[CBot::CBotErrAmbiguousCall] = TR("Ambiguous call to overloaded function");
stringsCbot[CBot::CBotErrFuncNotVoid] = TR("Function needs return type \"void\"");
+ stringsCbot[CBot::CBotErrNoClassName] = TR("Class name expected");
stringsCbot[CBot::CBotErrZeroDiv] = TR("Dividing by zero");
stringsCbot[CBot::CBotErrNotInit] = TR("Variable not initialized");
diff --git a/test/unit/CBot/CBotToken_test.cpp b/test/unit/CBot/CBotToken_test.cpp
index b51ca93..a36841a 100644
--- a/test/unit/CBot/CBotToken_test.cpp
+++ b/test/unit/CBot/CBotToken_test.cpp
@@ -60,7 +60,7 @@ protected:
ASSERT_EQ(token->GetType(), correct.type) << "type mismatch at token #" << (i+1);
i++;
}
- while((token = token->GetNext()) != nullptr);
+ while((token = token->GetNext()) != nullptr && !IsOfType(token, TokenTypNone));
ASSERT_EQ(i, data.size()) << "not enough tokens processed";
}
};
diff --git a/test/unit/CBot/CBot_test.cpp b/test/unit/CBot/CBot_test.cpp
index ca9ff91..71455e2 100644
--- a/test/unit/CBot/CBot_test.cpp
+++ b/test/unit/CBot/CBot_test.cpp
@@ -298,6 +298,96 @@ TEST_F(CBotUT, EmptyTest)
);
}
+TEST_F(CBotUT, FunctionCompileErrors)
+{
+ ExecuteTest(
+ "public",
+ CBotErrNoType
+ );
+
+ ExecuteTest(
+ "extern",
+ CBotErrNoType
+ );
+
+ ExecuteTest(
+ "public void",
+ CBotErrNoFunc
+ );
+
+ ExecuteTest(
+ "extern void",
+ CBotErrNoFunc
+ );
+
+ ExecuteTest(
+ "extern void MissingParameterType(",
+ CBotErrNoType
+ );
+
+ ExecuteTest(
+ "extern void MissingParamName(int",
+ CBotErrNoVar
+ );
+
+ ExecuteTest(
+ "extern void MissingCloseParen(int i",
+ CBotErrClosePar
+ );
+
+ ExecuteTest(
+ "extern void ParamTrailingComma(int i, ) {\n"
+ "}\n",
+ CBotErrNoType
+ );
+
+ ExecuteTest(
+ "extern void MissingOpenBlock(int i)",
+ CBotErrOpenBlock
+ );
+
+ ExecuteTest(
+ "extern void MissingCloseBlock()\n"
+ "{\n",
+ CBotErrCloseBlock
+ );
+
+}
+
+TEST_F(CBotUT, ClassCompileErrors)
+{
+ ExecuteTest(
+ "public class",
+ CBotErrNoClassName
+ );
+
+ ExecuteTest(
+ "public class 1234",
+ CBotErrNoClassName
+ );
+
+ ExecuteTest(
+ "public class TestClass",
+ CBotErrOpenBlock
+ );
+
+ ExecuteTest(
+ "public class TestClass\n"
+ "{\n",
+ CBotErrCloseBlock
+ );
+
+ ExecuteTest(
+ "public class TestClass extends",
+ CBotErrNoClassName
+ );
+
+ ExecuteTest(
+ "public class TestClass extends 1234",
+ CBotErrNoClassName
+ );
+}
+
TEST_F(CBotUT, DivideByZero)
{
ExecuteTest(
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/colobot.git
More information about the Pkg-games-commits
mailing list