Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit ca6c4a9

Browse files
author
Koundinya Veluri
committed
Fix loading native libraries from native search paths provided by the host
Fixed a couple of issues outside Windows regarding the directory separator char, path separator char, and absolute path determination. Fixes #1680
1 parent 125fd81 commit ca6c4a9

File tree

3 files changed

+61
-73
lines changed

3 files changed

+61
-73
lines changed

src/inc/clr/fs/path.h

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,25 @@ namespace clr
3636
class Path
3737
{
3838
public:
39+
#if !PLATFORM_UNIX
40+
static const CHAR DirectorySeparatorChar = '\\';
41+
#else // PLATFORM_UNIX
42+
static const CHAR DirectorySeparatorChar = '/';
43+
#endif
44+
45+
#if !PLATFORM_UNIX
46+
static const CHAR PathSeparatorChar = ';';
47+
#else // PLATFORM_UNIX
48+
static const CHAR PathSeparatorChar = ':';
49+
#endif // !PLATFORM_UNIX
50+
51+
#if !PLATFORM_UNIX
52+
static const CHAR VolumeSeparatorChar = ':';
53+
#else // PLATFORM_UNIX
54+
static const CHAR VolumeSeparatorChar = '/';
55+
#endif // !PLATFORM_UNIX
56+
57+
public:
3958
//-----------------------------------------------------------------------------------------
4059
static inline bool
4160
Exists(
@@ -54,36 +73,41 @@ namespace clr
5473
return wcscmp(wzPath, LONG_FORMAT_PATH_PREFIX) == 0;
5574
}
5675

57-
//-----------------------------------------------------------------------------------------
58-
static inline bool
59-
HasUncPrefix(LPCWSTR wzPath)
60-
{
61-
_ASSERTE(!clr::str::IsNullOrEmpty(wzPath)); // Must check this first.
62-
return wzPath[0] != W('\0') && wzPath[0] == W('\\')
63-
&& wzPath[1] != W('\0') && wzPath[1] == W('\\')
64-
&& wzPath[2] != W('\0') && wzPath[2] != W('?');
65-
}
66-
67-
//-----------------------------------------------------------------------------------------
68-
static inline bool
69-
HasDrivePrefix(LPCWSTR wzPath)
70-
{
71-
_ASSERTE(!clr::str::IsNullOrEmpty(wzPath)); // Must check this first.
72-
return wzPath[0] != W('\0')
73-
&& wzPath[1] != W('\0') && wzPath[1] == W(':')
74-
&& ((wzPath[0] >= W('a') && wzPath[0] <= W('z')) ||
75-
(wzPath[0] >= W('A') && wzPath[0] <= W('Z')));
76-
}
77-
7876
//-----------------------------------------------------------------------------------------
7977
// Returns true if wzPath represents a relative path.
8078
static inline bool
8179
IsRelative(LPCWSTR wzPath)
8280
{
83-
_ASSERTE(!clr::str::IsNullOrEmpty(wzPath)); // Must check this first.
84-
return !HasLongFormatPrefix(wzPath)
85-
&& !HasUncPrefix(wzPath)
86-
&& (!HasDrivePrefix(wzPath) || wzPath[2] != W('\\'));
81+
_ASSERTE(wzPath != nullptr);
82+
83+
// Similar to System.IO.Path.IsRelative()
84+
#if PLATFORM_UNIX
85+
if(wzPath[0] == VolumeSeparatorChar)
86+
{
87+
return false;
88+
}
89+
#else
90+
// Check for a paths like "C:\..." or "\\...". Additional notes:
91+
// - "\\?\..." - long format paths are considered as absolute paths due to the "\\" prefix
92+
// - "\..." - these paths are relative, as they depend on the current drive
93+
// - "C:..." and not "C:\..." - these paths are relative, as they depend on the current directory for drive C
94+
if (wzPath[0] != W('\0') &&
95+
wzPath[1] == VolumeSeparatorChar &&
96+
wzPath[2] == DirectorySeparatorChar &&
97+
(
98+
(wzPath[0] >= W('A') && wzPath[0] <= W('Z')) ||
99+
(wzPath[0] >= W('a') && wzPath[0] <= W('z'))
100+
))
101+
{
102+
return false;
103+
}
104+
if(wzPath[0] == DirectorySeparatorChar && wzPath[1] == DirectorySeparatorChar)
105+
{
106+
return false;
107+
}
108+
#endif
109+
110+
return true;
87111
}
88112

89113
//-----------------------------------------------------------------------------------------
@@ -105,7 +129,8 @@ namespace clr
105129
size_t cchBuf = *pcchBuffer;
106130

107131
IfFailRet(StringCchCopyExW(wzBuf, cchBuf, wzPathLeft, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE));
108-
IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzBuf[-1] == W('\\') ? W("") : W("\\"), &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE));
132+
const WCHAR directorySeparatorWString[] = {DirectorySeparatorChar, W('\0')};
133+
IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzBuf[-1] == DirectorySeparatorChar ? W("") : directorySeparatorWString, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE));
109134
IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzPathRight, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE));
110135

111136
return S_OK;

src/vm/appdomainnative.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include "../binder/inc/clrprivbindercoreclr.h"
3232
#endif
3333

34+
#include "clr/fs/path.h"
35+
using namespace clr::fs;
3436

3537
//************************************************************************
3638
inline AppDomain *AppDomainNative::ValidateArg(APPDOMAINREF pThis)
@@ -1578,7 +1580,7 @@ void QCALLTYPE AppDomainNative::SetNativeDllSearchDirectories(__in_z LPCWSTR wsz
15781580
while (itr != end)
15791581
{
15801582
start = itr;
1581-
BOOL found = sDirectories.Find(itr, W(';'));
1583+
BOOL found = sDirectories.Find(itr, Path::PathSeparatorChar);
15821584
if (!found)
15831585
{
15841586
itr = end;
@@ -1595,9 +1597,9 @@ void QCALLTYPE AppDomainNative::SetNativeDllSearchDirectories(__in_z LPCWSTR wsz
15951597

15961598
if (len > 0)
15971599
{
1598-
if (qualifiedPath[len-1]!='\\')
1600+
if (qualifiedPath[len - 1] != Path::DirectorySeparatorChar)
15991601
{
1600-
qualifiedPath.Append('\\');
1602+
qualifiedPath.Append(Path::DirectorySeparatorChar);
16011603
}
16021604

16031605
NewHolder<SString> stringHolder (new SString(qualifiedPath));

src/vm/dllimport.cpp

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
#include "fxretarget.h"
5757
#endif
5858

59+
#include "clr/fs/path.h"
60+
using namespace clr::fs;
61+
5962
// remove when we get an updated SDK
6063
#define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100
6164
#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000
@@ -6144,48 +6147,6 @@ LPVOID NDirect::NDirectGetEntryPoint(NDirectMethodDesc *pMD, HINSTANCE hMod)
61446147
RETURN pMD->FindEntryPoint(hMod);
61456148
}
61466149

6147-
static BOOL AbsolutePath(LPCWSTR wszLibName)
6148-
{
6149-
CONTRACTL
6150-
{
6151-
NOTHROW;
6152-
GC_NOTRIGGER;
6153-
MODE_ANY;
6154-
6155-
PRECONDITION(CheckPointer(wszLibName));
6156-
}
6157-
CONTRACTL_END;
6158-
6159-
// check for UNC or a drive
6160-
WCHAR* ptr = (WCHAR*) wszLibName;
6161-
WCHAR* start = ptr;
6162-
6163-
// Check for UNC path
6164-
while(*ptr)
6165-
{
6166-
if(*ptr != W('\\'))
6167-
break;
6168-
ptr++;
6169-
}
6170-
6171-
if((ptr - wszLibName) == 2)
6172-
return TRUE;
6173-
else
6174-
{
6175-
// Check to see if there is a colon indicating a drive or protocal
6176-
for(ptr = start; *ptr; ptr++)
6177-
{
6178-
if(*ptr == W(':'))
6179-
break;
6180-
}
6181-
if(*ptr != NULL)
6182-
return TRUE;
6183-
}
6184-
6185-
// We did not find a UNC/drive/protocol path
6186-
return FALSE;
6187-
}
6188-
61896150
VOID NDirectMethodDesc::SetNDirectTarget(LPVOID pTarget)
61906151
{
61916152
CONTRACTL
@@ -7078,7 +7039,7 @@ HINSTANCE NDirect::LoadLibraryModule( NDirectMethodDesc * pMD, LoadLibErrorTrack
70787039
}
70797040
#endif // !FEATURE_CORECLR
70807041

7081-
if (AbsolutePath(wszLibName))
7042+
if (!Path::IsRelative(wszLibName))
70827043
{
70837044
DWORD flags = loadWithAlteredPathFlags;
70847045
if ((dllImportSearchPathFlag & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) != 0)
@@ -7173,7 +7134,7 @@ HINSTANCE NDirect::LoadLibraryModule( NDirectMethodDesc * pMD, LoadLibErrorTrack
71737134
{
71747135
SString qualifiedPath(*(i.GetPath()));
71757136
qualifiedPath.Append(wszLibName);
7176-
if (AbsolutePath(qualifiedPath))
7137+
if (!Path::IsRelative(qualifiedPath))
71777138
{
71787139
hmod = LocalLoadLibraryHelper(qualifiedPath, loadWithAlteredPathFlags, pErrorTracker);
71797140
}

0 commit comments

Comments
 (0)