Fix crash when including a script that nests proplists in a local variable

Previously, only the outer proplist would be copied, but the parser expects
the inner proplists to also be present. Copy proplists deeply instead, as
is already done for functions, and in the linking step.
Günther Brammer 2012-08-09 01:21:54 +02:00
parent bfdc02900c
commit 576edc1e23
2 changed files with 44 additions and 29 deletions

View File

@ -1973,11 +1973,7 @@ C4Value C4AulParse::Parse_ConstPropList(const C4PropListStatic * parent, C4Strin
throw new C4AulParseError(this, "internal error: constant proplist is not static");
if (p->GetParent() != parent || p->GetParentKeyName() != Name)
{
// the proplist is from another definition, so don't change it
// create a replacement for this defnition
// FIXME: shouldn't the copy be made in parse, like functions are handled?
v.SetPropList(C4PropList::NewAnon(NULL, parent, Name));
p = v.getPropList()->IsStatic();
throw new C4AulParseError(this, "internal error: constant proplist has the wrong parent");
}
// In case of script reloads
p->Thaw();
@ -2977,6 +2973,47 @@ bool C4AulScript::Parse()
return true;
}
void C4ScriptHost::CopyPropList(C4Set<C4Property> & from, C4PropListStatic * to)
{
// append all funcs and local variable initializations
const C4Property * prop = from.First();
while (prop)
{
switch(prop->Value.GetType())
{
case C4V_Function:
{
C4AulScriptFunc * sf = prop->Value.getFunction()->SFunc();
//assert(sf->pOrgScript == *s);
C4AulScriptFunc *sfc;
if (sf->pOrgScript != this)
sfc = new C4AulScriptFunc(this, *sf);
else
sfc = sf;
sfc->SetOverloaded(to->GetFunc(sf->Name));
to->SetPropertyByS(prop->Key, C4VFunction(sfc));
}
break;
case C4V_PropList:
{
C4PropListStatic * p = prop->Value._getPropList()->IsStatic();
assert(p);
if (prop->Key != &::Strings.P[P_Prototype])
if (!p || p->GetParent() != to)
{
p = C4PropList::NewAnon(NULL, to, prop->Key);
CopyPropList(prop->Value._getPropList()->Properties, p);
}
to->SetPropertyByS(prop->Key, C4VPropList(p));
}
case C4V_Array: // FIXME: copy the array if necessary
default:
to->SetPropertyByS(prop->Key, prop->Value);
}
prop = from.Next(prop);
}
}
bool C4ScriptHost::Parse()
{
// check state
@ -2996,30 +3033,7 @@ bool C4ScriptHost::Parse()
for (std::list<C4ScriptHost *>::iterator s = SourceScripts.begin(); s != SourceScripts.end(); ++s)
{
// append all funcs and local variable initializations
const C4Property * prop = (*s)->LocalValues.First();
while (prop)
{
switch(prop->Value.GetType())
{
case C4V_Function:
{
C4AulScriptFunc * sf = prop->Value.getFunction()->SFunc();
assert(sf->pOrgScript == *s);
C4AulScriptFunc *sfc;
if (sf->pOrgScript != this)
sfc = new C4AulScriptFunc(this, *sf);
else
sfc = sf;
sfc->SetOverloaded(p->GetFunc(sf->Name));
p->SetPropertyByS(prop->Key, C4VFunction(sfc));
}
break;
default:
p->SetPropertyByS(prop->Key, prop->Value);
}
prop = (*s)->LocalValues.Next(prop);
}
CopyPropList((*s)->LocalValues, p);
if (*s == this)
continue;
// definition appends

View File

@ -62,6 +62,7 @@ protected:
std::list<C4ID> Includes; // include list
std::list<C4ID> Appends; // append list
void CopyPropList(C4Set<C4Property> & from, C4PropListStatic * to);
bool ResolveIncludes(C4DefList *rDefs); // resolve includes
bool ResolveAppends(C4DefList *rDefs); // resolve appends
bool Resolving; // set while include-resolving, to catch circular includes