mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-10 08:00:05 +00:00
Change: Limit total script ops that can be consumed by a list valuate (#11670)
This commit is contained in:
parent
502a52edd5
commit
48b6b1844a
6
src/3rdparty/squirrel/squirrel/sqvm.cpp
vendored
6
src/3rdparty/squirrel/squirrel/sqvm.cpp
vendored
@ -116,6 +116,8 @@ SQVM::SQVM(SQSharedState *ss)
|
|||||||
_can_suspend = false;
|
_can_suspend = false;
|
||||||
_in_stackoverflow = false;
|
_in_stackoverflow = false;
|
||||||
_ops_till_suspend = 0;
|
_ops_till_suspend = 0;
|
||||||
|
_ops_till_suspend_error_threshold = INT64_MIN;
|
||||||
|
_ops_till_suspend_error_label = nullptr;
|
||||||
_callsstack = nullptr;
|
_callsstack = nullptr;
|
||||||
_callsstacksize = 0;
|
_callsstacksize = 0;
|
||||||
_alloccallsstacksize = 0;
|
_alloccallsstacksize = 0;
|
||||||
@ -744,6 +746,10 @@ exception_restore:
|
|||||||
{
|
{
|
||||||
DecreaseOps(1);
|
DecreaseOps(1);
|
||||||
if (ShouldSuspend()) { _suspended = SQTrue; _suspended_traps = traps; return true; }
|
if (ShouldSuspend()) { _suspended = SQTrue; _suspended_traps = traps; return true; }
|
||||||
|
if (IsOpsTillSuspendError()) {
|
||||||
|
Raise_Error(fmt::format("excessive CPU usage in {}", _ops_till_suspend_error_label));
|
||||||
|
SQ_THROW();
|
||||||
|
}
|
||||||
|
|
||||||
const SQInstruction &_i_ = *ci->_ip++;
|
const SQInstruction &_i_ = *ci->_ip++;
|
||||||
#ifdef _DEBUG_DUMP
|
#ifdef _DEBUG_DUMP
|
||||||
|
7
src/3rdparty/squirrel/squirrel/sqvm.h
vendored
7
src/3rdparty/squirrel/squirrel/sqvm.h
vendored
@ -168,6 +168,8 @@ public:
|
|||||||
|
|
||||||
SQBool _can_suspend;
|
SQBool _can_suspend;
|
||||||
SQInteger _ops_till_suspend;
|
SQInteger _ops_till_suspend;
|
||||||
|
SQInteger _ops_till_suspend_error_threshold;
|
||||||
|
const char *_ops_till_suspend_error_label;
|
||||||
SQBool _in_stackoverflow;
|
SQBool _in_stackoverflow;
|
||||||
|
|
||||||
bool ShouldSuspend()
|
bool ShouldSuspend()
|
||||||
@ -175,6 +177,11 @@ public:
|
|||||||
return _can_suspend && _ops_till_suspend <= 0;
|
return _can_suspend && _ops_till_suspend <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsOpsTillSuspendError()
|
||||||
|
{
|
||||||
|
return _ops_till_suspend < _ops_till_suspend_error_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
void DecreaseOps(SQInteger amount)
|
void DecreaseOps(SQInteger amount)
|
||||||
{
|
{
|
||||||
if (_ops_till_suspend - amount < _ops_till_suspend) _ops_till_suspend -= amount;
|
if (_ops_till_suspend - amount < _ops_till_suspend) _ops_till_suspend -= amount;
|
||||||
|
@ -11,7 +11,9 @@
|
|||||||
#include "script_list.hpp"
|
#include "script_list.hpp"
|
||||||
#include "script_controller.hpp"
|
#include "script_controller.hpp"
|
||||||
#include "../../debug.h"
|
#include "../../debug.h"
|
||||||
|
#include "../../core/backup_type.hpp"
|
||||||
#include "../../script/squirrel.hpp"
|
#include "../../script/squirrel.hpp"
|
||||||
|
#include <../squirrel/sqvm.h>
|
||||||
|
|
||||||
#include "../../safeguards.h"
|
#include "../../safeguards.h"
|
||||||
|
|
||||||
@ -866,6 +868,14 @@ SQInteger ScriptList::Valuate(HSQUIRRELVM vm)
|
|||||||
bool backup_allow = ScriptObject::GetAllowDoCommand();
|
bool backup_allow = ScriptObject::GetAllowDoCommand();
|
||||||
ScriptObject::SetAllowDoCommand(false);
|
ScriptObject::SetAllowDoCommand(false);
|
||||||
|
|
||||||
|
/* Limit the total number of ops that can be consumed by a valuate operation */
|
||||||
|
SQInteger new_ops_error_threshold = vm->_ops_till_suspend_error_threshold;
|
||||||
|
if (vm->_ops_till_suspend_error_threshold == INT64_MIN) {
|
||||||
|
new_ops_error_threshold = vm->_ops_till_suspend - MAX_VALUATE_OPS;
|
||||||
|
vm->_ops_till_suspend_error_label = "valuator function";
|
||||||
|
}
|
||||||
|
AutoRestoreBackup ops_error_threshold_backup(vm->_ops_till_suspend_error_threshold, new_ops_error_threshold);
|
||||||
|
|
||||||
/* Push the function to call */
|
/* Push the function to call */
|
||||||
sq_push(vm, 2);
|
sq_push(vm, 2);
|
||||||
|
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
#include "script_object.hpp"
|
#include "script_object.hpp"
|
||||||
|
|
||||||
|
/** Maximum number of operations allowed for valuating a list. */
|
||||||
|
static const int MAX_VALUATE_OPS = 500000;
|
||||||
|
|
||||||
class ScriptListSorter;
|
class ScriptListSorter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include "../../depot_map.h"
|
#include "../../depot_map.h"
|
||||||
#include "../../vehicle_base.h"
|
#include "../../vehicle_base.h"
|
||||||
#include "../../train.h"
|
#include "../../train.h"
|
||||||
|
#include "../../core/backup_type.hpp"
|
||||||
|
#include <../squirrel/sqvm.h>
|
||||||
|
|
||||||
#include "../../safeguards.h"
|
#include "../../safeguards.h"
|
||||||
|
|
||||||
@ -41,6 +43,14 @@ ScriptVehicleList::ScriptVehicleList(HSQUIRRELVM vm)
|
|||||||
bool backup_allow = ScriptObject::GetAllowDoCommand();
|
bool backup_allow = ScriptObject::GetAllowDoCommand();
|
||||||
ScriptObject::SetAllowDoCommand(false);
|
ScriptObject::SetAllowDoCommand(false);
|
||||||
|
|
||||||
|
/* Limit the total number of ops that can be consumed by a filter operation, if a filter function is present */
|
||||||
|
SQInteger new_ops_error_threshold = vm->_ops_till_suspend_error_threshold;
|
||||||
|
if (nparam >= 1 && vm->_ops_till_suspend_error_threshold == INT64_MIN) {
|
||||||
|
new_ops_error_threshold = vm->_ops_till_suspend - MAX_VALUATE_OPS;
|
||||||
|
vm->_ops_till_suspend_error_label = "vehicle filter function";
|
||||||
|
}
|
||||||
|
AutoRestoreBackup ops_error_threshold_backup(vm->_ops_till_suspend_error_threshold, new_ops_error_threshold);
|
||||||
|
|
||||||
for (const Vehicle *v : Vehicle::Iterate()) {
|
for (const Vehicle *v : Vehicle::Iterate()) {
|
||||||
if (v->owner != ScriptObject::GetCompany() && !ScriptCompanyMode::IsDeity()) continue;
|
if (v->owner != ScriptObject::GetCompany() && !ScriptCompanyMode::IsDeity()) continue;
|
||||||
if (!v->IsPrimaryVehicle() && !(v->type == VEH_TRAIN && ::Train::From(v)->IsFreeWagon())) continue;
|
if (!v->IsPrimaryVehicle() && !(v->type == VEH_TRAIN && ::Train::From(v)->IsFreeWagon())) continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user