diff --git a/src/3rdparty/md5/md5.cpp b/src/3rdparty/md5/md5.cpp --- a/src/3rdparty/md5/md5.cpp +++ b/src/3rdparty/md5/md5.cpp @@ -297,7 +297,7 @@ void Md5::Append(const void *data, const if (left) memcpy(this->buf, p, left); } -void Md5::Finish(uint8 digest[16]) +void Md5::Finish(MD5Hash &digest) { static const uint8 pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/3rdparty/md5/md5.h b/src/3rdparty/md5/md5.h --- a/src/3rdparty/md5/md5.h +++ b/src/3rdparty/md5/md5.h @@ -53,6 +53,25 @@ #ifndef MD5_INCLUDED #define MD5_INCLUDED +/** The number of bytes in a MD5 hash. */ +static const size_t MD5_HASH_BYTES = 16; + +/** Container for storing a MD5 hash/checksum/digest. */ +using MD5Hash = std::array; + +/** + * Exclusively-or one hash into another hash. + * @param lhs The hash to exclusively-or into. + * @param rhs The hash to exclusively-or with. + * @return Reference to \c lhs hash. + */ +inline MD5Hash &operator^=(MD5Hash &lhs, const MD5Hash &rhs) +{ + for (size_t i = 0; i < lhs.size(); i++) lhs[i] ^= rhs[i]; + return lhs; +} + + struct Md5 { private: uint32 count[2]; ///< message length in bits, lsw first @@ -64,7 +83,7 @@ private: public: Md5(); void Append(const void *data, const size_t nbytes); - void Finish(uint8 digest[16]); + void Finish(MD5Hash &digest); }; #endif /* MD5_INCLUDED */ diff --git a/src/base_media_base.h b/src/base_media_base.h --- a/src/base_media_base.h +++ b/src/base_media_base.h @@ -14,6 +14,7 @@ #include "gfx_type.h" #include "textfile_type.h" #include "textfile_gui.h" +#include "3rdparty/md5/md5.h" #include /* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */ @@ -31,7 +32,7 @@ struct MD5File { }; std::string filename; ///< filename - uint8 hash[16]; ///< md5 sum of the file + MD5Hash hash; ///< md5 sum of the file std::string missing_warning; ///< warning when this file is missing ChecksumResult check_result; ///< cached result of md5 check diff --git a/src/base_media_func.h b/src/base_media_func.h --- a/src/base_media_func.h +++ b/src/base_media_func.h @@ -99,7 +99,7 @@ bool BaseSetvalue->c_str(); - for (uint i = 0; i < sizeof(file->hash) * 2; i++, c++) { + for (size_t i = 0; i < file->hash.size() * 2; i++, c++) { uint j; if ('0' <= *c && *c <= '9') { j = *c - '0'; @@ -285,14 +285,11 @@ template const char *T if (s->shortname != ci->unique_id) continue; if (!md5sum) return s->files[0].filename.c_str(); - byte md5[16]; - memset(md5, 0, sizeof(md5)); + MD5Hash md5; for (uint i = 0; i < Tbase_set::NUM_FILES; i++) { - for (uint j = 0; j < sizeof(md5); j++) { - md5[j] ^= s->files[i].hash[j]; - } + md5 ^= s->files[i].hash; } - if (memcmp(md5, ci->md5sum, sizeof(md5)) == 0) return s->files[0].filename.c_str(); + if (md5 == ci->md5sum) return s->files[0].filename.c_str(); } return nullptr; } diff --git a/src/fios.cpp b/src/fios.cpp --- a/src/fios.cpp +++ b/src/fios.cpp @@ -629,13 +629,12 @@ const char *FiosGetScreenshotDir() /** Basic data to distinguish a scenario. Used in the server list window */ struct ScenarioIdentifier { uint32 scenid; ///< ID for the scenario (generated by content). - uint8 md5sum[16]; ///< MD5 checksum of file. + MD5Hash md5sum; ///< MD5 checksum of file. std::string filename; ///< filename of the file. bool operator == (const ScenarioIdentifier &other) const { - return this->scenid == other.scenid && - memcmp(this->md5sum, other.md5sum, sizeof(this->md5sum)) == 0; + return this->scenid == other.scenid && this->md5sum == other.md5sum; } bool operator != (const ScenarioIdentifier &other) const @@ -714,7 +713,7 @@ const char *FindScenario(const ContentIn _scanner.Scan(false); for (ScenarioIdentifier &id : _scanner) { - if (md5sum ? (memcmp(id.md5sum, ci->md5sum, sizeof(id.md5sum)) == 0) + if (md5sum ? (id.md5sum == ci->md5sum) : (id.scenid == ci->unique_id)) { return id.filename.c_str(); } diff --git a/src/gamelog.cpp b/src/gamelog.cpp --- a/src/gamelog.cpp +++ b/src/gamelog.cpp @@ -106,10 +106,10 @@ void Gamelog::Reset() * @param md5sum array of md5sum to print, if known * @param gc GrfConfig, if known */ -static void AddGrfInfo(std::back_insert_iterator &output_iterator, uint32_t grfid, const uint8_t *md5sum, const GRFConfig *gc) +static void AddGrfInfo(std::back_insert_iterator &output_iterator, uint32_t grfid, const MD5Hash *md5sum, const GRFConfig *gc) { if (md5sum != nullptr) { - fmt::format_to(output_iterator, "GRF ID {:08X}, checksum {}", BSWAP32(grfid), MD5SumToString(md5sum)); + fmt::format_to(output_iterator, "GRF ID {:08X}, checksum {}", BSWAP32(grfid), MD5SumToString(*md5sum)); } else { fmt::format_to(output_iterator, "GRF ID {:08X}", BSWAP32(grfid)); } @@ -230,9 +230,9 @@ void Gamelog::Print(std::function &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) { /* A NewGRF got added to the game, either at the start of the game (never an issue), or later on when it could be an issue. */ - const GRFConfig *gc = FindGRFConfig(this->grfid, FGCM_EXACT, this->md5sum); + const GRFConfig *gc = FindGRFConfig(this->grfid, FGCM_EXACT, &this->md5sum); fmt::format_to(output_iterator, "Added NewGRF: "); - AddGrfInfo(output_iterator, this->grfid, this->md5sum, gc); + AddGrfInfo(output_iterator, this->grfid, &this->md5sum, gc); auto gm = grf_names.find(this->grfid); if (gm != grf_names.end() && !gm->second.was_missing) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was already added!"); grf_names[this->grfid] = gc; @@ -259,9 +259,9 @@ void Gamelog::Print(std::function &output_iterator, GrfIDMapping &grf_names, GamelogActionType action_type) { /* Another version of the same NewGRF got loaded. */ - const GRFConfig *gc = FindGRFConfig(this->grfid, FGCM_EXACT, this->md5sum); + const GRFConfig *gc = FindGRFConfig(this->grfid, FGCM_EXACT, &this->md5sum); fmt::format_to(output_iterator, "Compatible NewGRF loaded: "); - AddGrfInfo(output_iterator, this->grfid, this->md5sum, gc); + AddGrfInfo(output_iterator, this->grfid, &this->md5sum, gc); if (grf_names.count(this->grfid) == 0) fmt::format_to(output_iterator, ". Gamelog inconsistency: GrfID was never added!"); grf_names[this->grfid] = gc; } @@ -654,7 +654,7 @@ void Gamelog::GRFUpdate(const GRFConfig this->GRFMove(nl[n++]->ident.grfid, -(int)oi); } } else { - if (memcmp(og->ident.md5sum, ng->ident.md5sum, sizeof(og->ident.md5sum)) != 0) { + if (og->ident.md5sum != ng->ident.md5sum) { /* md5sum changed, probably loading 'compatible' GRF */ this->GRFCompatible(&nl[n]->ident); } diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -415,7 +415,7 @@ MD5File::ChecksumResult MD5File::CheckMD Md5 checksum; uint8 buffer[1024]; - uint8 digest[16]; + MD5Hash digest; size_t len; while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) { @@ -426,7 +426,7 @@ MD5File::ChecksumResult MD5File::CheckMD FioFCloseFile(f); checksum.Finish(digest); - return memcmp(this->hash, digest, sizeof(this->hash)) == 0 ? CR_MATCH : CR_MISMATCH; + return this->hash == digest ? CR_MATCH : CR_MISMATCH; } /** Names corresponding to the GraphicsFileType */ diff --git a/src/misc.cpp b/src/misc.cpp --- a/src/misc.cpp +++ b/src/misc.cpp @@ -77,7 +77,7 @@ std::string GenerateUid(std::string_view std::string coding_string = fmt::format("{}{}{}", InteractiveRandom(), current_time, subject); Md5 checksum; - uint8 digest[16]; + MD5Hash digest; checksum.Append(coding_string.c_str(), coding_string.length()); checksum.Finish(digest); diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -164,7 +164,7 @@ const NetworkServerGameInfo *GetCurrentN static void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config, std::string name) { /* Find the matching GRF file */ - const GRFConfig *f = FindGRFConfig(config->ident.grfid, FGCM_EXACT, config->ident.md5sum); + const GRFConfig *f = FindGRFConfig(config->ident.grfid, FGCM_EXACT, &config->ident.md5sum); if (f == nullptr) { AddGRFTextToList(config->name, name.empty() ? GetString(STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN) : name); config->status = GCS_NOT_FOUND; @@ -362,9 +362,8 @@ void DeserializeNetworkGameInfo(Packet * */ void SerializeGRFIdentifier(Packet *p, const GRFIdentifier *grf) { - uint j; p->Send_uint32(grf->grfid); - for (j = 0; j < sizeof(grf->md5sum); j++) { + for (size_t j = 0; j < grf->md5sum.size(); j++) { p->Send_uint8(grf->md5sum[j]); } } @@ -376,9 +375,8 @@ void SerializeGRFIdentifier(Packet *p, c */ void DeserializeGRFIdentifier(Packet *p, GRFIdentifier *grf) { - uint j; grf->grfid = p->Recv_uint32(); - for (j = 0; j < sizeof(grf->md5sum); j++) { + for (size_t j = 0; j < grf->md5sum.size(); j++) { grf->md5sum[j] = p->Recv_uint8(); } } diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp --- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -70,7 +70,7 @@ std::optional ContentInfo:: tmp = Game::GetScannerLibrary()->FindMainScript(this, true); break; case CONTENT_TYPE_NEWGRF: { - const GRFConfig *gc = FindGRFConfig(BSWAP32(this->unique_id), FGCM_EXACT, this->md5sum); + const GRFConfig *gc = FindGRFConfig(BSWAP32(this->unique_id), FGCM_EXACT, &this->md5sum); tmp = gc != nullptr ? gc->filename.c_str() : nullptr; break; } diff --git a/src/network/core/tcp_content_type.h b/src/network/core/tcp_content_type.h --- a/src/network/core/tcp_content_type.h +++ b/src/network/core/tcp_content_type.h @@ -12,6 +12,8 @@ #ifndef NETWORK_CORE_TCP_CONTENT_TYPE_H #define NETWORK_CORE_TCP_CONTENT_TYPE_H +#include "../../3rdparty/md5/md5.h" + /** The values in the enum are important; they are used as database 'keys' */ enum ContentType { CONTENT_TYPE_BEGIN = 1, ///< Helper to mark the begin of the types @@ -67,7 +69,7 @@ struct ContentInfo { std::string url; ///< URL related to the content std::string description; ///< Description of the content uint32 unique_id = 0; ///< Unique ID; either GRF ID or shortname - byte md5sum[16] = {0}; ///< The MD5 checksum + MD5Hash md5sum; ///< The MD5 checksum std::vector dependencies; ///< The dependencies (unique server side ids) StringList tags; ///< Tags associated with the content State state = State::UNSELECTED; ///< Whether the content info is selected (for download) diff --git a/src/network/network.cpp b/src/network/network.cpp --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -190,18 +190,14 @@ std::string GenerateCompanyPasswordHash( } Md5 checksum; - uint8 digest[16]; + MD5Hash digest; /* Generate the MD5 hash */ std::string salted_password_string = salted_password.str(); checksum.Append(salted_password_string.data(), salted_password_string.size()); checksum.Finish(digest); - std::ostringstream hashed_password; - hashed_password << std::hex << std::setfill('0'); - for (int di = 0; di < 16; di++) hashed_password << std::setw(2) << (int)digest[di]; // Cast needed, otherwise interpreted as character to add - - return hashed_password.str(); + return MD5SumToString(digest); } /** diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -322,7 +322,7 @@ std::string _network_server_name; NetworkJoinInfo _network_join; /** Make sure the server ID length is the same as a md5 hash. */ -static_assert(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1); +static_assert(NETWORK_SERVER_ID_LENGTH == MD5_HASH_BYTES * 2 + 1); /*********** * Sending functions @@ -663,7 +663,7 @@ NetworkRecvStatus ClientNetworkGameSocke DeserializeGRFIdentifier(p, &c); /* Check whether we know this GRF */ - const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, c.md5sum); + const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, &c.md5sum); if (f == nullptr) { /* We do not know this GRF, bail out of initialization */ Debug(grf, 0, "NewGRF {:08X} not found; checksum {}", BSWAP32(c.grfid), MD5SumToString(c.md5sum)); diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -37,7 +37,7 @@ ClientNetworkContentSocketHandler _netwo /** Wrapper function for the HasProc */ static bool HasGRFConfig(const ContentInfo *ci, bool md5sum) { - return FindGRFConfig(BSWAP32(ci->unique_id), md5sum ? FGCM_EXACT : FGCM_ANY, md5sum ? ci->md5sum : nullptr) != nullptr; + return FindGRFConfig(BSWAP32(ci->unique_id), md5sum ? FGCM_EXACT : FGCM_ANY, md5sum ? &ci->md5sum : nullptr) != nullptr; } /** @@ -62,7 +62,7 @@ bool ClientNetworkContentSocketHandler:: ci->description = p->Recv_string(NETWORK_CONTENT_DESC_LENGTH, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); ci->unique_id = p->Recv_uint32(); - for (uint j = 0; j < sizeof(ci->md5sum); j++) { + for (size_t j = 0; j < ci->md5sum.size(); j++) { ci->md5sum[j] = p->Recv_uint8(); } @@ -144,8 +144,7 @@ bool ClientNetworkContentSocketHandler:: /* Do we already have a stub for this? */ for (ContentInfo *ici : this->infos) { - if (ici->type == ci->type && ici->unique_id == ci->unique_id && - memcmp(ci->md5sum, ici->md5sum, sizeof(ci->md5sum)) == 0) { + if (ici->type == ci->type && ici->unique_id == ci->unique_id && ci->md5sum == ici->md5sum) { /* Preserve the name if possible */ if (ci->name.empty()) ci->name = ici->name; if (ici->IsSelected()) ci->state = ici->state; @@ -267,7 +266,7 @@ void ClientNetworkContentSocketHandler:: assert(cv->size() < 255); assert(cv->size() < (TCP_MTU - sizeof(PacketSize) - sizeof(byte) - sizeof(uint8)) / - (sizeof(uint8) + sizeof(uint32) + (send_md5sum ? /*sizeof(ContentInfo::md5sum)*/16 : 0))); + (sizeof(uint8) + sizeof(uint32) + (send_md5sum ? MD5_HASH_BYTES : 0))); Packet *p = new Packet(send_md5sum ? PACKET_CONTENT_CLIENT_INFO_EXTID_MD5 : PACKET_CONTENT_CLIENT_INFO_EXTID, TCP_MTU); p->Send_uint8((uint8)cv->size()); @@ -277,7 +276,7 @@ void ClientNetworkContentSocketHandler:: p->Send_uint32(ci->unique_id); if (!send_md5sum) continue; - for (uint j = 0; j < sizeof(ci->md5sum); j++) { + for (size_t j = 0; j < ci->md5sum.size(); j++) { p->Send_uint8(ci->md5sum[j]); } } @@ -288,7 +287,7 @@ void ClientNetworkContentSocketHandler:: bool found = false; for (ContentInfo *ci2 : this->infos) { if (ci->type == ci2->type && ci->unique_id == ci2->unique_id && - (!send_md5sum || memcmp(ci->md5sum, ci2->md5sum, sizeof(ci->md5sum)) == 0)) { + (!send_md5sum || ci->md5sum == ci2->md5sum)) { found = true; break; } diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp --- a/src/network/network_gamelist.cpp +++ b/src/network/network_gamelist.cpp @@ -124,7 +124,7 @@ void NetworkAfterNewGRFScan() for (GRFConfig *c = item->info.grfconfig; c != nullptr; c = c->next) { assert(HasBit(c->flags, GCF_COPY)); - const GRFConfig *f = FindGRFConfig(c->ident.grfid, FGCM_EXACT, c->ident.md5sum); + const GRFConfig *f = FindGRFConfig(c->ident.grfid, FGCM_EXACT, &c->ident.md5sum); if (f == nullptr) { /* Don't know the GRF (anymore), so mark game incompatible. */ c->status = GCS_NOT_FOUND; diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -46,6 +46,7 @@ GRFConfig::GRFConfig(const std::string & GRFConfig::GRFConfig(const GRFConfig &config) : ZeroedMemoryAllocator(), ident(config.ident), + original_md5sum(config.original_md5sum), filename(config.filename), name(config.name), info(config.info), @@ -61,7 +62,6 @@ GRFConfig::GRFConfig(const GRFConfig &co param_info(config.param_info), has_param_defaults(config.has_param_defaults) { - MemCpyT(this->original_md5sum, config.original_md5sum, lengthof(this->original_md5sum)); MemCpyT(this->param, config.param, lengthof(this->param)); if (config.error != nullptr) this->error = std::make_unique(*config.error); } @@ -475,7 +475,7 @@ GRFListCompatibility IsGoodGRFConfigList GRFListCompatibility res = GLC_ALL_GOOD; for (GRFConfig *c = grfconfig; c != nullptr; c = c->next) { - const GRFConfig *f = FindGRFConfig(c->ident.grfid, FGCM_EXACT, c->ident.md5sum); + const GRFConfig *f = FindGRFConfig(c->ident.grfid, FGCM_EXACT, &c->ident.md5sum); if (f == nullptr || HasBit(f->flags, GCF_INVALID)) { /* If we have not found the exactly matching GRF try to find one with the * same grfid, as it most likely is compatible */ @@ -485,7 +485,7 @@ GRFListCompatibility IsGoodGRFConfigList if (!HasBit(c->flags, GCF_COMPATIBLE)) { /* Preserve original_md5sum after it has been assigned */ SetBit(c->flags, GCF_COMPATIBLE); - memcpy(c->original_md5sum, c->ident.md5sum, sizeof(c->original_md5sum)); + c->original_md5sum = c->ident.md5sum; } /* Non-found has precedence over compatibility load */ @@ -508,7 +508,7 @@ compatible_grf: * already a local one, so there is no need to replace it. */ if (!HasBit(c->flags, GCF_COPY)) { c->filename = f->filename; - memcpy(c->ident.md5sum, f->ident.md5sum, sizeof(c->ident.md5sum)); + c->ident.md5sum = f->ident.md5sum; c->name = f->name; c->info = f->name; c->error = nullptr; @@ -575,7 +575,7 @@ bool GRFFileScanner::AddFile(const std:: GRFConfig **pd, *d; bool stop = false; for (pd = &_all_grfs; (d = *pd) != nullptr; pd = &d->next) { - if (c->ident.grfid == d->ident.grfid && memcmp(c->ident.md5sum, d->ident.md5sum, sizeof(c->ident.md5sum)) == 0) added = false; + if (c->ident.grfid == d->ident.grfid && c->ident.md5sum == d->ident.md5sum) added = false; /* Because there can be multiple grfs with the same name, make sure we checked all grfs with the same name, * before inserting the entry. So insert a new grf at the end of all grfs with the same name, instead of * just after the first with the same name. Avoids doubles in the list. */ @@ -691,7 +691,7 @@ void ScanNewGRFFiles(NewGRFScanCallback * @param desired_version Requested version * @return The matching grf, if it exists in #_all_grfs, else \c nullptr. */ -const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum, uint32 desired_version) +const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const MD5Hash *md5sum, uint32 desired_version) { assert((mode == FGCM_EXACT) != (md5sum == nullptr)); const GRFConfig *best = nullptr; diff --git a/src/newgrf_config.h b/src/newgrf_config.h --- a/src/newgrf_config.h +++ b/src/newgrf_config.h @@ -16,6 +16,7 @@ #include "fileio_type.h" #include "textfile_type.h" #include "newgrf_text.h" +#include "3rdparty/md5/md5.h" /** GRF config bit flags */ enum GCF_Flags { @@ -81,15 +82,12 @@ enum GRFPalette { /** Basic data to distinguish a GRF. Used in the server list window */ struct GRFIdentifier { uint32 grfid; ///< GRF ID (defined by Action 0x08) - uint8 md5sum[16]; ///< MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF) + MD5Hash md5sum; ///< MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF) GRFIdentifier() = default; GRFIdentifier(const GRFIdentifier &other) = default; GRFIdentifier(GRFIdentifier &&other) = default; - GRFIdentifier(uint32 grfid, const uint8 *md5sum) : grfid(grfid) - { - MemCpyT(this->md5sum, md5sum, lengthof(this->md5sum)); - } + GRFIdentifier(uint32 grfid, const MD5Hash &md5sum) : grfid(grfid), md5sum(md5sum) {} GRFIdentifier& operator =(const GRFIdentifier &other) = default; @@ -99,11 +97,11 @@ struct GRFIdentifier { * @param md5sum Expected md5sum, may be \c nullptr (in which case, do not check it). * @return the object has the provided grfid and md5sum. */ - inline bool HasGrfIdentifier(uint32 grfid, const uint8 *md5sum) const + inline bool HasGrfIdentifier(uint32 grfid, const MD5Hash *md5sum) const { if (this->grfid != grfid) return false; if (md5sum == nullptr) return true; - return memcmp(md5sum, this->md5sum, sizeof(this->md5sum)) == 0; + return *md5sum == this->md5sum; } }; @@ -158,7 +156,7 @@ struct GRFConfig : ZeroedMemoryAllocator GRFConfig &operator=(GRFConfig &rhs) = delete; GRFIdentifier ident; ///< grfid and md5sum to uniquely identify newgrfs - uint8 original_md5sum[16]; ///< MD5 checksum of original file if only a 'compatible' file was loaded + MD5Hash original_md5sum; ///< MD5 checksum of original file if only a 'compatible' file was loaded std::string filename; ///< Filename - either with or without full path GRFTextWrapper name; ///< NOSAVE: GRF name (Action 0x08) GRFTextWrapper info; ///< NOSAVE: GRF info (author, copyright, ...) (Action 0x08) @@ -217,7 +215,7 @@ struct NewGRFScanCallback { size_t GRFGetSizeOfDataSection(FILE *f); void ScanNewGRFFiles(NewGRFScanCallback *callback); -const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8 *md5sum = nullptr, uint32 desired_version = 0); +const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const MD5Hash *md5sum = nullptr, uint32 desired_version = 0); GRFConfig *GetGRFConfig(uint32 grfid, uint32 mask = 0xFFFFFFFF); GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only); void AppendStaticGRFConfigs(GRFConfig **dst); diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1245,7 +1245,7 @@ struct NewGRFWindow : public Window, New bool compatible = HasBit(c->flags, GCF_COMPATIBLE); if (c->status != GCS_NOT_FOUND && !compatible) continue; - const GRFConfig *f = FindGRFConfig(c->ident.grfid, FGCM_EXACT, compatible ? c->original_md5sum : c->ident.md5sum); + const GRFConfig *f = FindGRFConfig(c->ident.grfid, FGCM_EXACT, compatible ? &c->original_md5sum : &c->ident.md5sum); if (f == nullptr || HasBit(f->flags, GCF_INVALID)) continue; *l = new GRFConfig(*f); @@ -1452,7 +1452,7 @@ private: i = a->version - b->version; if (i != 0) return i < 0; - return memcmp(a->ident.md5sum, b->ident.md5sum, lengthof(b->ident.md5sum)) < 0; + return a->ident.md5sum < b->ident.md5sum; } /** Filter grfs by tags/name */ @@ -1473,7 +1473,7 @@ private: for (const GRFConfig *c = _all_grfs; c != nullptr; c = c->next) { bool found = false; - for (const GRFConfig *grf = this->actives; grf != nullptr && !found; grf = grf->next) found = grf->ident.HasGrfIdentifier(c->ident.grfid, c->ident.md5sum); + for (const GRFConfig *grf = this->actives; grf != nullptr && !found; grf = grf->next) found = grf->ident.HasGrfIdentifier(c->ident.grfid, &c->ident.md5sum); if (found) continue; if (_settings_client.gui.newgrf_show_old_versions) { @@ -1490,7 +1490,7 @@ private: * If we are the best version, then we definitely want to * show that NewGRF!. */ - if (best->version == 0 || best->ident.HasGrfIdentifier(c->ident.grfid, c->ident.md5sum)) { + if (best->version == 0 || best->ident.HasGrfIdentifier(c->ident.grfid, &c->ident.md5sum)) { this->avails.push_back(c); } } @@ -1575,7 +1575,7 @@ void ShowMissingContentWindow(const GRFC ci->state = ContentInfo::DOES_NOT_EXIST; ci->name = c->GetName(); ci->unique_id = BSWAP32(c->ident.grfid); - memcpy(ci->md5sum, HasBit(c->flags, GCF_COMPATIBLE) ? c->original_md5sum : c->ident.md5sum, sizeof(ci->md5sum)); + ci->md5sum = HasBit(c->flags, GCF_COMPATIBLE) ? c->original_md5sum : c->ident.md5sum; cv.push_back(ci); } ShowNetworkContentListWindow(cv.size() == 0 ? nullptr : &cv, CONTENT_TYPE_NEWGRF); diff --git a/src/script/script_scanner.cpp b/src/script/script_scanner.cpp --- a/src/script/script_scanner.cpp +++ b/src/script/script_scanner.cpp @@ -154,18 +154,14 @@ std::string ScriptScanner::GetConsoleLis /** Helper for creating a MD5sum of all files within of a script. */ struct ScriptFileChecksumCreator : FileScanner { - byte md5sum[16]; ///< The final md5sum. + MD5Hash md5sum; ///< The final md5sum. Subdirectory dir; ///< The directory to look in. /** * Initialise the md5sum to be all zeroes, * so we can easily xor the data. */ - ScriptFileChecksumCreator(Subdirectory dir) - { - this->dir = dir; - memset(this->md5sum, 0, sizeof(this->md5sum)); - } + ScriptFileChecksumCreator(Subdirectory dir) : dir(dir) {} /* Add the file and calculate the md5 sum. */ virtual bool AddFile(const std::string &filename, size_t basepath_length, const std::string &tar_filename) @@ -173,7 +169,6 @@ struct ScriptFileChecksumCreator : FileS Md5 checksum; uint8 buffer[1024]; size_t len, size; - byte tmp_md5sum[16]; /* Open the file ... */ FILE *f = FioFOpenFile(filename, "rb", this->dir, &size); @@ -184,12 +179,14 @@ struct ScriptFileChecksumCreator : FileS size -= len; checksum.Append(buffer, len); } + + MD5Hash tmp_md5sum; checksum.Finish(tmp_md5sum); FioFCloseFile(f); /* ... and xor it to the overall md5sum. */ - for (uint i = 0; i < sizeof(md5sum); i++) this->md5sum[i] ^= tmp_md5sum[i]; + this->md5sum ^= tmp_md5sum; return true; } @@ -237,7 +234,7 @@ static bool IsSameScript(const ContentIn checksum.Scan(".nut", path); } - return memcmp(ci->md5sum, checksum.md5sum, sizeof(ci->md5sum)) == 0; + return ci->md5sum == checksum.md5sum; } bool ScriptScanner::HasScript(const ContentInfo *ci, bool md5sum) diff --git a/src/settings.cpp b/src/settings.cpp --- a/src/settings.cpp +++ b/src/settings.cpp @@ -969,7 +969,8 @@ static GRFConfig *GRFLoadConfig(IniFile for (item = group->item; item != nullptr; item = item->next) { GRFConfig *c = nullptr; - uint8 grfid_buf[4], md5sum[16]; + uint8 grfid_buf[4]; + MD5Hash md5sum; const char *filename = item->name.c_str(); bool has_grfid = false; bool has_md5sum = false; @@ -978,12 +979,12 @@ static GRFConfig *GRFLoadConfig(IniFile has_grfid = DecodeHexText(filename, grfid_buf, lengthof(grfid_buf)); if (has_grfid) { filename += 1 + 2 * lengthof(grfid_buf); - has_md5sum = DecodeHexText(filename, md5sum, lengthof(md5sum)); - if (has_md5sum) filename += 1 + 2 * lengthof(md5sum); + has_md5sum = DecodeHexText(filename, md5sum.data(), md5sum.size()); + if (has_md5sum) filename += 1 + 2 * md5sum.size(); uint32 grfid = grfid_buf[0] | (grfid_buf[1] << 8) | (grfid_buf[2] << 16) | (grfid_buf[3] << 24); if (has_md5sum) { - const GRFConfig *s = FindGRFConfig(grfid, FGCM_EXACT, md5sum); + const GRFConfig *s = FindGRFConfig(grfid, FGCM_EXACT, &md5sum); if (s != nullptr) c = new GRFConfig(*s); } if (c == nullptr && !FioCheckFileExists(filename, NEWGRF_DIR)) { diff --git a/src/string.cpp b/src/string.cpp --- a/src/string.cpp +++ b/src/string.cpp @@ -618,9 +618,9 @@ int CDECL seprintf(char *str, const char * @param md5sum the md5sum itself * @return the string representation of the md5sum. */ -std::string MD5SumToString(const uint8 md5sum[16]) +std::string MD5SumToString(const MD5Hash &md5sum) { - return FormatArrayAsHex({md5sum, 16}); + return FormatArrayAsHex(md5sum); } diff --git a/src/string_func.h b/src/string_func.h --- a/src/string_func.h +++ b/src/string_func.h @@ -29,6 +29,7 @@ #include "core/bitmath_func.hpp" #include "core/span_type.hpp" #include "string_type.h" +#include "3rdparty/md5/md5.h" char *strecat(char *dst, const char *src, const char *last) NOACCESS(3); char *strecpy(char *dst, const char *src, const char *last) NOACCESS(3); @@ -90,7 +91,7 @@ static inline size_t ttd_strnlen(const c return t - str; } -std::string MD5SumToString(const uint8 md5sum[16]); +std::string MD5SumToString(const MD5Hash &md5sum); bool IsValidChar(WChar key, CharSetFilter afilter);