Improve type and length safety of commands taking binary data
This commit is contained in:
@@ -260,7 +260,7 @@ CommandProc CmdRenamePlan;
|
|||||||
|
|
||||||
CommandProc CmdDesyncCheck;
|
CommandProc CmdDesyncCheck;
|
||||||
|
|
||||||
#define DEF_CMD(proc, flags, type) {proc, #proc, (CommandFlags)flags, type}
|
#define DEF_CMD(proc, flags, type) Command(proc, #proc, (CommandFlags)flags, type)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The master command table
|
* The master command table
|
||||||
@@ -638,7 +638,7 @@ static int _docommand_recursive = 0;
|
|||||||
*/
|
*/
|
||||||
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
|
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
|
||||||
{
|
{
|
||||||
return DoCommand(container->tile, container->p1, container->p2, flags, container->cmd & CMD_ID_MASK, container->text.c_str());
|
return DoCommand(container->tile, container->p1, container->p2, flags, container->cmd & CMD_ID_MASK, container->text.c_str(), container->binary_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -651,10 +651,11 @@ CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
|
|||||||
* @param flags Flags for the command and how to execute the command
|
* @param flags Flags for the command and how to execute the command
|
||||||
* @param cmd The command-id to execute (a value of the CMD_* enums)
|
* @param cmd The command-id to execute (a value of the CMD_* enums)
|
||||||
* @param text The text to pass
|
* @param text The text to pass
|
||||||
|
* @param binary_length The length of binary data in text
|
||||||
* @see CommandProc
|
* @see CommandProc
|
||||||
* @return the cost
|
* @return the cost
|
||||||
*/
|
*/
|
||||||
CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text)
|
CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text, uint32 binary_length)
|
||||||
{
|
{
|
||||||
SCOPE_INFO_FMT([=], "DoCommand: tile: %X (%d x %d), p1: 0x%X, p2: 0x%X, flags: 0x%X, company: %s, cmd: 0x%X (%s)",
|
SCOPE_INFO_FMT([=], "DoCommand: tile: %X (%d x %d), p1: 0x%X, p2: 0x%X, flags: 0x%X, company: %s, cmd: 0x%X (%s)",
|
||||||
tile, TileX(tile), TileY(tile), p1, p2, flags, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd));
|
tile, TileX(tile), TileY(tile), p1, p2, flags, scope_dumper().CompanyInfo(_current_company), cmd, GetCommandName(cmd));
|
||||||
@@ -665,7 +666,7 @@ CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags,
|
|||||||
if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return CMD_ERROR;
|
if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return CMD_ERROR;
|
||||||
|
|
||||||
/* Chop of any CMD_MSG or other flags; we don't need those here */
|
/* Chop of any CMD_MSG or other flags; we don't need those here */
|
||||||
CommandProc *proc = _command_proc_table[cmd & CMD_ID_MASK].proc;
|
const Command &command = _command_proc_table[cmd & CMD_ID_MASK];
|
||||||
|
|
||||||
_docommand_recursive++;
|
_docommand_recursive++;
|
||||||
|
|
||||||
@@ -673,7 +674,7 @@ CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags,
|
|||||||
if (_docommand_recursive == 1 || !(flags & DC_EXEC) ) {
|
if (_docommand_recursive == 1 || !(flags & DC_EXEC) ) {
|
||||||
if (_docommand_recursive == 1) _cleared_object_areas.Clear();
|
if (_docommand_recursive == 1) _cleared_object_areas.Clear();
|
||||||
SetTownRatingTestMode(true);
|
SetTownRatingTestMode(true);
|
||||||
res = proc(tile, flags & ~DC_EXEC, p1, p2, text);
|
res = command.Execute(tile, flags & ~DC_EXEC, p1, p2, text, binary_length);
|
||||||
SetTownRatingTestMode(false);
|
SetTownRatingTestMode(false);
|
||||||
if (res.Failed()) {
|
if (res.Failed()) {
|
||||||
goto error;
|
goto error;
|
||||||
@@ -695,7 +696,7 @@ CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags,
|
|||||||
/* Execute the command here. All cost-relevant functions set the expenses type
|
/* Execute the command here. All cost-relevant functions set the expenses type
|
||||||
* themselves to the cost object at some point */
|
* themselves to the cost object at some point */
|
||||||
if (_docommand_recursive == 1) _cleared_object_areas.Clear();
|
if (_docommand_recursive == 1) _cleared_object_areas.Clear();
|
||||||
res = proc(tile, flags, p1, p2, text);
|
res = command.Execute(tile, flags, p1, p2, text, binary_length);
|
||||||
if (res.Failed()) {
|
if (res.Failed()) {
|
||||||
error:
|
error:
|
||||||
_docommand_recursive--;
|
_docommand_recursive--;
|
||||||
@@ -732,7 +733,7 @@ Money GetAvailableMoneyForCommand()
|
|||||||
*/
|
*/
|
||||||
bool DoCommandP(const CommandContainer *container, bool my_cmd)
|
bool DoCommandP(const CommandContainer *container, bool my_cmd)
|
||||||
{
|
{
|
||||||
return DoCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text.c_str(), my_cmd);
|
return DoCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text.c_str(), my_cmd, container->binary_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -748,7 +749,7 @@ bool DoCommandP(const CommandContainer *container, bool my_cmd)
|
|||||||
* @param callback A callback function to call after the command is finished
|
* @param callback A callback function to call after the command is finished
|
||||||
* @param text The text to pass
|
* @param text The text to pass
|
||||||
* @param my_cmd indicator if the command is from a company or server (to display error messages for a user)
|
* @param my_cmd indicator if the command is from a company or server (to display error messages for a user)
|
||||||
* @param binary_length The quantity of binary data in text
|
* @param binary_length The length of binary data in text
|
||||||
* @return \c true if the command succeeded, else \c false.
|
* @return \c true if the command succeeded, else \c false.
|
||||||
*/
|
*/
|
||||||
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, uint32 binary_length)
|
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, uint32 binary_length)
|
||||||
@@ -853,10 +854,10 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
|
|||||||
byte cmd_id = cmd & CMD_ID_MASK;
|
byte cmd_id = cmd & CMD_ID_MASK;
|
||||||
assert(cmd_id < lengthof(_command_proc_table));
|
assert(cmd_id < lengthof(_command_proc_table));
|
||||||
|
|
||||||
CommandProc *proc = _command_proc_table[cmd_id].proc;
|
const Command &command = _command_proc_table[cmd_id];
|
||||||
/* Shouldn't happen, but you never know when someone adds
|
/* Shouldn't happen, but you never know when someone adds
|
||||||
* NULLs to the _command_proc_table. */
|
* NULLs to the _command_proc_table. */
|
||||||
assert(proc != NULL);
|
assert(command.proc != NULL);
|
||||||
|
|
||||||
/* Command flags are used internally */
|
/* Command flags are used internally */
|
||||||
CommandFlags cmd_flags = GetCommandFlags(cmd);
|
CommandFlags cmd_flags = GetCommandFlags(cmd);
|
||||||
@@ -890,7 +891,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
|
|||||||
_cleared_object_areas.Clear();
|
_cleared_object_areas.Clear();
|
||||||
SetTownRatingTestMode(true);
|
SetTownRatingTestMode(true);
|
||||||
BasePersistentStorageArray::SwitchMode(PSM_ENTER_TESTMODE);
|
BasePersistentStorageArray::SwitchMode(PSM_ENTER_TESTMODE);
|
||||||
CommandCost res = proc(tile, flags, p1, p2, text);
|
CommandCost res = command.Execute(tile, flags, p1, p2, text, binary_length);
|
||||||
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_TESTMODE);
|
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_TESTMODE);
|
||||||
SetTownRatingTestMode(false);
|
SetTownRatingTestMode(false);
|
||||||
|
|
||||||
@@ -935,7 +936,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd,
|
|||||||
* use the construction one */
|
* use the construction one */
|
||||||
_cleared_object_areas.Clear();
|
_cleared_object_areas.Clear();
|
||||||
BasePersistentStorageArray::SwitchMode(PSM_ENTER_COMMAND);
|
BasePersistentStorageArray::SwitchMode(PSM_ENTER_COMMAND);
|
||||||
CommandCost res2 = proc(tile, flags | DC_EXEC, p1, p2, text);
|
CommandCost res2 = command.Execute(tile, flags | DC_EXEC, p1, p2, text, binary_length);
|
||||||
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_COMMAND);
|
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_COMMAND);
|
||||||
|
|
||||||
if (cmd_id == CMD_COMPANY_CTRL) {
|
if (cmd_id == CMD_COMPANY_CTRL) {
|
||||||
|
@@ -34,7 +34,7 @@ static const CommandCost CMD_ERROR = CommandCost(INVALID_STRING_ID);
|
|||||||
*/
|
*/
|
||||||
#define return_cmd_error(errcode) return CommandCost(errcode);
|
#define return_cmd_error(errcode) return CommandCost(errcode);
|
||||||
|
|
||||||
CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text = NULL);
|
CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text = NULL, uint32 binary_length = 0);
|
||||||
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags);
|
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags);
|
||||||
|
|
||||||
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = NULL, const char *text = NULL, bool my_cmd = true, uint32 binary_length = 0);
|
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback = NULL, const char *text = NULL, bool my_cmd = true, uint32 binary_length = 0);
|
||||||
|
@@ -492,6 +492,7 @@ enum CommandFlags {
|
|||||||
CMD_DEITY = 0x100, ///< the command may be executed by COMPANY_DEITY
|
CMD_DEITY = 0x100, ///< the command may be executed by COMPANY_DEITY
|
||||||
CMD_STR_CTRL = 0x200, ///< the command's string may contain control strings
|
CMD_STR_CTRL = 0x200, ///< the command's string may contain control strings
|
||||||
CMD_NO_EST = 0x400, ///< the command is never estimated.
|
CMD_NO_EST = 0x400, ///< the command is never estimated.
|
||||||
|
CMD_PROCEX = 0x800, ///< the command proc function has extended parameters
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(CommandFlags)
|
DECLARE_ENUM_AS_BIT_SET(CommandFlags)
|
||||||
|
|
||||||
@@ -537,6 +538,7 @@ enum CommandPauseLevel {
|
|||||||
* @return The CommandCost of the command, which can be succeeded or failed.
|
* @return The CommandCost of the command, which can be succeeded or failed.
|
||||||
*/
|
*/
|
||||||
typedef CommandCost CommandProc(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text);
|
typedef CommandCost CommandProc(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text);
|
||||||
|
typedef CommandCost CommandProcEx(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text, uint32 binary_length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a command with the flags which belongs to it.
|
* Define a command with the flags which belongs to it.
|
||||||
@@ -545,10 +547,26 @@ typedef CommandCost CommandProc(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
|||||||
* the #CMD_AUTO, #CMD_OFFLINE and #CMD_SERVER values.
|
* the #CMD_AUTO, #CMD_OFFLINE and #CMD_SERVER values.
|
||||||
*/
|
*/
|
||||||
struct Command {
|
struct Command {
|
||||||
CommandProc *proc; ///< The procedure to actually executing
|
union {
|
||||||
|
CommandProc *proc; ///< The procedure to actually execute
|
||||||
|
CommandProcEx *procex; ///< The procedure to actually execute, extended parameters
|
||||||
|
};
|
||||||
const char *name; ///< A human readable name for the procedure
|
const char *name; ///< A human readable name for the procedure
|
||||||
CommandFlags flags; ///< The (command) flags to that apply to this command
|
CommandFlags flags; ///< The (command) flags to that apply to this command
|
||||||
CommandType type; ///< The type of command.
|
CommandType type; ///< The type of command.
|
||||||
|
|
||||||
|
Command(CommandProc *proc, const char *name, CommandFlags flags, CommandType type)
|
||||||
|
: proc(proc), name(name), flags(flags & ~CMD_PROCEX), type(type) {}
|
||||||
|
Command(CommandProcEx *procex, const char *name, CommandFlags flags, CommandType type)
|
||||||
|
: procex(procex), name(name), flags(flags | CMD_PROCEX), type(type) {}
|
||||||
|
|
||||||
|
inline CommandCost Execute(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text, uint32 binary_length) const {
|
||||||
|
if (this->flags & CMD_PROCEX) {
|
||||||
|
return this->procex(tile, flags, p1, p2, text, binary_length);
|
||||||
|
} else {
|
||||||
|
return this->proc(tile, flags, p1, p2, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user