Validate type of all instructions, log validation failures at load.
The validator now checks that the type of conditional instructions is known. On a validation failure, the load code now outputs a corrupt savegame message, with the validation error message and a program dump, instead of using an assertion.
This commit is contained in:
@@ -11,9 +11,10 @@
|
|||||||
|
|
||||||
#include "../stdafx.h"
|
#include "../stdafx.h"
|
||||||
#include "../tracerestrict.h"
|
#include "../tracerestrict.h"
|
||||||
|
#include "../strings_func.h"
|
||||||
|
#include "../string_func.h"
|
||||||
#include "saveload.h"
|
#include "saveload.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "saveload.h"
|
|
||||||
|
|
||||||
static const SaveLoad _trace_restrict_mapping_desc[] = {
|
static const SaveLoad _trace_restrict_mapping_desc[] = {
|
||||||
SLE_VAR(TraceRestrictMappingItem, program_id, SLE_UINT32),
|
SLE_VAR(TraceRestrictMappingItem, program_id, SLE_UINT32),
|
||||||
@@ -66,7 +67,20 @@ static void Load_TRRP()
|
|||||||
SlObject(&stub, _trace_restrict_program_stub_desc);
|
SlObject(&stub, _trace_restrict_program_stub_desc);
|
||||||
prog->items.resize(stub.length);
|
prog->items.resize(stub.length);
|
||||||
SlArray(&(prog->items[0]), stub.length, SLE_UINT32);
|
SlArray(&(prog->items[0]), stub.length, SLE_UINT32);
|
||||||
assert(prog->Validate().Succeeded());
|
CommandCost validation_result = prog->Validate();
|
||||||
|
if (validation_result.Failed()) {
|
||||||
|
char str[4096];
|
||||||
|
char *strend = str + seprintf(str, lastof(str), "Trace restrict program %d: %s\nProgram dump:",
|
||||||
|
index, GetStringPtr(validation_result.GetErrorMessage()));
|
||||||
|
for (unsigned int i = 0; i < prog->items.size(); i++) {
|
||||||
|
if (i % 3) {
|
||||||
|
strend += seprintf(strend, lastof(str), " %08X", prog->items[i]);
|
||||||
|
} else {
|
||||||
|
strend += seprintf(strend, lastof(str), "\n%4u: %08X", i, prog->items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SlErrorCorrupt(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -414,7 +414,7 @@ void TraceRestrictProgram::DecrementRefCount() {
|
|||||||
* Validate a instruction list
|
* Validate a instruction list
|
||||||
* Returns successful result if program seems OK
|
* Returns successful result if program seems OK
|
||||||
* This only validates that conditional nesting is correct,
|
* This only validates that conditional nesting is correct,
|
||||||
* and that all non-conditionals have a known type, at present
|
* and that all instructions have a known type, at present
|
||||||
*/
|
*/
|
||||||
CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem> &items, TraceRestrictProgramActionsUsedFlags &actions_used_flags) {
|
CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem> &items, TraceRestrictProgramActionsUsedFlags &actions_used_flags) {
|
||||||
// static to avoid needing to re-alloc/resize on each execution
|
// static to avoid needing to re-alloc/resize on each execution
|
||||||
@@ -464,6 +464,23 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
|
|||||||
}
|
}
|
||||||
HandleCondition(condstack, condflags, true);
|
HandleCondition(condstack, condflags, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (GetTraceRestrictType(item)) {
|
||||||
|
case TRIT_COND_ENDIF:
|
||||||
|
case TRIT_COND_UNDEFINED:
|
||||||
|
case TRIT_COND_TRAIN_LENGTH:
|
||||||
|
case TRIT_COND_MAX_SPEED:
|
||||||
|
case TRIT_COND_CURRENT_ORDER:
|
||||||
|
case TRIT_COND_NEXT_ORDER:
|
||||||
|
case TRIT_COND_LAST_STATION:
|
||||||
|
case TRIT_COND_CARGO:
|
||||||
|
case TRIT_COND_ENTRY_DIRECTION:
|
||||||
|
case TRIT_COND_PBS_ENTRY_SIGNAL:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return_cmd_error(STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (GetTraceRestrictType(item)) {
|
switch (GetTraceRestrictType(item)) {
|
||||||
case TRIT_PF_DENY:
|
case TRIT_PF_DENY:
|
||||||
|
Reference in New Issue
Block a user