Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use multibyte character path for bundle_probe #44466

Merged
merged 1 commit into from
Nov 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscoree/unixinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ int coreclr_initialize(

if (bundleProbe != nullptr)
{
static Bundle bundle(StringToUnicode(exePath), bundleProbe);
static Bundle bundle(exePath, bundleProbe);
Bundle::AppBundle = &bundle;
}

Expand Down
9 changes: 5 additions & 4 deletions src/coreclr/src/inc/bundle.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,28 @@ struct BundleFileLocation
bool IsValid() const { LIMITED_METHOD_CONTRACT; return Offset != 0; }
};

typedef bool(__stdcall BundleProbe)(LPCWSTR, INT64*, INT64*);
typedef bool(__stdcall BundleProbe)(LPCSTR, INT64*, INT64*);

class Bundle
{
public:
Bundle(LPCWSTR bundlePath, BundleProbe *probe);
BundleFileLocation Probe(LPCWSTR path, bool pathIsBundleRelative = false) const;
Bundle(LPCSTR bundlePath, BundleProbe *probe);
BundleFileLocation Probe(const SString& path, bool pathIsBundleRelative = false) const;

const SString &Path() const { LIMITED_METHOD_CONTRACT; return m_path; }
const SString &BasePath() const { LIMITED_METHOD_CONTRACT; return m_basePath; }

static Bundle* AppBundle; // The BundleInfo for the current app, initialized by coreclr_initialize.
static bool AppIsBundle() { LIMITED_METHOD_CONTRACT; return AppBundle != nullptr; }
static BundleFileLocation ProbeAppBundle(LPCWSTR path, bool pathIsBundleRelative = false);
static BundleFileLocation ProbeAppBundle(const SString& path, bool pathIsBundleRelative = false);

private:

SString m_path; // The path to single-file executable
BundleProbe *m_probe;

SString m_basePath; // The prefix to denote a path within the bundle
COUNT_T m_basePathLength;
};

#endif // _BUNDLE_H_
Expand Down
29 changes: 15 additions & 14 deletions src/coreclr/src/vm/bundle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,26 @@ const SString &BundleFileLocation::Path() const
return Bundle::AppBundle->Path();
}

Bundle::Bundle(LPCWSTR bundlePath, BundleProbe *probe)
Bundle::Bundle(LPCSTR bundlePath, BundleProbe *probe)
{
STANDARD_VM_CONTRACT;

_ASSERTE(probe != nullptr);

m_path.Set(bundlePath);
m_path.SetUTF8(bundlePath);
m_probe = probe;

// The bundle-base path is the directory containing the single-file bundle.
// When the Probe() function searches within the bundle, it masks out the basePath from the assembly-path (if found).

LPCWSTR pos = wcsrchr(bundlePath, DIRECTORY_SEPARATOR_CHAR_W);
LPCSTR pos = strrchr(bundlePath, DIRECTORY_SEPARATOR_CHAR_A);
_ASSERTE(pos != nullptr);
size_t baseLen = pos - bundlePath + 1; // Include DIRECTORY_SEPARATOR_CHAR_W in m_basePath
m_basePath.Set(bundlePath, (COUNT_T)baseLen);
size_t baseLen = pos - bundlePath + 1; // Include DIRECTORY_SEPARATOR_CHAR_A in m_basePath
m_basePath.SetUTF8(bundlePath, (COUNT_T)baseLen);
m_basePathLength = (COUNT_T)baseLen;
}

BundleFileLocation Bundle::Probe(LPCWSTR path, bool pathIsBundleRelative) const
BundleFileLocation Bundle::Probe(const SString& path, bool pathIsBundleRelative) const
{
STANDARD_VM_CONTRACT;

Expand All @@ -59,17 +60,18 @@ BundleFileLocation Bundle::Probe(LPCWSTR path, bool pathIsBundleRelative) const
// Bundle.Probe("path/to/exe/lib.dll") => m_probe("lib.dll")
// Bundle.Probe("path/to/exe/and/some/more/lib.dll") => m_probe("and/some/more/lib.dll")

StackScratchBuffer scratchBuffer;
LPCSTR utf8Path(path.GetUTF8(scratchBuffer));

if (!pathIsBundleRelative)
{
size_t baseLen = m_basePath.GetCount();

#ifdef TARGET_UNIX
if (wcsncmp(m_basePath, path, baseLen) == 0)
if (wcsncmp(m_basePath, path, m_basePath.GetCount()) == 0)
am11 marked this conversation as resolved.
Show resolved Hide resolved
#else
if (_wcsnicmp(m_basePath, path, baseLen) == 0)
if (_wcsnicmp(m_basePath, path, m_basePath.GetCount()) == 0)
#endif // TARGET_UNIX
{
path += baseLen; // m_basePath includes count for DIRECTORY_SEPARATOR_CHAR_W
utf8Path += m_basePathLength; // m_basePath includes count for DIRECTORY_SEPARATOR_CHAR_W
}
else
{
Expand All @@ -78,15 +80,14 @@ BundleFileLocation Bundle::Probe(LPCWSTR path, bool pathIsBundleRelative) const
}
}

m_probe(path, &loc.Offset, &loc.Size);
m_probe(utf8Path, &loc.Offset, &loc.Size);

return loc;
}

BundleFileLocation Bundle::ProbeAppBundle(LPCWSTR path, bool pathIsBundleRelative)
BundleFileLocation Bundle::ProbeAppBundle(const SString& path, bool pathIsBundleRelative)
{
STANDARD_VM_CONTRACT;

return AppIsBundle() ? AppBundle->Probe(path, pathIsBundleRelative) : BundleFileLocation::Invalid();
}

3 changes: 0 additions & 3 deletions src/installer/corehost/cli/hostmisc/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ namespace pal
inline const char_t* strerror(int errnum) { return ::_wcserror(errnum); }

bool pal_utf8string(const string_t& str, std::vector<char>* out);
bool utf8_palstring(const std::string& str, string_t* out);
bool pal_clrstring(const string_t& str, std::vector<char>* out);
bool clr_palstring(const char* cstr, string_t* out);

Expand Down Expand Up @@ -223,7 +222,6 @@ namespace pal
inline const char_t* strerror(int errnum) { return ::strerror(errnum); }

inline bool pal_utf8string(const string_t& str, std::vector<char>* out) { out->assign(str.begin(), str.end()); out->push_back('\0'); return true; }
inline bool utf8_palstring(const std::string& str, string_t* out) { out->assign(str); return true; }
inline bool pal_clrstring(const string_t& str, std::vector<char>* out) { return pal_utf8string(str, out); }
inline bool clr_palstring(const char* cstr, string_t* out) { out->assign(cstr); return true; }

Expand Down Expand Up @@ -305,7 +303,6 @@ namespace pal
bool get_default_bundle_extraction_base_dir(string_t& extraction_dir);

int xtoi(const char_t* input);
bool unicode_palstring(const char16_t* str, pal::string_t* out);

bool get_loaded_library(const char_t *library_name, const char *symbol_name, /*out*/ dll_t *dll, /*out*/ string_t *path);
bool load_library(const string_t* path, dll_t* dll);
Expand Down
11 changes: 0 additions & 11 deletions src/installer/corehost/cli/hostmisc/pal.unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include <fnmatch.h>
#include <ctime>
#include <locale>
#include <codecvt>
#include <pwd.h>
#include "config.h"

Expand Down Expand Up @@ -266,16 +265,6 @@ int pal::xtoi(const char_t* input)
return atoi(input);
}

bool pal::unicode_palstring(const char16_t* str, pal::string_t* out)
{
out->clear();

std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> conversion;
out->assign(conversion.to_bytes(str));

return true;
}

bool pal::is_path_rooted(const pal::string_t& path)
{
return path.front() == '/';
Expand Down
12 changes: 0 additions & 12 deletions src/installer/corehost/cli/hostmisc/pal.windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#include <cassert>
#include <locale>
#include <codecvt>
#include <ShlObj.h>
#include <ctime>

Expand Down Expand Up @@ -623,11 +622,6 @@ static bool wchar_convert_helper(DWORD code_page, const char* cstr, int len, pal
return ::MultiByteToWideChar(code_page, 0, cstr, len, &(*out)[0], out->size()) != 0;
}

bool pal::utf8_palstring(const std::string& str, pal::string_t* out)
{
return wchar_convert_helper(CP_UTF8, &str[0], str.size(), out);
}

bool pal::pal_utf8string(const pal::string_t& str, std::vector<char>* out)
{
out->clear();
Expand All @@ -652,12 +646,6 @@ bool pal::clr_palstring(const char* cstr, pal::string_t* out)
return wchar_convert_helper(CP_UTF8, cstr, ::strlen(cstr), out);
}

bool pal::unicode_palstring(const char16_t* str, pal::string_t* out)
{
out->assign((const wchar_t *)str);
return true;
}

// Return if path is valid and file exists, return true and adjust path as appropriate.
bool pal::realpath(string_t* path, bool skip_error_logging)
{
Expand Down
15 changes: 2 additions & 13 deletions src/installer/corehost/cli/hostpolicy/hostpolicy_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,7 @@ namespace
// This function is an API exported to the runtime via the BUNDLE_PROBE property.
// This function used by the runtime to probe for bundled assemblies
// This function assumes that the currently executing app is a single-file bundle.
//
// bundle_probe recieves its path argument as cha16_t* instead of pal::char_t*, because:
// * The host uses Unicode strings on Windows and UTF8 strings on Unix
// * The runtime uses Unicode strings on all platforms
// * Using a unicode encoded path presents a uniform interface to the runtime
// and minimizes the number if Unicode <-> UTF8 conversions necessary.
//
// The unicode char type is char16_t* instead of whcar_t*, because:
// * wchar_t is 16-bit encoding on Windows while it is 32-bit encoding on most Unix systems
// * The runtime uses 16-bit encoded unicode characters.

bool STDMETHODCALLTYPE bundle_probe(const char16_t* path, int64_t* offset, int64_t* size)
bool STDMETHODCALLTYPE bundle_probe(const char* path, int64_t* offset, int64_t* size)
{
if (path == nullptr)
{
Expand All @@ -43,7 +32,7 @@ namespace

pal::string_t file_path;

if (!pal::unicode_palstring(path, &file_path))
if (!pal::clr_palstring(path, &file_path))
{
trace::warning(_X("Failure probing contents of the application bundle."));
trace::warning(_X("Failed to convert path [%ls] to UTF8"), path);
Expand Down
4 changes: 2 additions & 2 deletions src/installer/corehost/corehost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ bool is_exe_enabled_for_execution(pal::string_t* app_dll)
static const char hi_part[] = EMBED_HASH_HI_PART_UTF8;
static const char lo_part[] = EMBED_HASH_LO_PART_UTF8;

std::string binding(&embed[0]);
if (!pal::utf8_palstring(binding, app_dll))
if (!pal::clr_palstring(embed, app_dll))
{
trace::error(_X("The managed DLL bound to this executable could not be retrieved from the executable image."));
return false;
Expand All @@ -65,6 +64,7 @@ bool is_exe_enabled_for_execution(pal::string_t* app_dll)
size_t hi_len = (sizeof(hi_part) / sizeof(hi_part[0])) - 1;
size_t lo_len = (sizeof(lo_part) / sizeof(lo_part[0])) - 1;

std::string binding(&embed[0]);
if ((binding.size() >= (hi_len + lo_len)) &&
binding.compare(0, hi_len, &hi_part[0]) == 0 &&
binding.compare(hi_len, lo_len, &lo_part[0]) == 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static class Program
// The bundle-probe callback is only called from native code in the product
// Therefore the type on this test is adjusted to circumvent the failure.
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate byte BundleProbeDelegate([MarshalAs(UnmanagedType.LPWStr)] string path, IntPtr size, IntPtr offset);
public delegate byte BundleProbeDelegate([MarshalAs(UnmanagedType.LPUTF8Str)] string path, IntPtr size, IntPtr offset);

unsafe static bool Probe(BundleProbeDelegate bundleProbe, string path, bool isExpected)
{
Expand Down