diff options
author | rubidium <rubidium@openttd.org> | 2014-05-16 17:41:55 +0000 |
---|---|---|
committer | rubidium <rubidium@openttd.org> | 2014-05-16 17:41:55 +0000 |
commit | 46792e58dd689f6db76f35fd60b9946aba0bb846 (patch) | |
tree | 923e12bc8231e92bed9a8dc3e1b745041589df14 | |
parent | 191fd09d32b4f070da9f229724af4b4d90c9decb (diff) | |
download | openttd-46792e58dd689f6db76f35fd60b9946aba0bb846.tar.xz |
(svn r26591) -Add: some instrumentation to catch most cases where the wrong number of bytes would be written into variables during loading (or read during saving)
-rw-r--r-- | src/saveload/saveload.cpp | 41 | ||||
-rw-r--r-- | src/saveload/saveload.h | 13 |
2 files changed, 48 insertions, 6 deletions
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 2c57f0c8b..f3d2f6205 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1464,9 +1464,50 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) return 0; } +/** + * Check whether the variable size of the variable in the saveload configuration + * matches with the actual variable size. + * @param sld The saveload configuration to test. + */ +static bool IsVariableSizeRight(const SaveLoad *sld) +{ + switch (sld->cmd) { + case SL_VAR: + switch (GetVarMemType(sld->conv)) { + case SLE_VAR_BL: + return sld->size == sizeof(bool); + case SLE_VAR_I8: + case SLE_VAR_U8: + return sld->size == sizeof(int8); + case SLE_VAR_I16: + case SLE_VAR_U16: + return sld->size == sizeof(int16); + case SLE_VAR_I32: + case SLE_VAR_U32: + return sld->size == sizeof(int32); + case SLE_VAR_I64: + case SLE_VAR_U64: + return sld->size == sizeof(int64); + default: + return sld->size == sizeof(void *); + } + case SL_REF: + /* These should all be pointer sized. */ + return sld->size == sizeof(void *); + + case SL_STR: + /* These should be pointer sized, or fixed array. */ + return sld->size == sizeof(void *) || sld->size == sld->length; + + default: + return true; + } +} bool SlObjectMember(void *ptr, const SaveLoad *sld) { + assert(IsVariableSizeRight(sld)); + VarType conv = GB(sld->conv, 0, 8); switch (sld->cmd) { case SL_VAR: diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 1ad885009..72c51fa69 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -212,6 +212,7 @@ struct SaveLoad { * during runtime. Decision on which one to use is controlled by the function * that is called to save it. address: global=true, offset: global=false */ void *address; ///< address of variable OR offset of variable in the struct (max offset is 65536) + size_t size; ///< the sizeof size. }; /** Same as #SaveLoad but global variables are used (for better readability); */ @@ -227,7 +228,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param to Last savegame version that has the field. * @note In general, it is better to use one of the SLE_* macros below. */ -#define SLE_GENERAL(cmd, base, variable, type, length, from, to) {false, cmd, type, length, from, to, (void*)cpp_offsetof(base, variable)} +#define SLE_GENERAL(cmd, base, variable, type, length, from, to) {false, cmd, type, length, from, to, (void*)cpp_offsetof(base, variable), cpp_sizeof(base, variable)} /** * Storage of a variable in some savegame versions. @@ -340,11 +341,11 @@ typedef SaveLoad SaveLoadGlobVarList; /** Translate values ingame to different values in the savegame and vv. */ #define SLE_WRITEBYTE(base, variable, value) SLE_GENERAL(SL_WRITEBYTE, base, variable, 0, 0, value, value) -#define SLE_VEH_INCLUDE() {false, SL_VEH_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL} -#define SLE_ST_INCLUDE() {false, SL_ST_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL} +#define SLE_VEH_INCLUDE() {false, SL_VEH_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL, 0} +#define SLE_ST_INCLUDE() {false, SL_ST_INCLUDE, 0, 0, 0, SL_MAX_VERSION, NULL, 0} /** End marker of a struct/class save or load. */ -#define SLE_END() {false, SL_END, 0, 0, 0, 0, NULL} +#define SLE_END() {false, SL_END, 0, 0, 0, 0, NULL, 0} /** * Storage of global simple variables, references (pointers), and arrays. @@ -355,7 +356,7 @@ typedef SaveLoad SaveLoadGlobVarList; * @param to Last savegame version that has the field. * @note In general, it is better to use one of the SLEG_* macros below. */ -#define SLEG_GENERAL(cmd, variable, type, length, from, to) {true, cmd, type, length, from, to, (void*)&variable} +#define SLEG_GENERAL(cmd, variable, type, length, from, to) {true, cmd, type, length, from, to, (void*)&variable, sizeof(variable)} /** * Storage of a global variable in some savegame versions. @@ -448,7 +449,7 @@ typedef SaveLoad SaveLoadGlobVarList; #define SLEG_CONDNULL(length, from, to) {true, SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL | SLF_NOT_IN_CONFIG, length, from, to, (void*)NULL} /** End marker of global variables save or load. */ -#define SLEG_END() {true, SL_END, 0, 0, 0, 0, NULL} +#define SLEG_END() {true, SL_END, 0, 0, 0, 0, NULL, 0} /** * Checks whether the savegame is below \a major.\a minor. |