From 21377c8de5a97b0665135938f11132145520da7c Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 1 Mar 2022 12:47:31 +0100 Subject: [PATCH] Use secure versions of CRT getenv etc. when compiling with MSVC --- dtool/src/dtoolutil/executionEnvironment.cxx | 45 +++++++++++++++++--- dtool/src/dtoolutil/filename.cxx | 12 ++++++ dtool/src/dtoolutil/panda_getopt_impl.cxx | 12 +++++- dtool/src/dtoolutil/pfstreamBuf.cxx | 7 ++- dtool/src/interrogate/interrogate.cxx | 7 +++ panda/src/downloadertools/multify.cxx | 7 +++ panda/src/express/zipArchive.cxx | 12 ++++++ 7 files changed, 90 insertions(+), 12 deletions(-) diff --git a/dtool/src/dtoolutil/executionEnvironment.cxx b/dtool/src/dtoolutil/executionEnvironment.cxx index 4214505faf..d39ae70a4e 100644 --- a/dtool/src/dtoolutil/executionEnvironment.cxx +++ b/dtool/src/dtoolutil/executionEnvironment.cxx @@ -259,10 +259,14 @@ ns_has_environment_variable(const string &var) const { return true; } -#ifndef PREREAD_ENVIRONMENT - return getenv(var.c_str()) != nullptr; -#else +#ifdef PREREAD_ENVIRONMENT return false; +#elif defined(_MSC_VER) + size_t size = 0; + getenv_s(&size, nullptr, 0, var.c_str()); + return size != 0; +#else + return getenv(var.c_str()) != nullptr; #endif } @@ -301,11 +305,24 @@ ns_get_environment_variable(const string &var) const { } #ifndef PREREAD_ENVIRONMENT +#ifdef _MSC_VER + std::string value(128, '\0'); + size_t size = value.size(); + while (getenv_s(&size, &value[0], size, var.c_str()) == ERANGE) { + value.resize(size); + } + if (size != 0) { + // Strip off the trailing null byte. + value.resize(size - 1); + return value; + } +#else const char *def = getenv(var.c_str()); if (def != nullptr) { return def; } #endif +#endif #ifdef _WIN32 // On Windows only, we also simulate several standard folder names as @@ -414,14 +431,15 @@ ns_get_environment_variable(const string &var) const { void ExecutionEnvironment:: ns_set_environment_variable(const string &var, const string &value) { _variables[var] = value; + +#ifdef _MSC_VER + _putenv_s(var.c_str(), value.c_str()); +#else string putstr = var + "=" + value; // putenv() requires us to malloc a new C-style string. char *put = (char *)malloc(putstr.length() + 1); strcpy(put, putstr.c_str()); -#ifdef _MSC_VER - _putenv(put); -#else putenv(put); #endif } @@ -447,12 +465,27 @@ ns_clear_shadow(const string &var) { #ifdef PREREAD_ENVIRONMENT // Now we have to replace the value in the table. +#ifdef _MSC_VER + std::string value(128, '\0'); + size_t size = value.size(); + while (getenv_s(&size, &value[0], size, var.c_str()) == ERANGE) { + value.resize(size); + } + if (size != 0) { + // Strip off the trailing null byte. + value.resize(size - 1); + (*vi).second = std::move(value); + } else { + _variables.erase(vi); + } +#else const char *def = getenv(var.c_str()); if (def != nullptr) { (*vi).second = def; } else { _variables.erase(vi); } +#endif #endif // PREREAD_ENVIRONMENT } diff --git a/dtool/src/dtoolutil/filename.cxx b/dtool/src/dtoolutil/filename.cxx index c51119c54d..f676220158 100644 --- a/dtool/src/dtoolutil/filename.cxx +++ b/dtool/src/dtoolutil/filename.cxx @@ -152,10 +152,22 @@ get_panda_root() { if (panda_root == nullptr) { panda_root = new string; + +#ifdef _MSC_VER + char *envvar = nullptr; + size_t size = 0; + while (getenv_s(&size, envvar, size, "PANDA_ROOT") == ERANGE) { + envvar = (char *)alloca(size); + } + if (size != 0) { + (*panda_root) = front_to_back_slash(envvar); + } +#else const char *envvar = getenv("PANDA_ROOT"); if (envvar != nullptr) { (*panda_root) = front_to_back_slash(envvar); } +#endif // Ensure the string ends in a backslash. If PANDA_ROOT is empty or // undefined, this function must return a single backslash--not an empty diff --git a/dtool/src/dtoolutil/panda_getopt_impl.cxx b/dtool/src/dtoolutil/panda_getopt_impl.cxx index 2779a7906a..f2ca4ed65c 100644 --- a/dtool/src/dtoolutil/panda_getopt_impl.cxx +++ b/dtool/src/dtoolutil/panda_getopt_impl.cxx @@ -140,6 +140,10 @@ PandaGetopt(int argc, char *const argv[], const char *optstring, // _options[0] is used for invalid characters. _options.push_back(Option('?', no_argument)); +#ifdef _MSC_VER + size_t size; +#endif + if (optstring[0] == '-') { // RETURN_IN_ORDER: Non-option arguments (operands) are handled as if they // were the argument to an option with the value 1 ('\001'). @@ -154,8 +158,12 @@ PandaGetopt(int argc, char *const argv[], const char *optstring, // argument is reached, or when the element of argv is "--". ++optstring; _require_order = true; - - } else if (getenv("POSIXLY_CORRECT") != nullptr) { + } +#ifdef _MSC_VER + else if (getenv_s(&size, nullptr, 0, "POSIXLY_CORRECT") == 0 && size != 0) { +#else + else if (getenv("POSIXLY_CORRECT") != nullptr) { +#endif // REQUIRE_ORDER. _require_order = true; diff --git a/dtool/src/dtoolutil/pfstreamBuf.cxx b/dtool/src/dtoolutil/pfstreamBuf.cxx index a5585ee3cd..b2fcf2838e 100644 --- a/dtool/src/dtoolutil/pfstreamBuf.cxx +++ b/dtool/src/dtoolutil/pfstreamBuf.cxx @@ -331,8 +331,9 @@ open_pipe(const string &cmd) { // Both WinExec() and CreateProcess() want a non-const char pointer. Maybe // they change it, and maybe they don't. I'm not taking chances. - char *cmdline = new char[cmd.length() + 1]; - strcpy(cmdline, cmd.c_str()); + char *cmdline = (char *)alloca(cmd.size() + 1); + memcpy(cmdline, cmd.data(), cmd.size()); + cmdline[cmd.size()] = 0; // We should be using CreateProcess() instead of WinExec(), but that seems // to be likely to crash Win98. WinExec() seems better behaved, and it's @@ -345,8 +346,6 @@ open_pipe(const string &cmd) { // Don't return yet, since we still need to clean up. } - delete[] cmdline; - // Now restore our own stdout, up here in the parent process. if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) { #ifndef NDEBUG diff --git a/dtool/src/interrogate/interrogate.cxx b/dtool/src/interrogate/interrogate.cxx index 8a9d9fe113..0c15cb4a3a 100644 --- a/dtool/src/interrogate/interrogate.cxx +++ b/dtool/src/interrogate/interrogate.cxx @@ -547,8 +547,15 @@ main(int argc, char **argv) { // We allow overriding this value by setting SOURCE_DATE_EPOCH to support // reproducible builds. int file_identifier; +#ifdef _MSC_VER + char source_date_epoch[64]; + size_t source_date_epoch_size = 0; + if (getenv_s(&source_date_epoch_size, source_date_epoch, + sizeof(source_date_epoch), "SOURCE_DATE_EPOCH"), source_date_epoch_size > 1) { +#else const char *source_date_epoch = getenv("SOURCE_DATE_EPOCH"); if (source_date_epoch != nullptr && source_date_epoch[0] != 0) { +#endif file_identifier = atoi(source_date_epoch); } else { file_identifier = time(nullptr); diff --git a/panda/src/downloadertools/multify.cxx b/panda/src/downloadertools/multify.cxx index d649992b40..da3789d3cb 100644 --- a/panda/src/downloadertools/multify.cxx +++ b/panda/src/downloadertools/multify.cxx @@ -792,8 +792,15 @@ main(int argc, char **argv) { } } +#ifdef _MSC_VER + char source_date_epoch_str[64]; + size_t source_date_epoch_size = 0; + if (getenv_s(&source_date_epoch_size, source_date_epoch_str, + sizeof(source_date_epoch_str), "SOURCE_DATE_EPOCH"), source_date_epoch_size > 1) { +#else const char *source_date_epoch_str = getenv("SOURCE_DATE_EPOCH"); if (source_date_epoch_str != nullptr && source_date_epoch_str[0] != 0) { +#endif source_date_epoch = (time_t)strtoll(source_date_epoch_str, nullptr, 10); } diff --git a/panda/src/express/zipArchive.cxx b/panda/src/express/zipArchive.cxx index 64cc2ec497..fb232a7b40 100644 --- a/panda/src/express/zipArchive.cxx +++ b/panda/src/express/zipArchive.cxx @@ -2018,7 +2018,13 @@ write_index(std::ostream &write, streampos &fpos) { if (_timestamp > dos_epoch) { // Convert from UNIX timestamp to DOS/FAT timestamp. +#ifdef _MSC_VER + struct tm time_data; + struct tm *time = &time_data; + localtime_s(time, &_timestamp); +#else struct tm *time = localtime(&_timestamp); +#endif writer.add_uint16((time->tm_sec >> 1) | (time->tm_min << 5) | (time->tm_hour << 11)); @@ -2120,7 +2126,13 @@ write_header(std::ostream &write, std::streampos &fpos) { if (_timestamp > 315532800) { // Convert from UNIX timestamp to DOS/FAT timestamp. +#ifdef _MSC_VER + struct tm time_data; + struct tm *time = &time_data; + localtime_s(time, &_timestamp); +#else struct tm *time = localtime(&_timestamp); +#endif writer.add_uint16((time->tm_sec >> 1) | (time->tm_min << 5) | (time->tm_hour << 11));