Skip to content

Commit

Permalink
Don't leak references to Strings on script errors (#583)
Browse files Browse the repository at this point in the history
  • Loading branch information
Günther Brammer committed Apr 24, 2016
1 parent 5fbac34 commit e22ca51
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 41 deletions.
24 changes: 12 additions & 12 deletions src/script/C4AulParse.cpp
Expand Up @@ -1074,7 +1074,7 @@ C4V_Type C4AulParse::GetLastRetType(C4V_Type to)


C4AulBCC C4AulParse::MakeSetter(bool fLeaveValue) C4AulBCC C4AulParse::MakeSetter(bool fLeaveValue)
{ {
if(Type != PARSER) { C4AulBCC Dummy; Dummy.bccType = AB_ERR; return Dummy; } if(Type != PARSER) { return C4AulBCC(AB_ERR, 0); }
C4AulBCC Value = *(Fn->GetLastCode()), Setter = Value; C4AulBCC Value = *(Fn->GetLastCode()), Setter = Value;
// Check type // Check type
switch (Value.bccType) switch (Value.bccType)
Expand All @@ -1089,11 +1089,9 @@ C4AulBCC C4AulParse::MakeSetter(bool fLeaveValue)
case AB_STACK_SET: Setter.bccType = AB_STACK_SET; break; case AB_STACK_SET: Setter.bccType = AB_STACK_SET; break;
case AB_LOCALN: case AB_LOCALN:
Setter.bccType = AB_LOCALN_SET; Setter.bccType = AB_LOCALN_SET;
Setter.Par.s->IncRef(); // so string isn't dropped by RemoveLastBCC, see also C4AulScript::AddBCC
break; break;
case AB_PROP: case AB_PROP:
Setter.bccType = AB_PROP_SET; Setter.bccType = AB_PROP_SET;
Setter.Par.s->IncRef(); // so string isn't dropped by RemoveLastBCC, see also C4AulScript::AddBCC
break; break;
case AB_GLOBALN: Setter.bccType = AB_GLOBALN_SET; break; case AB_GLOBALN: Setter.bccType = AB_GLOBALN_SET; break;
default: default:
Expand Down Expand Up @@ -2390,15 +2388,17 @@ void C4AulParse::Parse_Expression(int iParentPrio)
Fn->GetLastCode()->Par.i = - Fn->GetLastCode()->Par.i; Fn->GetLastCode()->Par.i = - Fn->GetLastCode()->Par.i;
break; break;
} }
// changer? make a setter BCC, leave value for operator {
C4AulBCC Changer; // changer? make a setter BCC, leave value for operator
if(op->Changer) C4AulBCC Changer;
Changer = MakeSetter(true); if(op->Changer)
// write byte code Changer = MakeSetter(true);
AddBCC(op->Code, 0); // write byte code
// writter setter AddBCC(op->Code, 0);
if(op->Changer) // writter setter
AddBCC(Changer.bccType, Changer.Par.X); if(op->Changer)
AddBCC(Changer.bccType, Changer.Par.X);
}
break; break;
case ATT_BOPEN: case ATT_BOPEN:
Shift(); Shift();
Expand Down
28 changes: 1 addition & 27 deletions src/script/C4AulScriptFunc.cpp
Expand Up @@ -62,38 +62,12 @@ void C4AulScriptFunc::SetOverloaded(C4AulFunc * f)
void C4AulScriptFunc::AddBCC(C4AulBCCType eType, intptr_t X, const char * SPos) void C4AulScriptFunc::AddBCC(C4AulBCCType eType, intptr_t X, const char * SPos)
{ {
// store chunk // store chunk
C4AulBCC bcc; Code.emplace_back(eType, X);
bcc.bccType = eType;
bcc.Par.X = X;
Code.push_back(bcc);
PosForCode.push_back(SPos); PosForCode.push_back(SPos);

switch (eType)
{
case AB_STRING: case AB_CALL: case AB_CALLFS: case AB_LOCALN: case AB_PROP:
/* case AB_LOCALN_SET/AB_PROP_SET: -- expected to already have a reference upon creation, see MakeSetter */
bcc.Par.s->IncRef();
break;
case AB_CARRAY:
bcc.Par.a->IncRef();
break;
default: break;
}
} }


void C4AulScriptFunc::RemoveLastBCC() void C4AulScriptFunc::RemoveLastBCC()
{ {
C4AulBCC *pBCC = &Code.back();
switch (pBCC->bccType)
{
case AB_STRING: case AB_CALL: case AB_CALLFS: case AB_LOCALN: case AB_LOCALN_SET: case AB_PROP: case AB_PROP_SET:
pBCC->Par.s->DecRef();
break;
case AB_CARRAY:
pBCC->Par.a->DecRef();
break;
default: break;
}
Code.pop_back(); Code.pop_back();
PosForCode.pop_back(); PosForCode.pop_back();
} }
Expand Down
62 changes: 60 additions & 2 deletions src/script/C4AulScriptFunc.h
Expand Up @@ -93,18 +93,76 @@ enum C4AulBCCType
}; };


// byte code chunk // byte code chunk
struct C4AulBCC class C4AulBCC
{ {
public:
C4AulBCCType bccType; // chunk type C4AulBCCType bccType; // chunk type
union union
{ {
intptr_t X;
int32_t i; int32_t i;
C4String * s; C4String * s;
C4PropList * p; C4PropList * p;
C4ValueArray * a; C4ValueArray * a;
C4AulFunc * f; C4AulFunc * f;
intptr_t X;
} Par; // extra info } Par; // extra info
C4AulBCC(): bccType(AB_ERR) { }
C4AulBCC(C4AulBCCType bccType, intptr_t X): bccType(bccType), Par{X}
{
IncRef();
}
C4AulBCC(const C4AulBCC & from): C4AulBCC(from.bccType, from.Par.X) { }
C4AulBCC & operator = (const C4AulBCC & from)
{
DecRef();
bccType = from.bccType;
Par = from.Par;
IncRef();
return *this;
}
C4AulBCC(C4AulBCC && from): bccType(from.bccType), Par(from.Par)
{
from.bccType = AB_ERR;
}
C4AulBCC & operator = (C4AulBCC && from)
{
DecRef();
bccType = from.bccType;
Par = from.Par;
from.bccType = AB_ERR;
return *this;
}
~C4AulBCC()
{
DecRef();
}
private:
void IncRef()
{
switch (bccType)
{
case AB_STRING: case AB_CALL: case AB_CALLFS: case AB_LOCALN: case AB_LOCALN_SET: case AB_PROP: case AB_PROP_SET:
Par.s->IncRef();
break;
case AB_CARRAY:
Par.a->IncRef();
break;
default: break;
}
}
void DecRef()
{
switch (bccType)
{
case AB_STRING: case AB_CALL: case AB_CALLFS: case AB_LOCALN: case AB_LOCALN_SET: case AB_PROP: case AB_PROP_SET:
Par.s->DecRef();
break;
case AB_CARRAY:
Par.a->DecRef();
break;
default: break;
}
}
}; };


// script function class // script function class
Expand Down

0 comments on commit e22ca51

Please sign in to comment.