* fix crash due to invalid usage of union in steam_remote_storage

* fix invalid overlapping of data in steam_remote_storage due to invalid usage of union
This commit is contained in:
a 2024-08-02 04:40:25 +03:00
parent 3369c046a9
commit c61294bdcd
2 changed files with 38 additions and 39 deletions

View File

@ -36,30 +36,29 @@ struct Stream_Write {
}; };
struct Downloaded_File { struct Downloaded_File {
// --- these are needed due to the usage of union enum class DownloadSource {
Downloaded_File();
~Downloaded_File();
// ---
enum DownloadSource {
AfterFileShare, // attempted download after a call to Steam_Remote_Storage::FileShare() AfterFileShare, // attempted download after a call to Steam_Remote_Storage::FileShare()
AfterSendQueryUGCRequest, // attempted download after a call to Steam_UGC::SendQueryUGCRequest() AfterSendQueryUGCRequest, // attempted download after a call to Steam_UGC::SendQueryUGCRequest()
FromUGCDownloadToLocation, // attempted download via Steam_Remote_Storage::UGCDownloadToLocation() FromUGCDownloadToLocation, // attempted download via Steam_Remote_Storage::UGCDownloadToLocation()
} source{}; };
private:
DownloadSource source;
public:
Downloaded_File(DownloadSource src);
DownloadSource get_source() const;
// *** used in any case // *** used in any case
std::string file{}; std::string file{};
uint64 total_size{}; uint64 total_size{};
// put any additional data needed by other sources here // *** used when source = AfterSendQueryUGCRequest and FromUGCDownloadToLocation
Ugc_Remote_Storage_Bridge::QueryInfo mod_query_info{};
union {
// *** used when source = SendQueryUGCRequest only
Ugc_Remote_Storage_Bridge::QueryInfo mod_query_info;
// *** used when source = FromUGCDownloadToLocation only // *** used when source = FromUGCDownloadToLocation only
std::string download_to_location_fullpath; std::string download_to_location_fullpath{};
};
}; };

View File

@ -18,14 +18,13 @@
#include "dll/steam_remote_storage.h" #include "dll/steam_remote_storage.h"
Downloaded_File::Downloaded_File() Downloaded_File::Downloaded_File(DownloadSource src)
:source(src)
{ }
Downloaded_File::DownloadSource Downloaded_File::get_source() const
{ {
return source;
}
Downloaded_File::~Downloaded_File()
{
} }
static void copy_file(const std::string &src_filepath, const std::string &dst_filepath) static void copy_file(const std::string &src_filepath, const std::string &dst_filepath)
@ -421,9 +420,10 @@ SteamAPICall_t Steam_Remote_Storage::UGCDownload( UGCHandle_t hContent, uint32 u
shared_files[hContent].copy(data.m_pchFileName, sizeof(data.m_pchFileName) - 1); shared_files[hContent].copy(data.m_pchFileName, sizeof(data.m_pchFileName) - 1);
downloaded_files[hContent].source = Downloaded_File::DownloadSource::AfterFileShare; auto [ele_itr, _] = downloaded_files.insert_or_assign(hContent, Downloaded_File::DownloadSource::AfterFileShare);
downloaded_files[hContent].file = shared_files[hContent]; auto &ele = ele_itr->second;
downloaded_files[hContent].total_size = data.m_nSizeInBytes; ele.file = shared_files[hContent];
ele.total_size = data.m_nSizeInBytes;
} else if (auto query_res = ugc_bridge->get_ugc_query_result(hContent)) { } else if (auto query_res = ugc_bridge->get_ugc_query_result(hContent)) {
auto mod = settings->getMod(query_res.value().mod_id); auto mod = settings->getMod(query_res.value().mod_id);
auto &mod_name = query_res.value().is_primary_file auto &mod_name = query_res.value().is_primary_file
@ -441,11 +441,11 @@ SteamAPICall_t Steam_Remote_Storage::UGCDownload( UGCHandle_t hContent, uint32 u
mod_name.copy(data.m_pchFileName, sizeof(data.m_pchFileName) - 1); mod_name.copy(data.m_pchFileName, sizeof(data.m_pchFileName) - 1);
downloaded_files[hContent].source = Downloaded_File::DownloadSource::AfterSendQueryUGCRequest; auto [ele_itr, _] = downloaded_files.insert_or_assign(hContent, Downloaded_File::DownloadSource::AfterSendQueryUGCRequest);
downloaded_files[hContent].file = mod_name; auto &ele = ele_itr->second;
downloaded_files[hContent].total_size = mod_size; ele.file = mod_name;
ele.total_size = mod_size;
downloaded_files[hContent].mod_query_info = query_res.value(); ele.mod_query_info = query_res.value();
} else { } else {
data.m_eResult = k_EResultFileNotFound; //TODO: not sure if this is the right result data.m_eResult = k_EResultFileNotFound; //TODO: not sure if this is the right result
@ -512,7 +512,7 @@ int32 Steam_Remote_Storage::UGCRead( UGCHandle_t hContent, void *pvData, int32 c
Downloaded_File &dwf = f_itr->second; Downloaded_File &dwf = f_itr->second;
// depending on the download source, we have to decide where to grab the content/data // depending on the download source, we have to decide where to grab the content/data
switch (dwf.source) switch (dwf.get_source())
{ {
case Downloaded_File::DownloadSource::AfterFileShare: { case Downloaded_File::DownloadSource::AfterFileShare: {
PRINT_DEBUG(" source = AfterFileShare '%s'", dwf.file.c_str()); PRINT_DEBUG(" source = AfterFileShare '%s'", dwf.file.c_str());
@ -523,14 +523,14 @@ int32 Steam_Remote_Storage::UGCRead( UGCHandle_t hContent, void *pvData, int32 c
case Downloaded_File::DownloadSource::AfterSendQueryUGCRequest: case Downloaded_File::DownloadSource::AfterSendQueryUGCRequest:
case Downloaded_File::DownloadSource::FromUGCDownloadToLocation: { case Downloaded_File::DownloadSource::FromUGCDownloadToLocation: {
PRINT_DEBUG(" source = AfterSendQueryUGCRequest || FromUGCDownloadToLocation [%i]", (int)dwf.source); PRINT_DEBUG(" source = AfterSendQueryUGCRequest || FromUGCDownloadToLocation [%i]", (int)dwf.get_source());
auto mod = settings->getMod(dwf.mod_query_info.mod_id); auto mod = settings->getMod(dwf.mod_query_info.mod_id);
auto &mod_name = dwf.mod_query_info.is_primary_file auto &mod_name = dwf.mod_query_info.is_primary_file
? mod.primaryFileName ? mod.primaryFileName
: mod.previewFileName; : mod.previewFileName;
std::string mod_fullpath{}; std::string mod_fullpath{};
if (dwf.source == Downloaded_File::DownloadSource::AfterSendQueryUGCRequest) { if (dwf.get_source() == Downloaded_File::DownloadSource::AfterSendQueryUGCRequest) {
std::string mod_base_path = dwf.mod_query_info.is_primary_file std::string mod_base_path = dwf.mod_query_info.is_primary_file
? mod.path ? mod.path
: Local_Storage::get_game_settings_path() + "mod_images" + PATH_SEPARATOR + std::to_string(mod.id); : Local_Storage::get_game_settings_path() + "mod_images" + PATH_SEPARATOR + std::to_string(mod.id);
@ -547,7 +547,7 @@ int32 Steam_Remote_Storage::UGCRead( UGCHandle_t hContent, void *pvData, int32 c
break; break;
default: default:
PRINT_DEBUG(" unhandled download source %i", (int)dwf.source); PRINT_DEBUG(" unhandled download source %i", (int)dwf.get_source());
return -1; //TODO: is this the right return value? return -1; //TODO: is this the right return value?
break; break;
} }
@ -1134,12 +1134,12 @@ SteamAPICall_t Steam_Remote_Storage::UGCDownloadToLocation( UGCHandle_t hContent
copy_file(mod_fullpath, pchLocation); copy_file(mod_fullpath, pchLocation);
// TODO not sure about this though // TODO not sure about this though
downloaded_files[hContent].source = Downloaded_File::DownloadSource::FromUGCDownloadToLocation; auto [ele_itr, _] = downloaded_files.insert_or_assign(hContent, Downloaded_File::DownloadSource::FromUGCDownloadToLocation);
downloaded_files[hContent].file = mod_name; auto &ele = ele_itr->second;
downloaded_files[hContent].total_size = mod_size; ele.file = mod_name;
ele.total_size = mod_size;
downloaded_files[hContent].mod_query_info = query_res.value(); ele.mod_query_info = query_res.value();
downloaded_files[hContent].download_to_location_fullpath = pchLocation; ele.download_to_location_fullpath = pchLocation;
} else { } else {
data.m_eResult = k_EResultFileNotFound; //TODO: not sure if this is the right result data.m_eResult = k_EResultFileNotFound; //TODO: not sure if this is the right result