From 2b5fea4ea8f4d9efbec62323e26020e283ab42cc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 5 Mar 2017 21:44:10 +0100 Subject: [PATCH] - added version checks for function calls and virtual overrides. - restricted the UI functions in inventory. --- src/scripting/backend/codegen.cpp | 45 ++++++++++++++++--- src/scripting/backend/codegen.h | 10 +++-- src/scripting/backend/vmbuilder.cpp | 2 +- src/scripting/zscript/zcc_compile.cpp | 7 ++- wadsrc/static/zscript/inventory/inventory.txt | 4 +- 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index db834d146..06f8757c3 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -388,7 +388,7 @@ bool FxExpression::isConstant() const // //========================================================================== -VMFunction *FxExpression::GetDirectFunction() +VMFunction *FxExpression::GetDirectFunction(const VersionInfo &ver) { return nullptr; } @@ -6065,6 +6065,7 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classct } if ((vsym->Flags & VARF_Deprecated) && sym->mVersion >= ctx.Version) { + ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s - deprecated since %d.%d.%d", sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision); ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars()); } @@ -8495,19 +8496,44 @@ PPrototype *FxVMFunctionCall::ReturnProto() return Function->Variants[0].Proto; } + +bool FxVMFunctionCall::CheckAccessibility(const VersionInfo &ver) +{ + if (Function->mVersion > ver && !(Function->Variants[0].Flags & VARF_Deprecated)) + { + FString VersionString; + if (ver >= MakeVersion(2, 3)) + { + VersionString.Format("ZScript version %d.%d.%d", ver.major, ver.minor, ver.revision); + } + else + { + VersionString = "DECORATE"; + } + ScriptPosition.Message(MSG_ERROR, "%s not accessible to %s", Function->SymbolName.GetChars(), VersionString.GetChars()); + return false; + } + if ((Function->Variants[0].Flags & VARF_Deprecated) && Function->mVersion >= ver) + { + ScriptPosition.Message(MSG_WARNING, "Accessing deprecated function %s - deprecated since %d.%d.%d", Function->SymbolName.GetChars(), Function->mVersion.major, Function->mVersion.minor, Function->mVersion.revision); + return false; + } + return true; +} //========================================================================== // // // //========================================================================== -VMFunction *FxVMFunctionCall::GetDirectFunction() +VMFunction *FxVMFunctionCall::GetDirectFunction(const VersionInfo &ver) { // If this return statement calls a non-virtual function with no arguments, // then it can be a "direct" function. That is, the DECORATE // definition can call that function directly without wrapping // it inside VM code. - if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual)) + + if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual) && CheckAccessibility(ver)) { unsigned imp = Function->GetImplicitArgs(); if (Function->Variants[0].ArgFlags.Size() > imp && !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr; @@ -8536,6 +8562,11 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) int implicit = Function->GetImplicitArgs(); + if (!CheckAccessibility(ctx.Version)) + { + delete this; + return false; + } // This should never happen. if (Self == nullptr && (Function->Variants[0].Flags & VARF_Method)) { @@ -9372,11 +9403,11 @@ ExpEmit FxSequence::Emit(VMFunctionBuilder *build) // //========================================================================== -VMFunction *FxSequence::GetDirectFunction() +VMFunction *FxSequence::GetDirectFunction(const VersionInfo &ver) { if (Expressions.Size() == 1) { - return Expressions[0]->GetDirectFunction(); + return Expressions[0]->GetDirectFunction(ver); } return nullptr; } @@ -10358,11 +10389,11 @@ ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build) return out; } -VMFunction *FxReturnStatement::GetDirectFunction() +VMFunction *FxReturnStatement::GetDirectFunction(const VersionInfo &ver) { if (Args.Size() == 1) { - return Args[0]->GetDirectFunction(); + return Args[0]->GetDirectFunction(ver); } return nullptr; } diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 5c6fb8ddd..0861ee4ed 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -324,7 +324,7 @@ public: virtual bool isConstant() const; virtual bool RequestAddress(FCompileContext &ctx, bool *writable); virtual PPrototype *ReturnProto(); - virtual VMFunction *GetDirectFunction(); + virtual VMFunction *GetDirectFunction(const VersionInfo &ver); virtual bool CheckReturn() { return false; } virtual int GetBitValue() { return -1; } bool IsNumeric() const { return ValueType->isNumeric(); } @@ -1714,12 +1714,14 @@ class FxVMFunctionCall : public FxExpression TArray ReturnRegs; PFunction *CallingFunction; + bool CheckAccessibility(const VersionInfo &ver); + public: FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual); ~FxVMFunctionCall(); FxExpression *Resolve(FCompileContext&); PPrototype *ReturnProto(); - VMFunction *GetDirectFunction(); + VMFunction *GetDirectFunction(const VersionInfo &ver); ExpEmit Emit(VMFunctionBuilder *build); bool CheckEmitCast(VMFunctionBuilder *build, bool returnit, ExpEmit ®); TArray &GetReturnTypes() const @@ -1744,7 +1746,7 @@ public: FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); expr->NeedResult = false; } - VMFunction *GetDirectFunction(); + VMFunction *GetDirectFunction(const VersionInfo &ver); bool CheckReturn(); }; @@ -1951,7 +1953,7 @@ public: ~FxReturnStatement(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build); - VMFunction *GetDirectFunction(); + VMFunction *GetDirectFunction(const VersionInfo &ver); bool CheckReturn() { return true; } }; diff --git a/src/scripting/backend/vmbuilder.cpp b/src/scripting/backend/vmbuilder.cpp index df53e51ed..31290cc48 100644 --- a/src/scripting/backend/vmbuilder.cpp +++ b/src/scripting/backend/vmbuilder.cpp @@ -804,7 +804,7 @@ FFunctionBuildList FunctionBuildList; VMFunction *FFunctionBuildList::AddFunction(PNamespace *gnspc, const VersionInfo &ver, PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate, int stateindex, int statecount, int lumpnum) { - auto func = code->GetDirectFunction(); + auto func = code->GetDirectFunction(ver); if (func != nullptr) { delete code; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 0695b2070..fc8794aac 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -611,7 +611,7 @@ void ZCCCompiler::CreateClassTypes() { if (parent->mVersion > mVersion) { - Error(c->cls, "Parent class %s of %s not accessible to ZScript version %d.%d.%d", parent->GetClass()->TypeName.GetChars(), c->NodeName().GetChars(), mVersion.major, mVersion.minor, mVersion.revision); + Error(c->cls, "Parent class %s of %s not accessible to ZScript version %d.%d.%d", parent->TypeName.GetChars(), c->NodeName().GetChars(), mVersion.major, mVersion.minor, mVersion.revision); } c->cls->Type = parent->CreateDerivedClass(c->NodeName(), TentativeClass); if (c->Type() == nullptr) @@ -2493,6 +2493,11 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool else { auto oldfunc = clstype->Virtuals[vindex]; + auto parentfunc = dyn_cast(clstype->ParentClass->Symbols.FindSymbol(sym->SymbolName, true)); + if (parentfunc && parentfunc->mVersion > mVersion) + { + Error(f, "Attempt to override function %s which is incompatible with version %d.%d.%d", FName(f->Name).GetChars(), mVersion.major, mVersion.minor, mVersion.revision); + } if (oldfunc->VarFlags & VARF_Final) { Error(f, "Attempt to override final function %s", FName(f->Name).GetChars()); diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index 16a83c7a5..722f3158b 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -751,7 +751,7 @@ class Inventory : Actor native virtual bool Use (bool pickup) { return false; } virtual double GetSpeedFactor() { return 1; } virtual bool GetNoTeleportFreeze() { return false; } - virtual ui void AlterWeaponSprite(VisStyle vis, in out int changed) {} + virtual version("2.4") ui void AlterWeaponSprite(VisStyle vis, in out int changed) {} virtual void OwnerDied() {} virtual Color GetBlend () { return 0; } @@ -818,7 +818,7 @@ class Inventory : Actor native // //=========================================================================== - virtual ui bool DrawPowerup(int x, int y) { return false; } + virtual ui version("2.4") bool DrawPowerup(int x, int y) { return false; } //=========================================================================== //