Safely call script functions

This commit is contained in:
momo5502 2019-01-17 21:05:48 +01:00
parent fcc8971d43
commit e51f7afa3d
5 changed files with 38 additions and 16 deletions

View File

@ -36,6 +36,9 @@ namespace game
unsigned int* levelEntityId; unsigned int* levelEntityId;
int* g_script_error_level;
jmp_buf* g_script_error;
void AddRefToValue(VariableValue* value) void AddRefToValue(VariableValue* value)
{ {
if (value->type == SCRIPT_OBJECT) if (value->type == SCRIPT_OBJECT)
@ -153,6 +156,9 @@ namespace game
native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x184CDB0, 0x1D4F258, 0x1BF59C8)); native::scr_instanceFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x184CDB0, 0x1D4F258, 0x1BF59C8));
native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x186C68C, 0x1D6EB34, 0x1C152A4)); native::scr_globalFunctions = reinterpret_cast<native::scr_call_t*>(SELECT_VALUE(0x186C68C, 0x1D6EB34, 0x1C152A4));
native::g_script_error_level = reinterpret_cast<int*>(SELECT_VALUE(0x1BEFCFC, 0x20B21FC, 0x1F5B058));
native::g_script_error = reinterpret_cast<jmp_buf*>(SELECT_VALUE(0x1BF1D18, 0x20B4218, 0x1F5A818));
native::levelEntityId = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BCBCA4, 0x208E1A4, 0x1CD873C)); native::levelEntityId = reinterpret_cast<unsigned int*>(SELECT_VALUE(0x1BCBCA4, 0x208E1A4, 0x1CD873C));
} }
} }

View File

@ -48,6 +48,9 @@ namespace game
extern unsigned int* levelEntityId; extern unsigned int* levelEntityId;
extern int* g_script_error_level;
extern jmp_buf* g_script_error;
void AddRefToValue(VariableValue* value); void AddRefToValue(VariableValue* value);
void Scr_ClearOutParams(); void Scr_ClearOutParams();

View File

@ -77,7 +77,7 @@ void notification::vm_notify_stub(const unsigned int notify_id, const unsigned s
} }
catch (std::exception& e) catch (std::exception& e)
{ {
scripting::propagate_scripting_error(e); scripting::propagate_error(e);
} }
} }

View File

@ -75,7 +75,7 @@ void scripting::post_start()
} }
catch (std::exception& e) catch (std::exception& e)
{ {
propagate_scripting_error(e); propagate_error(e);
} }
}); });
on_stop([this]() on_stop([this]()
@ -225,7 +225,7 @@ void scripting::on_stop(const std::function<void()>& callback)
stop_callbacks_.push_back(callback); stop_callbacks_.push_back(callback);
} }
void scripting::propagate_scripting_error(const std::exception& e) void scripting::propagate_error(const std::exception& e)
{ {
printf("\n******* Script execution error *******\n"); printf("\n******* Script execution error *******\n");
printf("%s\n", e.what()); printf("%s\n", e.what());
@ -269,7 +269,7 @@ void scripting::call(const std::string& function, const unsigned int entity_id,
const int function_index = find_function_index(function); const int function_index = find_function_index(function);
if (function_index < 0) if (function_index < 0)
{ {
throw std::runtime_error("No function found for name " + function); throw std::runtime_error("No function found for name '" + function + "'");
} }
const game::native::scr_entref_t entity = function_index > 0x1C7 const game::native::scr_entref_t entity = function_index > 0x1C7
@ -278,20 +278,32 @@ void scripting::call(const std::string& function, const unsigned int entity_id,
const auto function_ptr = game::native::Scr_GetFunc(function_index); const auto function_ptr = game::native::Scr_GetFunc(function_index);
/*static_assert(sizeof(jmp_buf) == 64); if(!call_safe(function_ptr, entity))
++*(DWORD*)0x20B21FC;
int res = setjmp(((jmp_buf*)0x20B4218)[*(DWORD*)0x20B21FC]);
if (res)
{ {
--*(DWORD*)0x20B21FC; throw std::runtime_error("Error executing function '" + function + "'");
return; }
}*/
function_ptr(entity.val);
//--*(DWORD*)0x20B21FC;
} }
#pragma warning(push)
#pragma warning(disable: 4611)
bool scripting::call_safe(const game::native::scr_call_t function, const game::native::scr_entref_t entref)
{
static_assert(sizeof(jmp_buf) == 64);
*game::native::g_script_error_level += 1;
if (setjmp(game::native::g_script_error[*game::native::g_script_error_level]))
{
*game::native::g_script_error_level -= 1;
return false;
}
function(entref.val);
*game::native::g_script_error_level -= 1;
return true;
}
#pragma warning(pop)
int scripting::find_function_index(const std::string& function) int scripting::find_function_index(const std::string& function)
{ {
auto function_entry = game::scripting::instance_function_map.find(function); auto function_entry = game::scripting::instance_function_map.find(function);

View File

@ -56,7 +56,7 @@ public:
static void on_start(const std::function<void()>& callback); static void on_start(const std::function<void()>& callback);
static void on_stop(const std::function<void()>& callback); static void on_stop(const std::function<void()>& callback);
static void propagate_scripting_error(const std::exception& e); static void propagate_error(const std::exception& e);
private: private:
std::unique_ptr<chaiscript::ChaiScript> chai_; std::unique_ptr<chaiscript::ChaiScript> chai_;
@ -80,5 +80,6 @@ private:
static void stop_execution(); static void stop_execution();
static void call(const std::string& function, unsigned int entity_id, const std::vector<chaiscript::Boxed_Value>& arguments); static void call(const std::string& function, unsigned int entity_id, const std::vector<chaiscript::Boxed_Value>& arguments);
static bool call_safe(game::native::scr_call_t function, game::native::scr_entref_t entref);
static int find_function_index(const std::string& function); static int find_function_index(const std::string& function);
}; };