From db1970059948afe958689f496325d9228c7d8139 Mon Sep 17 00:00:00 2001
From: Evil Eye <malusluminis@hotmail.com>
Date: Sat, 30 Apr 2022 16:45:45 +0200
Subject: [PATCH] Make stack manipulation unconditional

---
 CHANGELOG.md                                  |   1 +
 apps/openmw/mwscript/cellextensions.cpp       |   2 +
 apps/openmw/mwscript/statsextensions.cpp      |   1 +
 .../mwscript/transformationextensions.cpp     | 140 ++++++++++--------
 4 files changed, 84 insertions(+), 60 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 26e52a1ea0..120df16b2e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -114,6 +114,7 @@
     Bug #6682: HitOnMe doesn't fire as intended
     Bug #6697: Shaders vertex lighting incorrectly clamped
     Bug #6711: Log time differs from real time
+    Bug #6717: Broken script causes interpreter stack corruption
     Feature #890: OpenMW-CS: Column filtering
     Feature #1465: "Reset" argument for AI functions
     Feature #2491: Ability to make OpenMW "portable"
diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp
index d5ac222244..f00fcfd447 100644
--- a/apps/openmw/mwscript/cellextensions.cpp
+++ b/apps/openmw/mwscript/cellextensions.cpp
@@ -208,6 +208,7 @@ namespace MWScript
                 void execute (Interpreter::Runtime& runtime) override
                 {
                     Interpreter::Type_Float level = runtime[0].mFloat;
+                    runtime.pop();
 
                     if (!MWMechanics::getPlayer().isInCell())
                     {
@@ -231,6 +232,7 @@ namespace MWScript
                 void execute (Interpreter::Runtime& runtime) override
                 {
                     Interpreter::Type_Float level = runtime[0].mFloat;
+                    runtime.pop();
 
                     if (!MWMechanics::getPlayer().isInCell())
                     {
diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp
index a62d40065d..08f4cd6f27 100644
--- a/apps/openmw/mwscript/statsextensions.cpp
+++ b/apps/openmw/mwscript/statsextensions.cpp
@@ -1208,6 +1208,7 @@ namespace MWScript
             void execute (Interpreter::Runtime& runtime) override
             {
                 // dummy
+                runtime.pop();
                 runtime.push(0);
             }
         };
diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp
index 9f2ecf9e34..c4e78dbc96 100644
--- a/apps/openmw/mwscript/transformationextensions.cpp
+++ b/apps/openmw/mwscript/transformationextensions.cpp
@@ -193,18 +193,23 @@ namespace MWScript
                     std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
                     runtime.pop();
 
-                    if (axis == "x")
+                    float ret = 0.f;
+                    if (!axis.empty())
                     {
-                        runtime.push(osg::RadiansToDegrees(ptr.getCellRef().getPosition().rot[0]));
-                    }
-                    else if (axis == "y")
-                    {
-                        runtime.push(osg::RadiansToDegrees(ptr.getCellRef().getPosition().rot[1]));
-                    }
-                    else if (axis == "z")
-                    {
-                        runtime.push(osg::RadiansToDegrees(ptr.getCellRef().getPosition().rot[2]));
+                        if (axis[0] == 'x')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getCellRef().getPosition().rot[0]);
+                        }
+                        else if (axis[0] == 'y')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getCellRef().getPosition().rot[1]);
+                        }
+                        else if (axis[0] == 'z')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getCellRef().getPosition().rot[2]);
+                        }
                     }
+                    runtime.push(ret);
                 }
         };
 
@@ -220,18 +225,23 @@ namespace MWScript
                     std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
                     runtime.pop();
 
-                    if (axis=="x")
+                    float ret = 0.f;
+                    if (!axis.empty())
                     {
-                        runtime.push(osg::RadiansToDegrees(ptr.getRefData().getPosition().rot[0]));
-                    }
-                    else if (axis=="y")
-                    {
-                        runtime.push(osg::RadiansToDegrees(ptr.getRefData().getPosition().rot[1]));
-                    }
-                    else if (axis=="z")
-                    {
-                        runtime.push(osg::RadiansToDegrees(ptr.getRefData().getPosition().rot[2]));
+                        if (axis[0] == 'x')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getRefData().getPosition().rot[0]);
+                        }
+                        else if (axis[0] == 'y')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getRefData().getPosition().rot[1]);
+                        }
+                        else if (axis[0] == 'z')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getRefData().getPosition().rot[2]);
+                        }
                     }
+                    runtime.push(ret);
                 }
         };
 
@@ -247,18 +257,23 @@ namespace MWScript
                     std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
                     runtime.pop();
 
-                    if(axis == "x")
+                    float ret = 0.f;
+                    if (!axis.empty())
                     {
-                        runtime.push(ptr.getRefData().getPosition().pos[0]);
-                    }
-                    else if(axis == "y")
-                    {
-                        runtime.push(ptr.getRefData().getPosition().pos[1]);
-                    }
-                    else if(axis == "z")
-                    {
-                        runtime.push(ptr.getRefData().getPosition().pos[2]);
+                        if (axis[0] == 'x')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getRefData().getPosition().pos[0]);
+                        }
+                        else if (axis[0] == 'y')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getRefData().getPosition().pos[1]);
+                        }
+                        else if (axis[0] == 'z')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getRefData().getPosition().pos[2]);
+                        }
                     }
+                    runtime.push(ret);
                 }
         };
 
@@ -271,14 +286,14 @@ namespace MWScript
                 {
                     MWWorld::Ptr ptr = R()(runtime);
 
-                    if (!ptr.isInCell())
-                        return;
-
                     std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
                     runtime.pop();
                     Interpreter::Type_Float pos = runtime[0].mFloat;
                     runtime.pop();
 
+                    if (!ptr.isInCell())
+                        return;
+
                     // Note: SetPos does not skip weather transitions in vanilla engine, so we do not call setTeleported(true) here.
 
                     const auto curPos = ptr.getRefData().getPosition().asVec3();
@@ -328,18 +343,23 @@ namespace MWScript
                     std::string axis = runtime.getStringLiteral (runtime[0].mInteger);
                     runtime.pop();
 
-                    if(axis == "x")
+                    float ret = 0.f;
+                    if (!axis.empty())
                     {
-                        runtime.push(ptr.getCellRef().getPosition().pos[0]);
-                    }
-                    else if(axis == "y")
-                    {
-                        runtime.push(ptr.getCellRef().getPosition().pos[1]);
-                    }
-                    else if(axis == "z")
-                    {
-                        runtime.push(ptr.getCellRef().getPosition().pos[2]);
+                        if (axis[0] == 'x')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getCellRef().getPosition().pos[0]);
+                        }
+                        else if (axis[0] == 'y')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getCellRef().getPosition().pos[1]);
+                        }
+                        else if (axis[0] == 'z')
+                        {
+                            ret = osg::RadiansToDegrees(ptr.getCellRef().getPosition().pos[2]);
+                        }
                     }
+                    runtime.push(ret);
                 }
         };
 
@@ -352,15 +372,6 @@ namespace MWScript
                 {
                     MWWorld::Ptr ptr = R()(runtime);
 
-                    if (ptr.getContainerStore())
-                        return;
-
-                    bool isPlayer = ptr == MWMechanics::getPlayer();
-                    if (isPlayer)
-                    {
-                        MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
-                    }
-
                     Interpreter::Type_Float x = runtime[0].mFloat;
                     runtime.pop();
                     Interpreter::Type_Float y = runtime[0].mFloat;
@@ -372,6 +383,15 @@ namespace MWScript
                     std::string cellID = runtime.getStringLiteral (runtime[0].mInteger);
                     runtime.pop();
 
+                    if (ptr.getContainerStore())
+                        return;
+
+                    bool isPlayer = ptr == MWMechanics::getPlayer();
+                    if (isPlayer)
+                    {
+                        MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
+                    }
+
                     MWWorld::CellStore* store = nullptr;
                     try
                     {
@@ -424,14 +444,6 @@ namespace MWScript
                 {
                     MWWorld::Ptr ptr = R()(runtime);
 
-                    if (!ptr.isInCell())
-                        return;
-
-                    if (ptr == MWMechanics::getPlayer())
-                    {
-                        MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
-                    }
-
                     Interpreter::Type_Float x = runtime[0].mFloat;
                     runtime.pop();
                     Interpreter::Type_Float y = runtime[0].mFloat;
@@ -440,6 +452,14 @@ namespace MWScript
                     runtime.pop();
                     Interpreter::Type_Float zRot = runtime[0].mFloat;
                     runtime.pop();
+
+                    if (!ptr.isInCell())
+                        return;
+
+                    if (ptr == MWMechanics::getPlayer())
+                    {
+                        MWBase::Environment::get().getWorld()->getPlayer().setTeleported(true);
+                    }
                     int cx,cy;
                     MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy);