Use secure versions of CRT getenv etc. when compiling with MSVC

This commit is contained in:
rdb 2022-03-01 12:47:31 +01:00
parent dc05889be2
commit 21377c8de5
7 changed files with 90 additions and 12 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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));